【Pwn#0x07】THUCTF 2022 babystack_level3
比赛链接:THUCTF2022
(报名了比赛的账号现在(2022/11/15)还可以下载附件和开启实例)
学习了一下ret2dlresolve的基础。
在NO RELRO的时候,程序的.dynamic节被存储在RW的地址空间,而其中的一个指针strtab指向的是动态链接的符号表。
我们可以把这个符号表提取出来,修改一下,存在一个别的地方,然后把.dynamic里面的指针修改到那个地方。然后程序就会使用我们的假字符串表来进行动态符号解析!
题目分析
整个程序,一个输出函数都没有,但是保护只开了NX。很显然是要用ret2dlresolve来做。(实际上做题目的时候我还没学ret2dlresolve,然后去网上搜没有输出函数怎么打搜到的哈哈哈)
漏洞是可以在一个固定地址读入0x110个字节,并且可以栈溢出0x10个字节,也就是刚好把返回地址给覆盖掉。
那么思路就是
- 把rop chain读到固定地址那里,然后stack pivot过去
- rop chain是构造一个假的dynstr表(比如把read改成system),然后把.dynamic那里的指针改成假的dynstr,并且跳转到plt来触发动态符号解析,来调用想要的函数。
大失败原因
这题我本地打通之后,花了整整两天才在在线环境上打通,并且主要是靠出题人dylanyang师傅超级善良好心的debug帮助。
我们知道,栈地址是向下增长的,因此之前调用过的函数,其栈帧会被新的函数给覆盖,或者说重用。
在ROP中也是这个道理,虽然ROP链是按照调用顺序向上增长的,然而如果调用的是函数,函数的栈帧将会向下把一些东西给覆盖掉。
而我是如何踩进这个坑的呢?
在经典的stack pivot中,新的ROP Chain的第一个8字是会被当作saved rbp来pop给rbp的,所以是无用的一个八字。(如果你不想第二次stack pivot了)
然后我是一个非常懒惰的人,当我发现”/bin/sh\x00”正好是八个字节的时候,我心动了。把这八个字节填到新ROP Chain的开头不是正正好好吗!?
然后就寄了!因为在调用后续函数如execv、do_system的时候,栈帧会往下增长并且把这八个字节给覆盖掉!
以下是调试的截图,可以看到在执行完posix_spawnattr_init之后,我提前存在这边的”ABCDEFGH”突然变成了0……
解决方法实在是很简单,换一个位置存”/bin/sh”字符串就行。
但是不知道这个问题的话,自己来调试实在是看不出什么东西。真的是我遇到最奇怪的情况了……
EXP
1 | from pwn import * |