从描述信息来看,本道题是关于随机数的题目,提示信息如下:

​ ssh登上查看文件及权限:

​ 查看random.c源代码并反汇编后分析:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>

int main(){
unsigned int random;
random = rand(); // random value!

unsigned int key=0;
scanf("%d", &key);

if( (key ^ random) == 0xdeadbeef ){
printf("Good!\n");
system("/bin/cat flag");
return 0;
}

printf("Wrong, maybe you should try 2^32 cases.\n");
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
Dump of assembler code for function main:
0x00000000004005f4 <+0>: push rbp
0x00000000004005f5 <+1>: mov rbp,rsp
0x00000000004005f8 <+4>: sub rsp,0x10
0x00000000004005fc <+8>: mov eax,0x0
0x0000000000400601 <+13>: call 0x400500 <rand@plt>
0x0000000000400606 <+18>: mov DWORD PTR [rbp-0x4],eax
0x0000000000400609 <+21>: mov DWORD PTR [rbp-0x8],0x0
0x0000000000400610 <+28>: mov eax,0x400760
0x0000000000400615 <+33>: lea rdx,[rbp-0x8]
0x0000000000400619 <+37>: mov rsi,rdx
0x000000000040061c <+40>: mov rdi,rax
0x000000000040061f <+43>: mov eax,0x0
0x0000000000400624 <+48>: call 0x4004f0 <__isoc99_scanf@plt>
0x0000000000400629 <+53>: mov eax,DWORD PTR [rbp-0x8]
=> 0x000000000040062c <+56>: xor eax,DWORD PTR [rbp-0x4]
0x000000000040062f <+59>: cmp eax,0xdeadbeef
0x0000000000400634 <+64>: jne 0x400656 <main+98>
0x0000000000400636 <+66>: mov edi,0x400763
0x000000000040063b <+71>: call 0x4004c0 <puts@plt>
0x0000000000400640 <+76>: mov edi,0x400769
0x0000000000400645 <+81>: mov eax,0x0
0x000000000040064a <+86>: call 0x4004d0 <system@plt>
0x000000000040064f <+91>: mov eax,0x0
0x0000000000400654 <+96>: jmp 0x400665 <main+113>
0x0000000000400656 <+98>: mov edi,0x400778
0x000000000040065b <+103>: call 0x4004c0 <puts@plt>
0x0000000000400660 <+108>: mov eax,0x0
0x0000000000400665 <+113>: leave
0x0000000000400666 <+114>: ret
End of assembler dump.

分析:

 1.  cat flag条件是随机数random和key异或后未0xdeadbeef。
 2.  key通过scanf()接收的,random为随机生成的四字节数,最开始想到是否可以给key赋值8个字节来覆盖random,但注意到scanf("%d",&key)这里使用了%d坐限制,使得key只能被赋值为一个DWORD(四字节),所以这个方案pass。
 3.  继续分析发现,该题目并不是一个严格意义上的漏洞题,重点在于随机数random的生成。写过C代码就知道,rand()是伪随机的,正常使用情况下需要在rand()之前生成一个随机数种子(一般使用但钱时间作为随机数种子)作为rand()的参数来保证准确生成随机数。而这里直接使用rand(),随机数种子就是系统默认的1,会导致每次生成的random都是一个数。

​ 所以cat flag就简单了,调试一下random程序,得到变量random的值,然后逆运算即可得到key的值,random值存储在rbp-0x4处,本地调试和ssh远程调试得到的值都为:0x6b8b4567

​ key=0xdeadbeef ^ 0x6b8b4567 =3039230856