damCTF- rev/schlage (beginner) __WP
damCTF- rev/schlage (beginner) __WP
先用
可以看到是64位的ELF文件,debug信息还在file
命令查看接着使用radare2反汇编
使用VV
命令进入视图模式
我们的任务是解锁,这里又5把锁
关键的代码是这5个函数
Pin1
第三把锁比较简单,来看第一把锁
也可以在视图模式按o
再输入函数旁边的字母
这是一个循环操作,共五次,每一次将两个数字异或,最后和0xee
比较,相同则成功rbp+rax-0x0e
即指向开头移入地址的5个数
0x3e xor 0x57 xor 0x81 xor 0xd3 xor 0x 25 xor 0x 93 xor 0xee
结果为0x99
jle:
JNB al, bl ;al里的内容不等于bl时跳转
JBE al, bl ;al里的内容小于或等于bl时跳转
;同理,JGB是大于或等于,JLE是小于或等于
;A(above)大于,B(below)小于,E(equal)等于,用于比较无符号数
;G(great)大于,L(less than)小于, E(equal)等于,用于比较带符号数
pin5
#### srand() 第5把锁用到了`srand()`和`rand()`两个函数。根据种子产生随机数
- 给srand()提供一个种子,它是一个unsigned int类型;
- 调用rand(),它会根据提供给srand()的种子值返回一个随机数(在0到RAND_MAX之间);
也就是,一个种子,它所产生的随机数是固定的。
1 | unsigned int a=1111638594; //0x42424242 |
输入rand()
生成的随机数即可,即为1413036362
lea
lea是“load effective address”的缩写,简单的说,lea指令可以用来将一个内存地址直接
赋给目的操作数,例如:lea eax,[ebx+8]就是将ebx+8这个值直接赋给eax,而不是把ebx+8处的内存地址里
的数据
赋给eax。而mov指令则恰恰相反,例如:mov eax,[ebx+8]则是把内存地址为ebx+8处的数据赋给eax。
pin2
查看汇编代码可以知道,pin2根据实际输出了一个种子,根据种子调用`rand() `即可。这个种子下一把锁还要用到,再一次调用rand()
,获得的是第二个随机数。
pin4
我认为这是最难得了,主要是编程。
直接看r2 太复杂,所以我用IDA PRO,然后F5反编译。
1 | puts("What's your favorite sentence?"); |
注释已经写在代码中,接下来,就是编程破解得到符合的字符串。
1 |
|
输入字符,成功解锁。
最后flag文件在远程服务器,但链接时间很短,可能需要脚本自动化发送,有点小难😢
fgets()
C 库函数 char *fgets(char *str, int n, FILE *stream) 从指定的流 stream 读取一行,并把它存储在 str 所指向的字符串内。当读取 (n-1) 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止,具体视情况而定。
strlen()
C 库函数 size_t strlen(const char *str) 计算字符串 str 的长度,直到空结束字符,但不包括空结束字符。
结束语
不愧是新手题,只是最后编程花了我不少时间。