Tmphack

From Lundman Wiki
Jump to: navigation, search

Hacking the Amano timecard system device. Inspecting AGX-100 and AGX-10 devices.


Firmware analysis

The device seems to communicate on port 1441.


The bytes captured are:


host <<=>> minidevice  Run 1
======================
>> port 1441 Syn?
<< Syn!

>> 04 "0900" 05     # 04 = new request ? The response seems to be, 01 stuff, 02 stuff, 03 stuff, 04 end
<< 01 "0001" 02 "09000021800000000080000000              " 03 09    # This says "8" and there are 8 records
                      # possibly read as 09 00002 18 00" as the 18 might be the 17 digits after
>> 10 30            # ACK, and clear it.
<< 04               # 04 end of data/idle/ready for next

>> 04 "0700" 05     # new request  ?
<< "0700" 04        # empty?
>> 04 "0600" 05     # get tiemcard entries
<< 01 "0001" 02 "longstringofdata" 03 0d     # lots of data, in chunks of 8 records
>> 10 30            # ACK, and clear (send 10 31 to ACK and not clear).
<< 04               # End of data

>> 04 "1901" 05     # request for 1901. Perhaps request to enter receive mode.
<< 10 30            # ACK, ready to receive?
>> 01 "0002" 02 "1911            " 03 0b   # spaces, normal 01,02,03 reply, but what is it
<< 10 31            # 10 31 ACK, with no clear
>> 04               # END of data

>> 04 "0600" 05     # again, give me 0600 again...?
<< "0600" 04        # and, now its empty (due to 10 30).
>> Fin
<< Fin


The longstring of data, appears to contain:

01
30 3030 31                    "0001"
02 
#Start of record, total of 8 records this time
3331                          "31"
3230 3038 3130 3033 3038 3436 "200810030846"   # known
3030 3031                     "0001"
3030 3030 3030 3132 3232      "0000001222"     # known
3030 3031                     "0001" 
#Start of next record
3331                          "31"
... etc ..
3030 3031                     "0001" 
# end
03 0d

Later on, around noon:

01 "0001" 02 "31"
"200810031243"
"0003"
"0000001148"
"8901"
"31"  # etc
# Follow by 8 other "0003" and "8901". We have one:
"31"
"200810031323"
"0004"
"0000001139"
"0001"

Afternoon:

"31"
"200810031602"
"0002"
"0000001469"
"0001"


// ========================================================================
//       ID # | KeyID |    Date/Time |     Status |    Special | Flag
// 0000001222 |    31 | 200812311611 |    0002    |      00    |  01
//
// Punch-IN : 0001 00 01
// Punch-OUT: 0002 00 01
// Lunch-OUT: 0003 89 01
// Lunch-IN : 0004 00 01
//
// Or perhaps Lunch-OUT should be considered "punched out from work temporarily
// with default reason set to 89, which we consider to be lunch".



host <<=>> minidevice  Run 2
======================

>> 04 "0900" 05
<< 01 "0001" 02 "09000021800000000240000000              " 03 07  # This says 24 and there are 24 records
>> 10 30
<< 04

>> 04 "0700" 05
<< "0700" 04

>> 04 "0600" 05
<< 01 "0001"
<< 02 "longstringdata" 03 0e   # 8 records
>> 10 30
<< 01 "0001" 
<< 02 "more long data" 03 0e   # 8 records
>> 10 30
<< 01 "0001" 
<< 02 "more long data" 03 04   # 8 records
>> 10 30
<< 04

>> 04 "1901" 05
<< 10 30

>> 01 "0002" 02 "1911            " 03 0b
<< 10 31
>> 04

>> 04 "0600" 05
<< "0600" 04

>> Fin
<< Fin

AGX-10

Picked up an older device for 1 yen on the auction. Seems to be of a similar design, except the main card reader has only serial, then they have bolted on a serial-to-ethernet adaptor device. When you connect to port 80 it displays the settings that it is redirecting serial 9600 to port 1441.

Testing from my code:

< sent to device
: hex of received bytes
> string of received bytes
<04"0900"05

:01 30 30 30 31 02 30 39 30 30 30 30 32 30 35 30 
:30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 30 
:30 30 31 36 20 20 20 20 20 20 20 20 20 20 03 
>'0001090000205000000000000000000016          '

:05 
>
>10 30

:04 
>
>04 "0700" 05

:01 30 30 30 31 02 30 37 30 30 32 34 32 30 30 30 
:30 30 30 30 30 30 30 30 30 30 30 20 20 20 17 
>'0001070024200000000000000   '

:05 
>

:05 
>

:04 
>
>04 "0600" 05

:30 36 30 30 04 
>'0600'
 

This makes me think:

04 OK
05 EOR EndOfRequest?
01 Part1..  02 Part2..  03 Part3  CRC
10-30 Received OK. The DATA packet is deleted when unit receives this to a 0600.
10-31 Received OK, but this does not delete the data (next 0600 sends it again).
15 Error, bad crc, or just bad request


Requests (04-request-05)

       // 0000 = empty
       // 0100 = 0001 01 2008 12 30 1351 19    Time?
       // 0200 = '000102050100000000020001    030002    040002    0502560008060000    0700030003080000    090001    100000000011000000001200000000    '
       // 0300 = empty
       // 0400 = empty
       // 0500 = empty
       // 0600 = get time-entries
       // 0700 = get time, empty
       // 0800 = empty
       // 0900 = get serial and number of entries
       // 1000 = empty
       // 1100 = empty
       // 1200 = empty
       // ...
       // 2100 = empty
0900 status and number of entries?
0700 empty for agx-100, and '.0001.0700 210 2008 12 30 1236 10   ' for agx-10. Looks like date/time
0600 send the entries, 8 at a time
1901 unknown, but sent
       // 0101 = ERROR
       // ...
       // 0801 = ERROR
       // 0901 = ERROR
       // 1001 = 04
       // 1101 = 04
       // 1201 = 04
       // 1301 = 04
       // 1401 = ERROR
       // 1501 = ERROR
       // 1601 = 04
       // 1701 = ERROR
       // 1801 = ERROR
       // 1901 = 04     // Receive mode?
       // 3101 = ERROR


It also just occurred to me that my real card has a magnetic strip, and does indeed work with the old unit. This is a record from it:

0001 31 2008 12 30 1815 0001 0000001222 0001

Note it still starts with "31" which makes me think it is not Unit Number, but perhaps card series.

Checksum

01-02-03 seem to be always followed by a checksum byte (&0x0f) so, we need to figure this out:

01 0001 02 09 0 0 0 0 218 00000000 0 8 0000000______________ 03 09
01 0001 02 31 200810030846000100000012220001
01 0001 02 31 200810030925000100000010610001 03 0d
01 0002 02 19 11 ____________ 03 0b

01 0001 02 09 0 0 0 0 218 00000000 2 4 0000000______________ 03 07
01 0001 02 31 200810030933000100000011070001
           31 200810030934000100000014550001
           31 200810030936000100000011670001
           31 200810030941000100000014460001 03 0e
01 0002 02 19 11 ____________ 03 0b

01 0001 02 09 0 0 0 0 218 00000000 0 7 0000000______________ 03 06
01 0001 02 31 200810030958000100000011660001
           31 200810031010000100000011620001 
            ________________________________ 03 06
01 0002 02 19 11 ____________ 03 0b

01 0001 02 09 0 0 0 0 218 00000000 0 2 0000000______________ 03 03
01 0001 02 31 200810031031000100000015510001
           31 200810031054000100000011390001
            ________________________________
            ________________________________
            ________________________________
            ________________________________
            ________________________________
            ________________________________ 03 0a

01 0001 02 09 0 0 0 0 218 00000000 0 0 000000000____________ 03 01

Note that the data-get (reply to 0600) always has 8 records in it, or padded out with spaces until final 03.


The two closest packets we have are the two listing 8 entries and 7 entries.

01 0001 02 09 0 0 0 0 218 00000000 0 8 0000000______________ 03 09
01 0001 02 09 0 0 0 0 218 00000000 0 7 0000000______________ 03 06
                                  30 38
                                  30 37
                          38 =>   0011 1000    09 => 1001
                          37 =>   0011 0111    06 => 0110

So it would seem that the CRC is XOR based. It is computed from the first byte following 0x02 (6th byte into the message) and includes the 0x03 byte at the end.

Java Examples

The following list is in Java examples, which appear to match my findings:

   final byte SOH = 1;    Start of header?
   final byte STX = 2;    Start transmit
   final byte ETX = 3;    End transmit
   final byte EOT = 4;    End of text
   final byte ENQ = 5;    Enquiry
   final byte DLE = 16;   0x10, with "0" or "1"
   final byte NAK = 21;   0x15 error
   final byte SYN = 22;   0x16
   final byte ETB = 23;   0x17 Get this in GetTime 0400
   final byte CR = 10;
   final byte LF = 13;

To set time, they send "11xx" where xx is TerminalNo * 2 -1. The TerminalNo is sometimes calculated TerminalNo * 2 -2.

04 "1101" 05
02 11 yyyymmddhhMMSSyyyymmddyyyymmdd" 03 crc

Where the 2nd and third dates are for daylight savings. However, Japan do not use DST, so the units do not appear to bother with that. This is the correct sequence to set the time, and it works.

< 04 "1101" 05
> 10 30 
Computed CRC as 0E
: 02 31 31 32 30 30 39 30 31 30 37 30 39 30 39 30 30 03 0E 
< 0x02 "1120090107090900" 0x03 0x0e
> 10 31 
< 0x04

Success. The first data written to the unit. The format of the date string does appear to change considerably between units, but at least we have an idea of what to expect.

Also, the 31 in the punch data appears to be related to:

   static final int COSTCENTER = 0;
   static final int DEPARTMENT = 1;
   static final int JOB = 2;
   static final int MESSAGEINFO = 3;
   static final int MSGLINE1 = 4;
   static final int MSGLINE2 = 5;
   static final int MSGLINE3 = 6;
   static final int MSGLINE4 = 7;
   static final int DATEOFHOURS = 8;
   static final int EMPLOYEENAME = 9;
   static final int HOURS_REG = 10;
   static final int HOURS_OT = 11;
   static final int HOURS_MSC = 12;
   static final int BNF1 = 13;
   static final int BNF2 = 14;
   static final int BNF3 = 15;
   static final int BNF4 = 16;
   static final int BNF5 = 17;
   static final int LABORLEVEL4 = 18;
   static final int LABORLEVEL5 = 19;
   static final int LABORLEVEL6 = 20;
   static final int PUNCHTABLE = 31;

According to the Java sources:

00nn nn=id*2-2 poll device
06nn Select for Ask terminal
11nn nn=id*2-1 : Select for Set time
14nn nn=id*2-1 : Select Terminal for download (to the device)
19nn nn=id*2-1 : Select for clear
YYZZ Auto query
XXZZ Auto query
XXnn Select for Set Terminal

10nn expects n=16   (mtx5 say firmware update here.)
1301 expects n=24

19nn Special commands

19AM Clear validation data, string of 16.
191618 Clear Terminal Data, string of 16.
1915 Clear tables, string of 16.

Downloadable locations and filenames:

sendIDTable()    sendFile((byte)1, "TABID01.SRT");
sendRelayTable() sendFile((byte)2, "RL.SRT");
sendVTTable()    sendFile((byte)3, "TABVT01.SRT");