2

(i've also posted this question on stackoverflow before i found out there was a specific stackexchange site for reverse engineering. My bad. Original post here: https://stackoverflow.com/questions/26095009/need-help-reverse-engineering-a-crc16)

I'm trying to connect to the Safecom TA-810 (badge/registration system) to automate the process of calculating how long employee's have worked each day. Currently this is done by:

  1. Pulling the data into the official application
  2. Printing a list of all 'registrations'
  3. Manually entering the values from the printed lists into our HR application

This is a job that can take multiple hours which we'd like to see automated. So far the official tech support has been disappointing and refused to share any details.

Using wireshark I have been capturing the UDP transmissions and have pretty much succeeded in understanding how the protocol is built up. I'm only having issues with what i suppose is a CRC field. I don't know how it is calculated (CRC type and parameters) and using which fields ...

This is how a message header looks like:

D0 07 71 BC BE 3B 00 00

D0 07 - Message type
71 BC - This i believe is the CRC
BE 3B - Some kind of session identifier. Stays the same for every message after the initial message (initial message has '00 00' as value)
00 00 - Message number. '01 00', '02 00', '03 00'

Some examples:

Header only examples
E8 03 17 FC 00 00 00 00 -> initial request (#0, no session nr)
D0 07 71 BC BE 3B 00 00 -> Initial response (#0, device sends a session nr)
4C 04 EF BF BE 3B 06 00 -> Message #6, still using the same session # as the initial response

Larger example, which has data
0B 00 07 E1 BE 3B 01 00 7E 45 78 74 65 6E 64 46 6D 74

I've also been trying to figure this out by reading the disassembled code from the original application. The screenshot below happens before the socket.sendto and seems to be related.

original application code

Any help will be extremely appreciated.

EDIT: Made some success with debugging the application using ollydbg. The CRC appears in register (reversed) EDX at the selected line in the following screenshot.

crc showing up

  • If your assembler code is related, it looks much more like it's copying the session identifier and the message number, as the [mov esi+04],ax and [mov esi+06],ax hint at those fields. Without access to a running version of the application, or at least many more examples, it's going to be quite hard to calculate the CRC. Have you ever thought of using the text-only printer driver combined with 'print to file' to get an ascii file of your records, then use a {perl,python,awk,VB,whatever scripting language} script to parse that ascii file? – Guntram Blohm Sep 30 '14 at 12:20
  • I've already implemented a similar system as the print-to-file using a built-in export function. But it still requires manual interactions to load, export, and start parsing the data. The final goal is to completely automate the process. Supplying more examples, more assembly or even getting access to a running version could be arranged if someone is willing to look into it. – MythJuha Sep 30 '14 at 12:47
  • Been making some good progress debugging the flow. Seems to be much easier than a CRC16. They are just adding all bytes. – MythJuha Sep 30 '14 at 18:19
0

I've managed to create a php script that does the CRC calculation by debugging the application using OllyDbg.

The CRC is calculated by Adding up every 2 bytes (every short). if the result is larger than a short, the 'most significant short' is added to the 'least significant short' until the result fits in a short. Finally, the CRC (short) is inverted.

I'll add my php script for completeness:

<?php
function CompareHash($telegram)
{
  $telegram = str_replace(" ", "", $telegram);
  $telegram_crc = substr($telegram, 4, 4);
  $telegram = str_replace($telegram_crc, "0000", $telegram);

  echo "Telegram: ", $telegram, ', Crc: ', $telegram_crc, ' (', hexdec($telegram_crc), ')<br />';

  $crc = 0; 
  $i = 0;

  while ($i < strlen($telegram)) 
  {
    $short = substr($telegram, $i, 4);

    if (strlen($short) < 4) $short = $short . '00';

    $crc += hexdec($short);
    $i += 4;
  }

  echo "Crc: ", $crc, ', inverse: ', ~$crc;

  // Region "truncate CRC to Int16"
  while($crc > hexdec('FFFF'))
  {
    $short = $crc & hexdec ('FFFF');

    // Region "unsigned shift right by 16 bits"
    $crc = $crc >> 16;
    $crc = $crc & hexdec ('FFFF');
    // End region

    $crc =  $short + $crc;
  }
  // End region

  // Region "invert Int16"
  $crc = ~$crc;
  $crc = $crc & hexdec ('FFFF');
  // End region

  echo ', shifted ', $crc;

  if (hexdec($telegram_crc) == $crc)
  {
    echo "<br />MATCH!!! <br />";
  }
  else
  {
    echo "<br />failed .... <br />";
  }
}

$s1_full = "E8 03 17 FC 00 00 00 00";
$s2_full = "D0 07 71 BC BE 3B 00 00";
$s3_full = "D0 07 4E D4 E1 23 00 00";
$s4_full = "D0 07 35 32 BE 3B 07 00   7E 44 65 76 69 63 65  4E    61 6D 65 3D 54 41 38 31 30 00";
$s5_full = "0B 00 39 6C BE 3B 05 00   7E 52 46 43 61 72 64  4F    6E";

CompareHash($s1_full);
CompareHash($s2_full);
CompareHash($s3_full);
CompareHash($s4_full);
CompareHash($s5_full);
?>

Thanks for the feedback!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.