Open mungewell opened 3 weeks ago
Kinda looks like this....
:hello
host,1.13.2 15 0200 0500 01000000 2cb4 68656c6c6f
1.13.2,host 0
host,1.13.1 0
1.13.1,host 25 0200 0f00 01000000 2cb4 68656c6c6f2c6920616d204853334d
:hello,I am HS3M
get the data.... command, msg length, seq counter, ????, address, count
host,1.13.2 18 0206 0800 02000000 b6dd 00002040 f6010000
1.13.2,host 0
host,1.13.1 0
1.13.1,host 512 0206 f601 00000000 b6dd c202000070563412e0340...
chunk
Well I suspect that "????" is a 16bit checksum...
I can talk to keyboard (in Bootloader mode) via libUSB
$ sudo python3 hydra.py
00000000: 01 02 00 00 01 00 00 00 86 38 .........8
None
00000000: 02 00 0F 00 01 00 00 00 2C B4 68 65 6C 6C 6F 2C ........,.hello,
00000010: 69 20 61 6D 20 48 53 33 4D i am HS3M
None
But with checksum Zero-ed out...
$ sudo python3 hydra.py
00000000: 01 02 00 00 01 00 00 00 00 00 ..........
None
00000000: 02 02 00 00 02 00 00 00 00 00 ..........
None
Oh well, that's nice... :-)
a=b"\x02\x00\x05\x00\x01\x00\x00\x00\x2c\xb4\x68\x65\x6c\x6c\x6f"
a=b"\x02\x00\x05\x00\x01\x00\x00\x00\x00\x01\x68\x65\x6c\x6c\x6f"
b=b"\x02\x06\x08\x00\x02\x00\x00\x00\xb6\xdd\x00\x00\x20\x40\xf6\x01\x00\x00"
b=b"\x02\x06\x08\x00\x02\x00\x00\x00\x00\x01\x00\x00\x20\x40\xf6\x01\x00\x00"
# Appears to be 'TCP' checksum! ^^ ^^ preset checksum = 0x00 0x01
def carry_around_add(a, b):
c = a + b
return (c & 0xffff) + (c >> 16)
def checksum(msg):
if len(msg) & 1:
msg += b"\x00"
s = 0
for i in range(0, len(msg), 2):
w = msg[i] + (msg[i+1] << 8)
s = carry_around_add(s, w)
return ~s & 0xffff
print("%4.4x" % checksum(a))
print("%4.4x" % checksum(b))
Which gives the correct answers
$ python3 checksum.py
2cb4
b6dd
That 'checksum()` is not quiet right, I can receive a few packets (~1500 bytes), but fails at 'seq=5'
hello,i am HS3M
Writing data to file: test.bin
00000000: 02 06 08 00 02 00 00 00 B6 DD 00 00 20 40 F6 01 ............ @..
00000010: 00 00 ..
None
........
00000000: 02 06 08 00 03 00 00 00 B4 E6 F6 01 20 40 F6 01 ............ @..
00000010: 00 00 ..
None
........
00000000: 02 06 08 00 04 00 00 00 B2 EF EC 03 20 40 F6 01 ............ @..
00000010: 00 00 ..
None
........
00000000: 02 06 08 00 05 00 00 00 B0 F8 E2 05 20 40 F6 01 ............ @..
00000010: 00 00 ..
None
.Traceback (most recent call last):
Whereas the keyboard wants:
host,1.13.2 18 02060800 05000000 b1f8 e2052040 f6010000
$ sudo python3 retrieve_voice.py -v -s 1506 test.bin
CONFIGURATION 1: 30 mA ===================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x2 Configuration
wTotalLength : 0x20 (32 bytes)
bNumInterfaces : 0x1
bConfigurationValue : 0x1
iConfiguration : 0x0
bmAttributes : 0x80 Bus Powered
bMaxPower : 0xf (30 mA)
INTERFACE 0: Reserved ==================================
bLength : 0x9 (9 bytes)
bDescriptorType : 0x4 Interface
bInterfaceNumber : 0x0
bAlternateSetting : 0x0
bNumEndpoints : 0x2
bInterfaceClass : 0x0 Reserved
bInterfaceSubClass : 0x0
bInterfaceProtocol : 0x0
iInterface : 0x0
ENDPOINT 0x81: Bulk IN ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x81 IN
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x40 (64 bytes)
bInterval : 0x5
ENDPOINT 0x2: Bulk OUT ===============================
bLength : 0x7 (7 bytes)
bDescriptorType : 0x5 Endpoint
bEndpointAddress : 0x2 OUT
bmAttributes : 0x2 Bulk
wMaxPacketSize : 0x200 (512 bytes)
bInterval : 0x5
hello,i am HS3M
Writing data to file: test.bin
........
........
........
bye
$ hexdump -C test.bin | head
00000000 c2 02 00 00 70 56 34 12 e0 34 06 00 dc 00 00 00 |....pV4..4......|
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 |................|
00000020 89 00 00 00 42 02 00 00 43 02 00 00 44 02 00 00 |....B...C...D...|
00000030 45 02 00 00 46 02 00 00 47 02 00 00 48 02 00 00 |E...F...G...H...|
00000040 49 02 00 00 4a 02 00 00 4b 02 00 00 4c 02 00 00 |I...J...K...L...|
00000050 4d 02 00 00 4e 02 00 00 4f 02 00 00 50 02 00 00 |M...N...O...P...|
00000060 51 02 00 00 52 02 00 00 53 02 00 00 54 02 00 00 |Q...R...S...T...|
00000070 55 02 00 00 56 02 00 00 57 02 00 00 58 02 00 00 |U...V...W...X...|
00000080 59 02 00 00 5a 02 00 00 5b 02 00 00 5c 02 00 00 |Y...Z...[...\...|
00000090 5d 02 00 00 5e 02 00 00 5f 02 00 00 60 02 00 00 |]...^..._...`...|
Short script to validate 'checksum()', currently fails on a couple of observed messages. checksum.py.txt
$ python3 checksum.py
b'01030300000000008234627965'
Checksum failed, expected 0x86 0x38
b'02000500010000002cb468656c6c6f'
b'0206080002000000b6dd00002040f6010000'
b'0206080003000000b4e6f6012040f6010000'
b'0206080004000000b2efec032040f6010000'
b'0206080005000000b0f8e2052040f6010000'
Checksum failed, expected 0xb1 0xf8
b'0206080006000000af01d8072040f6010000'
b'0206080007000000ad0ace092040f6010000'
b'0206080008000000ab13c40b2040f6010000'
b'0206080009000000a91cba0d2040f6010000'
b'020608000a000000a8cbb00f204050000000'
b'020303000b0000008228627965'
Saved a full (0x0160000 long) pcap and noticed some discontuities when analysing the data...
b"\x02\x06\x08\x00\x0e\x00\x00\x00\x9f\x49\x88\x17\x20\x40\xf6\x01\x00\x00",
b"\x02\x06\x08\x00\x0f\x00\x00\x00\x9d\x52\x7e\x19\x20\x40\xf6\x01\x00\x00",
b"\x02\x06\x08\x00\x00\x01\x00\x00\xc3\xc9\x14\xf2\x21\x40\xf6\x01\x00\x00",
^^ ^^ ^^
b"\x02\x06\x08\x00\x0e\x01\x00\x00\xa8\x47\x88\x0d\x22\x40\xf6\x01\x00\x00",
b"\x02\x06\x08\x00\x0f\x01\x00\x00\xa6\x50\x7e\x0f\x22\x40\xf6\x01\x00\x00",
b"\x02\x06\x08\x00\x00\x02\x00\x00\xcc\xc7\x14\xe8\x23\x40\xf6\x01\x00\x00",
b"\x02\x06\x08\x00\x0e\x02\x00\x00\xb1\x45\x88\x03\x24\x40\xf6\x01\x00\x00",
b"\x02\x06\x08\x00\x0f\x02\x00\x00\xaf\x4e\x7e\x05\x24\x40\xf6\x01\x00\x00",
b"\x02\x06\x08\x00\x00\x03\x00\x00\xd5\xc5\x14\xde\x25\x40\xf6\x01\x00\x00",
etc...
Looking at the cheksums for all the reads. I managed to figure a 'fix' for a few more, but it still fails starting from:
Start: 0x00000000
0000: 0x00000206
0002: 0x00000a06
0004: 0x0000100f
0006: 0x0000100f
0008: 0x0000100f
0010: 0x0000e8bc
0012: 0x000119fc
0014: 0x00020ffd
0016: 0x00020ffd
End: 0x00021000 0x-00021001 0x0002efff
b'0206080006090000ffefd8ad3140f6010000'
Checksum failed, expected 0x00 0xf0
--
Start: 0x00000000
0000: 0x00000206
0002: 0x00000a06
0004: 0x00001114
0006: 0x00001114
0008: 0x00001114
0010: 0x0000df91
0012: 0x00011ad1
0014: 0x000210d2
0016: 0x000210d2
End: 0x000210d5 0x-000210D6 0x0002ef2a
b'02060800070e00002aefce7d3b40f6010000'
Checksum failed, expected 0x2b 0xef
--
...
With these changes we can read 74296 Bytes, which is small chunk of the table but enough to decode the first few waveforms (ie should tell us a bit more about the Keyboard/Desktop/Delux).
Spent way too long/many late nights on this... but here's some conclusions:
In pictorial form the init for the first 256 blocks (each of 502 byte), referenced to the 'sequence' number
0000 : 0000100000000000
1000 : 0000000000000111
2000 : 1100000000000000
3000 : 0000000111111100
4000 : 0000000000000000
5000 : 0111111111100000
6000 : 0000000000111111
7000 : 1111111000000000
8000 : 0000111111111111
9000 : 1111000000000111
a000 : 1111111111111111
b000 : 0000000111111111
c000 : 1111111111111000
d000 : 0111111111111111
e000 : 1111111110111111
f000 : 1111100000000000
In order to download the whole voice segment you'd need nearly 46,000 blocks - with the equation (or pseudo random sequence) known.... and I couldn't figure it out.
Then I released... pick one init value, use that until you get an error (ie no response from Keyboard, as a USB timeout) and then restart the connection (send "bye" and "hello" again), flip the init value and continue where you got to/left off.
SUCCESS, painfully slow due to the USB time-outs, but success all the same. It took close to an hour with the Explorer and would probably be longer for Keyboard/Desktop/Delux.
$ time sudo python3 retrieve_voice.py -v test.bin > test.log
real 58m51.587s
user 0m0.006s
sys 0m0.006s
Also note that you only have to do this once (and if you can't find the ASM dev tool), to get the factory waveforms. Once you have that file, you can patch with your own samples and upload as a '.dat' using the regular (non developer) tools from ASM.
short.pcapng.tar.gz