Tmphack: Difference between revisions
No edit summary |
No edit summary |
||
(10 intermediate revisions by the same user not shown) | |||
Line 19: | Line 19: | ||
<< 01 "0001" 02 "09000021800000000080000000 " 03 09 # This says "8" and there are 8 records | << 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 | # possibly read as 09 00002 18 00" as the 18 might be the 17 digits after | ||
>> 10 30 # | >> 10 30 # ACK, and clear it. | ||
<< 04 # 04 | << 04 # 04 end of data/idle/ready for next | ||
>> 04 "0700" 05 # new request ? | >> 04 "0700" 05 # new request ? | ||
<< "0700" 04 # empty? | << "0700" 04 # empty? | ||
>> 04 "0600" 05 # | >> 04 "0600" 05 # get tiemcard entries | ||
<< 01 "0001" 02 "longstringofdata" 03 0d # lots of data | << 01 "0001" 02 "longstringofdata" 03 0d # lots of data, in chunks of 8 records | ||
>> 10 30 # | >> 10 30 # ACK, and clear (send 10 31 to ACK and not clear). | ||
<< 04 # | << 04 # End of data | ||
>> 04 "1901" 05 # request for 1901 | >> 04 "1901" 05 # request for 1901. Perhaps request to enter receive mode. | ||
<< 10 30 | << 10 30 # ACK, ready to receive? | ||
>> 01 "0002" 02 "1911 " 03 0b # spaces, normal 01,02,03 reply, but what is it | >> 01 "0002" 02 "1911 " 03 0b # spaces, normal 01,02,03 reply, but what is it | ||
<< 10 31 # 10 31 | << 10 31 # 10 31 ACK, with no clear | ||
>> 04 # | >> 04 # END of data | ||
>> 04 "0600" 05 # again, give me 0600 again? | >> 04 "0600" 05 # again, give me 0600 again...? | ||
<< "0600" 04 # now its empty | << "0600" 04 # and, now its empty (due to 10 30). | ||
>> Fin | >> Fin | ||
<< Fin | << Fin | ||
Line 219: | Line 219: | ||
// 1701 = ERROR | // 1701 = ERROR | ||
// 1801 = ERROR | // 1801 = ERROR | ||
// 1901 = 04 // | // 1901 = 04 // Receive mode? | ||
// 3101 = ERROR | // 3101 = ERROR | ||
Line 275: | Line 275: | ||
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. | 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"); |
Latest revision as of 03:50, 7 January 2009
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");