PWN刷题记录——guess_num
guess_num:[下载地址]
题目分析
拿到题目先跑一下康一康
是一个猜数的游戏,随便输几次数跑一下,不料第二回合就GG了
丢到IDA里打探一下
通过分析源代码发现程序会随机产生10个随机数分布在10个回合中,只要每个回合的数字都猜对就可以进入子函数直接获取flag
对程序进行安全机制检查发现,程序所有保护都开启了,咋办?有点慌、、
由于有了堆栈保护,所以程序不能通过栈溢出返回到sub_C3E()函数,这条路子就、、死心吧,只能另寻他路
既然不能控制程序返回地址,那么我们考虑一下是不是可以控制一下栈上的数据,比如控制用来产生随机数种子得到srand函数。我们知道,srand函数所产生的随机种子是由seed的值确定的,seed一样,rand函数产生的伪随机数值也会一样。
先看一下程序中的seed是怎么来的
看样子是没法直接得知seed的具体值,那么就只能直接开干了
在IDA里面查看main函数的栈空间可以得知
程序中的变量v7即栈空间中的var_30,它在栈中到变量seed的偏移量为0x20
利用思路
由于程序中gets函数没有对输入大小进行限制,所以我们可以利用gets函数使v7溢出覆盖到变量seed,使得seed为我们指定的固定值,这样就可以使得每一轮的“随机数”都可以被我们准确地“猜到”,从而获得flag
EXP编写
第一种EXP(笨方法)
我们设置seed的值为1,那么rand随机出来的10个伪随机数就是固定不变的,可以使用C语言代码先把这10个随机数求出来,然后在exp脚本中打表使用
求随机数的C语言代码
1 |
|
exp脚本
1 | from pwn import * |
脚本执行便可获得flag: cyberpeace{4e3336a2bfd434405154107ca1240212}
第二种EXP(利用python库)
后来在搜索题解的时候,意识到可以直接使用python标准库中自带的ctypes模块进行python和c的混合编程
那么我们的exp可以这样写
1 | from pwn import * |
运行,同样也可以得到flag
参考链接: