从描述信息来看,本道题是关于随机数的题目,提示信息如下:
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();
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