July 21, 2026
Wireshark Dissector for TP-Link Smart Home System and Device Discovery Protocols
A Lua-based Wireshark protocol dissector that is tested on network traffic from TP-Link Tapo C100 IP camera and is aimed at analyzing…

By Kostas Ereksonas
2 min read
A Lua-based Wireshark protocol dissector that is tested on network traffic from TP-Link Tapo C100 IP camera and is aimed at analyzing app-to-device communications on ports TCP/8001 and TCP/8800, as well as packets for device discovery on ports UDP/20002 and UDP/20004.
Full code can be found on my Tapo protocol analysis Github repository.
Additional IoT device security research (among other things that are IT and cyber security related) can be found on my Github profile.
Table of Contents
- Device Discovery
- Header Structure for Device Discovery Packets
- Payloads of Device Discovery Packets
- Communication and Media Messages
- Header of a Communication Message
- Payload of a Communication Message
- Wireshark Filters
Device Discovery
For device discovery, ports UDP/20002 and UDP/20004 are being used.
Header Structure for Device Discovery Packets
A write-up on command injection vulnerability within tdpServer daemon that listens on port UDP/200002, as well as another write-up on remote code execution (RCE) vulnerability found in the TP-Link AC1750 Smart Wi-Fi router both describe a device discovery packet that has 16 byte long header with it's fields defined as follows:
There are 8 separate fields that can be defined as follows:
- Byte 1: Packet version.
- Byte 2: Packet type.
- Bytes 3–4: Packet opcode.
- Bytes 5–6: Packet payload length.
- Byte 7: Packet flags.
- Byte 8: Struct alignment.
- Bytes 9–12: Serial Number.
- Bytes 13–16: Checksum.
Below is the header's representation in Wireshark:
Payloads of Device Discovery Packets
Observed payloads include:
- Device configuration messages, some data encrypted with AES key:
{
"error_code": 0,
"result": {
"device_id": "REDACTED",
"device_name": "Tapo C100",
"device_type": "SMART.IPCAMERA",
"device_model": "C100",
"ip": "REDACTED",
"mac": "REDACTED",
"hardware_version": "4.0",
"firmware_version": "1.1.21 Build 220511 Rel.42882n(4555)",
"factory_default": false,
"mgt_encrypt_schm": {
"is_support_https": true
},
"encrypt_info": {
"sym_schm": "AES",
"key": "REDACTED",
"data": "REDACTED"
}
}
}{
"error_code": 0,
"result": {
"device_id": "REDACTED",
"device_name": "Tapo C100",
"device_type": "SMART.IPCAMERA",
"device_model": "C100",
"ip": "REDACTED",
"mac": "REDACTED",
"hardware_version": "4.0",
"firmware_version": "1.1.21 Build 220511 Rel.42882n(4555)",
"factory_default": false,
"mgt_encrypt_schm": {
"is_support_https": true
},
"encrypt_info": {
"sym_schm": "AES",
"key": "REDACTED",
"data": "REDACTED"
}
}
}- Public RSA key:
{
"params": {
"rsa_key": "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvzPNrLCSw3Rqf+AKwla2\\nntENZ+P4UUwGDzwvSc5HyJIYkY5+aQ8tpdQAO6NfN1JlVAUm94gxH5cw9s+xGgok\\nusbhFCHvMFp2g0CxvFg1P225+fq8Hmqqm9JN/ZkL2qwR4to6yvn256IqUxzmwKi8\\nFiX60VmAkmeJDOy8XGcN8ch385T9/sX1KyKZNxzX4z5xJEOlwcr5ZdhUeOmB6dbF\\njFF8GliOKSZdE01GVgeZPqJA21/8EQa1yJy8v31o+NNRd3QJaWjIzFqjGs1sl+Zj\\niPggKWcR/LqGt8Dd031velv2gVgmyBIjqi779cxns8IA5zYsvJbkxm0pFr3CU3GZ\\nYQIDAQAB\\n-----END PUBLIC
KEY-----\\n"
}
}{
"params": {
"rsa_key": "-----BEGIN PUBLIC KEY-----\\nMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvzPNrLCSw3Rqf+AKwla2\\nntENZ+P4UUwGDzwvSc5HyJIYkY5+aQ8tpdQAO6NfN1JlVAUm94gxH5cw9s+xGgok\\nusbhFCHvMFp2g0CxvFg1P225+fq8Hmqqm9JN/ZkL2qwR4to6yvn256IqUxzmwKi8\\nFiX60VmAkmeJDOy8XGcN8ch385T9/sX1KyKZNxzX4z5xJEOlwcr5ZdhUeOmB6dbF\\njFF8GliOKSZdE01GVgeZPqJA21/8EQa1yJy8v31o+NNRd3QJaWjIzFqjGs1sl+Zj\\niPggKWcR/LqGt8Dd031velv2gVgmyBIjqi779cxns8IA5zYsvJbkxm0pFr3CU3GZ\\nYQIDAQAB\\n-----END PUBLIC
KEY-----\\n"
}
}Communication and Media Messages
A proprietary protocol that manages JSON control messages and encrypted media (audio + video) streams runs on port TCP/8800. Some keep-alive messages were also observed on port TCP/8001.
Header of a Communication Message
Header is formed from the first 28 bytes of the message. Fields are text based rather than byte-based:
Payload of a Communication Message
Payloads of this protocol include JSON-formatted stream information and encrypted video stream with a type of mp2t.
- Video stream request:
{
"params": {
"preview": {
"audio": [
"default"
],
"audio_config": {
"encode_type": "G711alaw",
"sample_rate": "8"
},
"channels": [
0
],
"deviceId": "REDACTED",
"resolutions": [
"HD"
],
"track_id": "REDACTED"
},
"method": "get"
},
"seq": 1,
"type": "request"
}{
"params": {
"preview": {
"audio": [
"default"
],
"audio_config": {
"encode_type": "G711alaw",
"sample_rate": "8"
},
"channels": [
0
],
"deviceId": "REDACTED",
"resolutions": [
"HD"
],
"track_id": "REDACTED"
},
"method": "get"
},
"seq": 1,
"type": "request"
}- Response on success:
{
"type": "response",
"seq": 1,
"params": {
"error_code": 0,
"session_id": "1"
}
}{
"type": "response",
"seq": 1,
"params": {
"error_code": 0,
"session_id": "1"
}
}- Channel lens mask info:
{
"type": "notification",
"params": {
"event_type": "channel_lens_mask_info",
"channels": 0,
"enabled": "off"
}
}{
"type": "notification",
"params": {
"event_type": "channel_lens_mask_info",
"channels": 0,
"enabled": "off"
}
}- Channel resolution info:
{
"type": "notification",
"params": {
"event_type": "channel_resolution_info",
"channels": 0,
"resolution": "1280*720"
}
}{
"type": "notification",
"params": {
"event_type": "channel_resolution_info",
"channels": 0,
"resolution": "1280*720"
}
}Wireshark Filters
The following Wireshark filters are programmed for this dissector: