diff --git a/scripts/fake-registration-server.py b/scripts/fake-registration-server.py index f9eae0f..f1e51fa 100755 --- a/scripts/fake-registration-server.py +++ b/scripts/fake-registration-server.py @@ -9,6 +9,8 @@ Copyright (c) 2018 VTRUST. All rights reserved. import tornado.web import os import hashlib +import hmac +import binascii def file_as_bytes(file): with file: return file.read() @@ -32,7 +34,8 @@ class JSONHandler(tornado.web.RequestHandler): def get(self): print('\n') print('URI:'+str(self.request.uri)) - self.write('Hello Human, Do you have IOT?') + #self.write('Hello Human, Do you have IOT?') + self.post() def post(self): print('\n') uri = str(self.request.uri) @@ -42,7 +45,7 @@ class JSONHandler(tornado.web.RequestHandler): if(a == "s.gw.token.get"): print("Answer s.gw.token.get") answer =(b'{"result":{"gwApiUrl":"http://10.42.42.1/gw.json","stdTimeZone":"-05:00","mqttRanges":"","timeZone":"-05:00",' - b'"httpsPSKUrl":"https://10.42.42.1/gw.json","mediaMqttUrl":"10.42.42.1","gwMqttUrl":"10.42.42.1","dstIntervals":[]},"t":7,"e":false,"success":true}\n' + b'"httpsPSKUrl":"https://10.42.42.1/gw.json","mediaMqttUrl":"10.42.42.1","mqttsUrl":"10.42.42.1","gwMqttUrl":"10.42.42.1","dstIntervals":[]},"t":7,"e":false,"success":true}\n' ) self.set_header("Content-Type", "application/json;charset=UTF-8") @@ -71,22 +74,47 @@ class JSONHandler(tornado.web.RequestHandler): self.set_header('Content-Length', str(len(answer))) self.set_header('Content-Language', 'zh-CN') self.write(answer) - print("TRIGGER UPGRADE IN 10 SECONDS") - os.system("./trigger_upgrade.sh %s &" % str(gwId)) + elif(".dynamic.config.get" in a): + print("Answer tuya.device.dynamic.config.get") + index = uri.find("gwId=")+5 + gwId = uri[index:index+20] + print("READ GW ID",gwId) + answer = (b'{"result":' + b'{' + b'"ackId":"1234567", "time":"1", "validTime":"1",' + b'"config":{"stdTimeZone":"UTC", "dstIntervals":"0"}' + b'},' + b'"t":9, "e":false,"success":true}') + self.set_header("Content-Type", "application/json;charset=UTF-8") + self.set_header('Content-Length', str(len(answer))) + self.set_header('Content-Language', 'zh-CN') + self.write(answer) - elif(".upgrade" in a): - print("Answer s.gw.upgrade") + elif(".upgrade.get" in a) or ('.upgrade.silent.get' in a): + print("Answer s.gw.upgrade.get") #Fixme #Calculate MD5 and Filesize - file_md5 = hashlib.md5(file_as_bytes(open('../files/upgrade.bin', 'rb'))).hexdigest() file_len = os.path.getsize('../files/upgrade.bin') - answer = b'{"result":{"auto":3,"fileSize":"%d","etag":"0000000000","version":"9.0.0","url":"http://10.42.42.1/files/upgrade.bin","md5":"%s"},"t":100,"e":false,"success":true}' % (file_len,file_md5.encode('utf-8')) + file_sha256 = hashlib.sha256(file_as_bytes(open('../files/upgrade.bin', 'rb'))).hexdigest().upper() + file_hmac = hmac.HMAC(b'0000000000000000', file_sha256.encode(), 'sha256').hexdigest().upper() + answer = b'{"result":{"auto":3,"size":"%d","type":9,"pskUrl":"https://10.42.42.1/files/upgrade.bin","hmac":"%s","version":"9.0.0"},"t":10,"e":false,"success":true}'%(file_len, file_hmac.encode()) print(answer) self.set_header("Content-Type", "application/json;charset=UTF-8") self.set_header('Content-Length', str(len(answer))) self.set_header('Content-Language', 'zh-CN') self.write(answer) + elif(".dynamic.config.ack" in a): + print("Answer tuya.device.dynamic.config.ack") + answer =b'{"result":true,"t":7,"e":false,"success":true}' + self.set_header("Content-Type", "application/json;charset=UTF-8") + self.set_header('Content-Length', str(len(answer))) + self.set_header('Content-Language', 'zh-CN') + self.write(answer) + print("TRIGGER UPGRADE IN 10 SECONDS") + os.system("./trigger_upgrade.sh %s &" % str(gwId)) + + elif(".debug.log" in a): print("Answer atop.online.debug.log") answer =b'{"result":true,"t":7,"e":false,"success":true}' diff --git a/scripts/mq_pub_15.py b/scripts/mq_pub_15.py index 58a0be2..493dc91 100755 --- a/scripts/mq_pub_15.py +++ b/scripts/mq_pub_15.py @@ -8,6 +8,7 @@ Copyright (c) 2018 VTRUST. All rights reserved. import sys, getopt, time, pyaes, base64 import paho.mqtt.client as mqtt #pip install paho-mqtt from hashlib import md5 +import binascii help_message = '''USAGE: "-i"/"--deviceID" @@ -25,8 +26,7 @@ class iotAES(object): cipher = pyaes.blockfeeder.Encrypter(pyaes.AESModeOfOperationECB(self.key.encode())) crypted_text = cipher.feed(raw) crypted_text += cipher.feed() - crypted_text_b64 = base64.b64encode(crypted_text) - return crypted_text_b64 + return crypted_text def decrypt(self, enc): enc = base64.b64decode(enc) cipher = pyaes.blockfeeder.Decrypter(pyaes.AESModeOfOperationECB(self.key)) @@ -47,15 +47,11 @@ def iot_dec(message, local_key): def iot_enc(message, local_key): iot_aes = iotAES(local_key) messge_enc = iot_aes.encrypt(message) - m = md5() - PROTOCOL_VERSION_BYTES = b'2.1' - # preMd5String = b'data=' + messge_enc + b'||lpv=' + PROTOCOL_VERSION_BYTES + b'||' + local_key - preMd5String = b'data=' + messge_enc + b'||pv=' + PROTOCOL_VERSION_BYTES + b'||' + local_key.encode() - # print (preMd5String) - m.update(preMd5String) - md5sum = m.hexdigest() - print (md5sum) #ca2b66d33d3f50a1 #ca2b66d33d3f50a1 - messge_enc = PROTOCOL_VERSION_BYTES + md5sum[8:][:16].encode('latin1') + messge_enc + message = b'%08d'%((int(time.time()*100)%100000000)) + messge_enc + c = binascii.crc32(message) + PROTOCOL_VERSION_BYTES = b'2.2' + messge_enc = PROTOCOL_VERSION_BYTES + (c).to_bytes(4, byteorder='big') +message + print (messge_enc) return messge_enc @@ -98,7 +94,8 @@ def main(argv=None): print (help_message) return 2 - message = '{"data":{"gwId":"%s"},"protocol":15,"s":%d,"t":%d}' %(deviceID, 1523715, time.time()) + + message = '{"data":{"gwId":"%s"},"protocol":15,"s":"%d","t":"%d"}' %(deviceID, 1523715, time.time()) m1 = iot_enc(message, localKey) client = mqtt.Client("P1") diff --git a/scripts/psk-frontend.py b/scripts/psk-frontend.py new file mode 100755 index 0000000..2378d26 --- /dev/null +++ b/scripts/psk-frontend.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 + +import socket +import select +import ssl +import sslpsk + +from Crypto.Cipher import AES +import hashlib +from binascii import hexlify, unhexlify + +server_hint_hex = "316448527363324e6a62486c74624778336557683530303030303030303030303030303030" +server_hint = unhexlify(server_hint_hex) + + +def listener(host, port): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) + sock.bind((host, port)) + sock.listen(1) + return sock + +def client(host, port): + sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + sock.connect((host, port)) + return sock + + +def get_psk(identity): + id = identity + server_hint = unhexlify(server_hint_hex) + + md5_uuid = id[17:(17+16)] + source = id[1:50] + + rand = server_hint[21:21+16] + + key = hashlib.md5(rand).digest() + to_encode = id[1:33] + iv = hashlib.md5(source).digest() + cipher = AES.new(key ,AES.MODE_CBC, iv) + + c = cipher.encrypt(to_encode) + print("PSK: %r"%(hexlify(c))) + return c + + +class PskFrontend(): + def __init__(self, listening_host, listening_port, host, port): + self.listening_port = listening_port + self.listening_host = listening_host + self.host = host + self.port = port + + self.server_sock = listener(listening_host, listening_port) + self.sessions = [] + self.hint = '1dHRsc2NjbHltbGx3eWh50000000000000000' + + + + def readables(self): + readables = [self.server_sock] + for (s1, s2) in self.sessions: + readables.append(s1) + readables.append(s2) + return readables + + def new_client(self, s1): + try: + ssl_sock = sslpsk.wrap_socket(s1, + server_side = True, + ssl_version=ssl.PROTOCOL_TLSv1_2, + ciphers='PSK-AES128-CBC-SHA256', + psk=get_psk, + hint=self.hint) + + s2 = client(self.host, self.port) + self.sessions.append((ssl_sock, s2)) + except: + pass + def data_ready_cb(self, s): + if s == self.server_sock: + _s, frm = s.accept() + print("new client on port %d from %r"%(self.listening_port, frm)) + self.new_client(_s) + + for (s1, s2) in self.sessions: + if s == s1 or s == s2: + c = s1 if s == s2 else s2 + try: + buf = s.recv(4096) + if len(buf) > 0: + c.send(buf) + else: + s1.shutdown(socket.SHUT_RDWR) + s2.shutdown(socket.SHUT_RDWR) + self.sessions.remove((s1,s2)) + except: + self.sessions.remove((s1,s2)) + + +def main(): + proxies = [PskFrontend('', 443, '127.0.0.1', 80), PskFrontend('', 8886, '127.0.0.1', 1883)] + + + while True: + readables = [] + for p in proxies: + readables = readables + p.readables() + r,_,_ = select.select(readables, [], []) + for s in r: + for p in proxies: + p.data_ready_cb(s) + + +if __name__ == '__main__': + main() diff --git a/start_flash.sh b/start_flash.sh index 6b6c3a5..d9cb179 100755 --- a/start_flash.sh +++ b/start_flash.sh @@ -44,6 +44,8 @@ $screen_with_log smarthack-web.log -S smarthack-web -m -d ./fake-registration-se echo " Starting Mosquitto in a screen" sudo service mosquitto stop >/dev/null 2>&1 $screen_with_log smarthack-mqtt.log -S smarthack-mqtt -m -d mosquitto -v +echo " Starting PSK frontend in a screen" +$screen_with_log smarthack-psk.log -S smarthack-psk -m -d ./psk-frontend.py -v echo echo "======================================================" echo diff --git a/stop_flash.sh b/stop_flash.sh index a22c215..12550f5 100755 --- a/stop_flash.sh +++ b/stop_flash.sh @@ -5,3 +5,4 @@ sudo screen -S smarthack-wifi -X stuff '^C' sudo screen -S smarthack-web -X stuff '^C' sudo screen -S smarthack-smartconfig -X stuff '^C' sudo screen -S smarthack-mqtt -X stuff '^C' +sudo screen -S smarthack-psk -X stuff '^C'