lotto - pwnable
题目
题目是一个猜乐透号码的游戏,并且给出了源代码。
先运行,看看游戏怎么运行的:
输入 1 开启游戏,输入6位号码。程序进行判断,如此循环进行。
分析
6位数字乐透数字,说实话也不多,可以利用脚本自动输入。但是在脚本输入全部的组合后,仍然没有得到flag。难道乐透数字不是纯数字或者出现什么意外?
我们来看看源码中有没有什么提示。
第一个红框是lotto号码的生成。为什么不是上一行read,才是生成lotto号码对应代码段?没有lotto的初始值是由read中写入的,然后循环遍历地将lotto号码提出出来进行处理,最终lotto号码由ascii码表中1~45的字符组成。
第二个红框则是检测输入值submit 与 lotto号码。一共循环遍历6*6次,而match = 6则中奖了!!!为什么一个6位的乐透号码,需要循环36次???
这里就存在一个逻辑到代码实现的漏洞。逻辑上的应该只要输入的号码都包含在乐透号码中则中奖。(乐透号码:123456,提交号码:654321➡中奖)
从代码实现来看,遍历36次,如果match = 6就中奖。(乐透号码:123456,提交号码:111111➡中奖) 那么我们输入乐透号码中的任意一个*6,则让match = 6。
前面我们知道了lotto是由ascii中的1~45组成。还有一点需要注意,每一次重新开始游戏都会生成一个新的lotto。也就是说我们不能确定每一次的lotto号码。
int main(int argc, char* argv[]){
// menu
unsigned int menu;
while(1){
printf("- Select Menu -\n");
printf("1. Play Lotto\n");
printf("2. Help\n");
printf("3. Exit\n");
scanf("%d", &menu);
switch(menu){
case 1:
play();//循环调用play()
break;
case 2:
help();
break;
case 3:
printf("bye\n");
return 0;
default:
printf("invalid menu\n");
break;
}
}
return 0;
}
但是问题也不大,我们只要循环输入同一串字符串,总会出现匹配的。只是时间与你的运气相关,我也尝试过编写脚本输入,但是总是输出不了flag值,索性作罢,反正运气好几次就出来了。
// 我失败脚本输出日志
lotto@prowl:/tmp$ python skye.py
[+] Starting local process '/home/lotto/lotto': pid 381272
- Select Menu -
1. Play Lotto
2. Help
3. Exit
Submit your 6 lotto bytes :
Lotto Start!
// 就是这里输出不了flag里面的内容
/bin/cat: flag: Is a directory
- Select Menu -
1. Play Lotto
2. Help
3. Exit
[*] Stopped process '/home/lotto/lotto' (pid 381272)
lotto@prowl:/tmp$
ascii表中1~45,从33开始为可见字符,那我们就选择33吧(!)。也就是我们输入的字符串是!!!!!!