0

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

MythJuha
  • 11
  • 4
  • 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:20

2 Answers2

0

Take a look at CRC RevEng. If you can correctly identify the data that the CRC is operating on and the location of the CRC, you should be able to determine the CRC parameters. If it is a CRC.

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
  • Been trying to find out more by looking at the assembly code made by ollydbg or ida pro. But so far without luck. I have no idea which field are used and if it's even a CRC16 or a different implementation. It's a big undertaking when having no experience with assembly. – MythJuha Sep 30 '14 at 09:48
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!

MythJuha
  • 11
  • 4