0x01 分析
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; }
|
rand标准用法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #include <stdio.h> #include <stdlib.h> #include <time.h>
int main() { int i, n; time_t t; n = 5; srand((unsigned) time(&t));
for( i = 0 ; i < n ; i++ ) { printf("%d\n", rand() % 50); } return(0); }
|
- 给srand()提供一个种子,否则默认为1;
- rand()产生伪随机数
0x02 利用思路
程序中并没有先调用srand并提供一个变化的种子,因此程序默认执行srand(1),那么每次执行rand函数产生的数就是固定的,使用gdb调试找到那个数便可以要过检查。
0x03 调试
main:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| gdb-peda$ disas main 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 ... 0x0000000000400665 <+113>: leave 0x0000000000400666 <+114>: ret End of assembler dump.
|
可以发现rand函数的返回值首先存储在eax,将断点下在0x0000000000400606,在此处读出eax的值便可以得到“随机数”,而input xor eax == 0xdeadbeef
便会执行system("/bin/cat flag")
执行,那么input = 0xdeadbeef xor eax
即可得到应该输入的数。