mirror of
https://github.com/softScheck/tplink-smartplug
synced 2026-01-11 23:38:46 +01:00
Converted TDDP client to Python 3
This commit is contained in:
1430
tddp-client/pyDes.py
1430
tddp-client/pyDes.py
File diff suppressed because it is too large
Load Diff
70
tddp-client/tddp-client.py → tddp-client/tddp_client.py
Normal file → Executable file
70
tddp-client/tddp-client.py → tddp-client/tddp_client.py
Normal file → Executable file
@@ -1,4 +1,4 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python3
|
||||||
#
|
#
|
||||||
# TP-Link Device Debug Protocol (TDDP) v2 Client
|
# TP-Link Device Debug Protocol (TDDP) v2 Client
|
||||||
# Based on https://www.google.com/patents/CN102096654A?cl=en
|
# Based on https://www.google.com/patents/CN102096654A?cl=en
|
||||||
@@ -22,15 +22,15 @@
|
|||||||
# limitations under the License.
|
# limitations under the License.
|
||||||
#
|
#
|
||||||
|
|
||||||
from pyDes import *
|
|
||||||
import hashlib
|
|
||||||
import argparse
|
import argparse
|
||||||
|
import hashlib
|
||||||
import socket
|
import socket
|
||||||
import struct
|
|
||||||
import binascii
|
|
||||||
import string
|
import string
|
||||||
|
|
||||||
version = 0.2
|
from binascii import hexlify, unhexlify
|
||||||
|
from pyDes import *
|
||||||
|
|
||||||
|
version = 0.3
|
||||||
|
|
||||||
# Default username and password
|
# Default username and password
|
||||||
username = "admin"
|
username = "admin"
|
||||||
@@ -38,19 +38,19 @@ password = "admin"
|
|||||||
|
|
||||||
# Check if IP is valid
|
# Check if IP is valid
|
||||||
def validIP(ip):
|
def validIP(ip):
|
||||||
try:
|
try:
|
||||||
socket.inet_pton(socket.AF_INET, ip)
|
socket.inet_pton(socket.AF_INET, ip)
|
||||||
except socket.error:
|
except socket.error:
|
||||||
parser.error("Invalid IP Address.")
|
parser.error("Invalid IP Address.")
|
||||||
return ip
|
return ip
|
||||||
|
|
||||||
# Check if command is two hex chars
|
# Check if command is two hex chars
|
||||||
def validHex(cmd):
|
def validHex(cmd):
|
||||||
ishex = all(c in string.hexdigits for c in cmd)
|
ishex = all(c in string.hexdigits for c in cmd)
|
||||||
if len(cmd) == 2 and ishex:
|
if len(cmd) == 2 and ishex:
|
||||||
return cmd
|
return cmd
|
||||||
else:
|
else:
|
||||||
parser.error("Please issue a two-character hex command, e.g. 0A")
|
parser.error("Please issue a two-character hex command, e.g. 0A")
|
||||||
|
|
||||||
# Parse commandline arguments
|
# Parse commandline arguments
|
||||||
parser = argparse.ArgumentParser(description="Experimental TP-Link TDDPv2 Client v" + str(version))
|
parser = argparse.ArgumentParser(description="Experimental TP-Link TDDPv2 Client v" + str(version))
|
||||||
@@ -65,9 +65,9 @@ args = parser.parse_args()
|
|||||||
ip = args.target
|
ip = args.target
|
||||||
cmd = args.command
|
cmd = args.command
|
||||||
if args.username:
|
if args.username:
|
||||||
username = args.username
|
username = args.username
|
||||||
if args.password:
|
if args.password:
|
||||||
password = args.password
|
password = args.password
|
||||||
|
|
||||||
# TDDP runs on UDP Port 1040
|
# TDDP runs on UDP Port 1040
|
||||||
# Response is sent to UDP Port 61000
|
# Response is sent to UDP Port 61000
|
||||||
@@ -77,9 +77,9 @@ port_receive = 61000
|
|||||||
|
|
||||||
# TDDP DES Key = MD5 of username and password concatenated
|
# TDDP DES Key = MD5 of username and password concatenated
|
||||||
# Key is first 8 bytes only
|
# Key is first 8 bytes only
|
||||||
tddp_key = hashlib.md5(username + password).hexdigest()[:16]
|
tddp_key = hashlib.md5(username.encode() + password.encode()).hexdigest()[:16]
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
print "TDDP Key:\t", tddp_key, "(" + username + password + ")"
|
print("TDDP Key:\t", tddp_key, "(" + username + password + ")")
|
||||||
|
|
||||||
## TDDP Header
|
## TDDP Header
|
||||||
# 0 1 2 3
|
# 0 1 2 3
|
||||||
@@ -176,18 +176,21 @@ tddp_digest = "%0.32X" % 00
|
|||||||
tddp_data = ""
|
tddp_data = ""
|
||||||
|
|
||||||
# Recalculate length if sending data
|
# Recalculate length if sending data
|
||||||
tddp_length = len(tddp_data)/2
|
|
||||||
|
tddp_length = len(tddp_data)//2
|
||||||
tddp_length = "%0.8X" % tddp_length
|
tddp_length = "%0.8X" % tddp_length
|
||||||
|
|
||||||
## Encrypt data with key
|
## Encrypt data with key
|
||||||
key = des(binascii.unhexlify(tddp_key), ECB)
|
key = des(unhexlify(tddp_key), ECB)
|
||||||
data = key.encrypt(binascii.unhexlify(tddp_data))
|
data = key.encrypt(unhexlify(tddp_data))
|
||||||
|
|
||||||
## Assemble packet
|
## Assemble packet
|
||||||
tddp_packet = "".join([tddp_ver, tddp_type, tddp_code, tddp_reply, tddp_length, tddp_id, tddp_subtype, tddp_reserved, tddp_digest, data.encode('hex')])
|
tddp_packet = "".join([tddp_ver, tddp_type, tddp_code, tddp_reply,
|
||||||
|
tddp_length, tddp_id, tddp_subtype,
|
||||||
|
tddp_reserved, tddp_digest, hexlify(data.encode()).decode()])
|
||||||
|
|
||||||
# Calculate MD5
|
# Calculate MD5
|
||||||
tddp_digest = hashlib.md5(binascii.unhexlify(tddp_packet)).hexdigest()
|
tddp_digest = hashlib.md5(unhexlify(tddp_packet)).hexdigest()
|
||||||
tddp_packet = tddp_packet[:24] + tddp_digest + tddp_packet[56:]
|
tddp_packet = tddp_packet[:24] + tddp_digest + tddp_packet[56:]
|
||||||
|
|
||||||
# Binding receive socket in advance in case reply comes fast.
|
# Binding receive socket in advance in case reply comes fast.
|
||||||
@@ -196,23 +199,26 @@ sock_receive.bind(('', port_receive))
|
|||||||
|
|
||||||
# Send a request
|
# Send a request
|
||||||
sock_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
sock_send = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||||
sock_send.sendto(binascii.unhexlify(tddp_packet), (ip, port_send))
|
sock_send.sendto(unhexlify(tddp_packet), (ip, port_send))
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
print "Raw Request:\t", tddp_packet
|
print("Raw Request:\t", tddp_packet)
|
||||||
t = tddp_packet
|
t = tddp_packet
|
||||||
print "Request Data:\tVersion", t[0:2], "Type", t[2:4], "Status", t[6:8], "Length", t[8:16], "ID", t[16:20], "Subtype", t[20:22]
|
print("Request Data:\tVersion", t[0:2], "Type", t[2:4], "Status", t[6:8],
|
||||||
|
"Length", t[8:16], "ID", t[16:20], "Subtype", t[20:22])
|
||||||
sock_send.close()
|
sock_send.close()
|
||||||
|
|
||||||
# Receive the reply
|
# Receive the reply
|
||||||
response, addr = sock_receive.recvfrom(1024)
|
response, addr = sock_receive.recvfrom(1024)
|
||||||
r = response.encode('hex')
|
r = hexlify(response).decode()
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
print "Raw Reply:\t", r
|
print("Raw Reply:\t", r)
|
||||||
sock_receive.close()
|
sock_receive.close()
|
||||||
print "Reply Data:\tVersion", r[0:2], "Type", r[2:4], "Status", r[6:8], "Length", r[8:16], "ID", r[16:20], "Subtype", r[20:22]
|
print("Reply Data:\tVersion", r[0:2], "Type", r[2:4], "Status", r[6:8],
|
||||||
|
"Length", r[8:16], "ID", r[16:20], "Subtype", r[20:22])
|
||||||
|
|
||||||
# Take payload and decrypt using key
|
# Take payload and decrypt using key
|
||||||
recv_data = r[56:]
|
recv_data = r[56:]
|
||||||
if recv_data:
|
if recv_data:
|
||||||
print "Decrypted:\t" + key.decrypt(binascii.unhexlify(recv_data))
|
print("Decrypted:\t", end="")
|
||||||
|
print(key.decrypt(unhexlify(recv_data)))
|
||||||
|
|
||||||
Reference in New Issue
Block a user