簡體   English   中英

解碼 Tp-Link Tapo c200 IoT IP 相機的 Discovery udp 數據包有效負載的二進制部分

[英]Decoding the binary part of a Discovery udp packet payload for Tp-Link Tapo c200 IoT IP camera

我試圖找出這個 tplink C200 相機的 API 堆棧,它不是公開的。 我可以使用 fiddler 和 Wireshark 相對輕松地找出大部分 Api 調用,但是在發現調用開始時的一些二進制幀讓我感到困惑。

用戶第一次登錄后,相機的 android App 開始向 255.255.255.255 廣播此 udp 數據包:

0000   ff ff ff ff ff ff 20 4e 7f d9 64 3e 08 00 45 00   ...... N..d>..E.
0010   02 11 08 88 40 00 40 11 b0 46 c0 a8 bf 65 ff ff   ....@.@..F...e..
0020   ff ff cd ed 4e 22 01 fd 1e c3 02 00 00 01 01 e5   ....N"..........
0030   11 00 08 34 d4 be c1 46 b6 89 7b 22 70 61 72 61   ...4...F..{"para
0040   6d 73 22 3a 7b 22 72 73 61 5f 6b 65 79 22 3a 22   ms":{"rsa_key":"
0050   2d 2d 2d 2d 2d 42 45 47 49 4e 20 50 55 42 4c 49   -----BEGIN PUBLI
0060   43 20 4b 45 59 2d 2d 2d 2d 2d 5c 6e 4d 49 49 42   C KEY-----\nMIIB
0070   49 6a 41 4e 42 67 6b 71 68 6b 69 47 39 77 30 42   IjANBgkqhkiG9w0B
0080   41 51 45 46 41 41 4f 43 41 51 38 41 4d 49 49 42   AQEFAAOCAQ8AMIIB
0090   43 67 4b 43 41 51 45 41 33 72 4e 70 4f 66 6b 59   CgKCAQEA3rNpOfkY
00a0   35 35 4d 6a 32 62 6c 77 4e 39 6d 30 5c 6e 62 56   55Mj2blwN9m0\nbV
00b0   50 72 79 76 32 37 68 6c 61 7a 6f 46 37 78 4d 55   Pryv27hlazoF7xMU
00c0   46 4f 46 57 6b 62 63 61 6f 4a 41 67 6e 52 79 45   FOFWkbcaoJAgnRyE
00d0   36 42 56 30 77 70 47 71 68 79 4f 69 49 4f 72 34   6BV0wpGqhyOiIOr4
00e0   35 50 49 55 74 62 54 51 52 45 44 56 34 75 5c 6e   5PIUtbTQREDV4u\n
00f0   2b 4b 6f 55 75 6b 41 4c 71 6c 2f 42 42 6b 41 34   +KoUukALql/BBkA4
0100   76 67 6a 67 4f 55 45 30 79 53 74 36 74 77 61 79   vgjgOUE0ySt6tway
0110   6a 2b 6b 33 73 6e 6b 2f 56 70 49 6a 61 44 74 36   j+k3snk/VpIjaDt6
0120   32 6f 33 62 35 70 6e 44 4b 45 68 48 4c 56 45 66   2o3b5pnDKEhHLVEf
0130   5c 6e 79 6c 4a 30 6b 45 6e 58 4e 43 54 35 68 73   \nylJ0kEnXNCT5hs
0140   6b 64 68 39 66 59 38 78 74 6d 62 42 6d 57 31 47   kdh9fY8xtmbBmW1G
0150   2b 6e 54 6c 30 73 43 47 54 2f 75 75 77 65 31 6b   +nTl0sCGT/uuwe1k
0160   74 67 45 78 7a 70 43 67 57 77 62 75 71 78 49 49   tgExzpCgWwbuqxII
0170   47 54 5c 6e 66 63 58 31 79 52 6d 54 73 77 37 53   GT\nfcX1yRmTsw7S
0180   66 73 5a 71 58 4f 61 39 50 6f 36 62 68 65 73 48   fsZqXOa9Po6bhesH
0190   4e 78 4c 33 48 53 52 35 72 43 6f 73 6f 6f 72 75   NxL3HSR5rCosooru
01a0   34 7a 67 71 6a 6b 64 62 42 2f 57 2b 46 71 6d 35   4zgqjkdbB/W+Fqm5
01b0   42 6d 71 50 5c 6e 44 51 75 4c 6b 49 6c 4c 4a 2b   BmqP\nDQuLkIlLJ+
01c0   34 56 32 71 35 63 48 41 73 67 4d 54 38 48 52 78   4V2q5cHAsgMT8HRx
01d0   31 5a 74 50 75 55 54 78 45 49 66 55 49 4e 58 64   1ZtPuUTxEIfUINXd
01e0   41 57 67 4b 36 75 4d 75 4e 74 4d 4e 5a 56 4f 50   AWgK6uMuNtMNZVOP
01f0   6b 2f 71 54 31 30 5c 6e 72 51 49 44 41 51 41 42   k/qT10\nrQIDAQAB
0200   5c 6e 2d 2d 2d 2d 2d 45 4e 44 20 50 55 42 4c 49   \n-----END PUBLI
0210   43 20 4b 45 59 2d 2d 2d 2d 2d 5c 6e 22 7d 7d 00   C KEY-----\n"}}.

它每隔一段時間就會熄滅,直到相機回復。 我試圖模仿數據包但沒有成功,因為我無法復制這些字節(數據幀的開頭):

(002B->003A): 02 00 00 01 01 e5 11 00 08 34 d4 是 c1 46 b6 89

正如您在此之后立即注意到的 ASCII 可讀消息開始 ({"params":...),我重復了幾次發現步驟,我注意到這些字節在某種程度上與 udp 發現的應用程序端的本地綁定端口有關消息是通過發送的,以下是我收集的示例:

Frame in udp packet                 port
0200000101e511000d554fad4de6fb2b    49411
0200000101e5110003ef2ad6767c88ee    49417
0200000101e511000c74622ed5e0246e    50248
0200000101e511000376feec3ed43466    50260
0200000101e51100046c5d74ee1a8de1    50797
0200000101e5110000503e7aa816e491    50802
0200000101e511000fdfc58e766d3742    52169
0200000101e511000e13aaabcd1a38ba    52332
0200000101e511000834d4bec146b689    52717
0200000101e511010000027822e38756    52956
0200000101e5110003e10659047571be    53370
0200000101e511000cbad8000079daf0    53500
0200000101e5110002e5bc217cb12739    57161
0200000101e511000922aa242d80ae84    58170
0200000101e511000d8945e5e21b2265    58421
0200000101e511000f97146569f2cbfe    58425
0200000101e511000d66c663c5ac4d69    59985
0200000101e511000105947d8d9e16f9    61818
0200000101e511000c9ed77f9024d65f    61879
0200000101e5110008b9a7fbc1624863    61927
0200000101e511000b3d5323ee84b6b7    62182
0200000101e511000f7b9b183a81ff80    62996
0200000101e511000da2e8028da2f46a    63043
0200000101e5110000c4390fbdc258e2    63046

我找不到關系,我嘗試了幾種不同的物聯網協議和散列方法,有人知道這些是什么或它們是如何計算的嗎?

PS 這些端口號在這些幀中以某種方式編碼,它應該是工業編碼,簡單的 hash 或異或加密。 任何想法?

看起來應用程序正在生成一個 RSA 公鑰/私鑰對,並在JSON object 中廣播公鑰。 使用的端口與密鑰對無關。 事實上,即使同一個端口再次被重用,密鑰對仍然是不同的。 如果您想了解更多關於 RSA 的信息,不妨從這里開始? https://en.wikipedia.org/wiki/RSA_(cryptosystem)

這可能是一個遲到的答復,但我最近正在自己解決這個問題,並且可以分享我的發現:

  • 前四個字節始終為 2、0、0、1。
  • 接下來的兩個字節是稍后出現的 json 字節串的長度,以大端序編碼為兩個字節的數字。
  • 接下來的兩個字節是 17(十六進制的 11)和 0。
  • 接下來的 4 個字節完全是隨機生成的——它們可以是任何東西。 我檢查的 Tapo android 應用程序生成了一個從 0 到 268435456 的隨機值,並為此目的將其轉換為 4 字節的大端值。
  • 最后一步有點棘手:插入編碼為 4 字節大端值的數字 1516993677,然后用整個字節數組(包括最后的 json)上的 crc32 校驗和覆蓋它。 這應該為您提供一個可以發送並讓 tp-link 智能插頭/相機響應的值。

是我最終在我自己的項目中用來生成這些字節的幾個 python 函數:

from random import randrange
from zlib import crc32
from Crypto.PublicKey import RSA

def get_payload():
    key = RSA.generate(2048).publickey().exportKey('PEM')

    # newline on the end and no spaces in separators to perfectly match
    #  the packets sent by vendor apps
    payload = json.dumps(
        {'params': {'rsa_key': key.decode('utf-8') + '\n'}},
        separators=(',', ':')
    )

    # Fun fact: the P100 plugs will respond just the same if you send
    #  b'\x02\x00\x00\x01\x00\x00\x11\x00\x0e\xd7\xd6\xac\x84\x0e\xfdY'
    #  which is the result of passing an empty string to build_packet()
    #
    # We send a full packet anyway, however, in case future firmware
    #  updates fix that
    return build_packet(payload)

def build_packet(string):
    # Magic prefix bytes generated by reverse-engineering the Tapo android app
    #  algorithm found in com\tplink\tdp\common\b.java
    prefix = b'\x02\x00\x00\x01\x00\x00\x11\x00\x00\x00\x00\x00Zk|\x8d'

    output_array = bytearray(prefix + string.encode('utf-8'))

    # Insert dynamic bytes that change based on the string / randomness
    output_array[4:6] = len(string).to_bytes(2, 'big')
    output_array[8:12] = randrange(268435456).to_bytes(4, 'big')

    # Insert checksum based on current array
    output_array[12:16] = crc32(output_array).to_bytes(4, 'big')

    return bytes(output_array)

(您可以在上述鏈接的提交歷史中看到更多關於這是如何計算出來的)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM