0%

CTF-逆向简单入门题

simple

x64的ELF,主函数反编译

xor

xor函数是将两个数组异或后放回第二个数组arr内,同时判断flag是否正确有两个条件,一个是长度为26字节,一个是异或后数组与src相等。因此将src和arr异或即可解出原来的字符串。

arr

用IDA中的Edit->Export Data或者Shift+E导出arr和src,编写脚本异或

1
2
3
for i in range(len(src)):
flag[i] = src[i] ^ arr[i]
print(str(flag))

或者换一种思路,利用程序本身的异或,通过将src的字符串作为输入,通过调试观察异或后输出的字符串得到flag。

disasm

直接观察反汇编看到,调用前arr地址进了esi寄存器。只要输入src字符串的内容,在调用结束后(0x4006E0)处下断点,打印出esi所指的字符串即可得到答案。gdb命令如下

1
2
3
4
break 0x4006E0
run
printf "%s",(char*)&esi
#或者用$esi查看地址,再用 x/26sb 查看字符串

medium

x64的ELF,主函数反编译

medium

程序的逻辑是,输入8轮数字,通过与一个生成的1000以内的随机数比较判断是否正确,最后输出的即为9个生成的随机数。

乍一看好像答案总是会变化的,但是实际上rand()生成的是伪随机数,例如使用线性同余法生成。在程序中注意到有srand(0x7E3u);设置了固定的随机数种子,因此结果也是固定的。用C还原程序实现即可得到答案

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

int main(int argc, char const *argv[])
{
/* code */
srand(0x7E3u);
printf("flag{");
for(int i=0;i<=8;i++){
printf("%x",(int)(rand()%1000));
}
printf("}\n");
return 0;
}

当然同样可以用调试的方法,通过在每轮计算的结果处下断点并且打印出对应数字解出flag,具体过程不再赘述。