通过基于虚拟机的混淆保护了keygenme,这是一种基于Miasm动态符号执行(DSE)的解决方案,可自动反汇编VM字节码。
几周前,我参加了法国网络安全挑战赛(简称FCSC)。由法国国家网络安全局(ANSSI)组建的Jeopardy CTF,以选择将在2020年底参加欧洲网络安全挑战赛(ECSC)的法国团队。
在提出的挑战(加密,反向,pwn,网络,取证,硬件)中,我真的很喜欢做一个名为keykoolol的反向追踪。
挑战的目的是分析一个以用户名和序列作为输入的二进制文件,并为其编写一个密钥。然后,我们必须使用此密钥生成器为多个用户名生成良好的序列以获取标志。
二进制文件是ELF x86-64可执行文件,非常小,奇热只有14KB。
$ file keykoolol keykoolol: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 3.2.0, BuildID[sha1]=1422aa3ad6edad4cc689ec6ed5d9fd4e6263cd72, stripped
如果使用伪输入执行它,则会得到以下输出。
$ ./keykoolol [+] Username: aaaaaa [+] Serial: bbbbbbbbb [!] Incorrect serial.
让我们在我们最喜欢的反汇编程序中将其打开,以查看代码的外观。这是IDA反编译器的main函数。
以上是反编译器输出的IDAmain函数,如你所见,main函数的代码易于阅读,并包含以下步骤。
1. 从stdin读取用户名和序列;
2. 删除两个输入的换行符;
3. 调用包含6个参数的函数(此处重命名为check),包括用户名,序列及其各自的长度。
4. 如果函数的返回值不同于0,则说明该用户名/序列是正确的。
现在,让我们看一下函数check。
串口校验函数分析
在IDA反编译器中打开check函数时,我们注意到的第一件事是IDA对其进行反编译所花费的时间。
如果我们查看反汇编控制流程图,我们会很快理解为什么,函数非常强大!
让我们深入研究代码,以了解函数的结构。
函数首先在0x203040处初始化前40个字节,在0x203080到0处初始化前2048个字节。
然后,它依次复制:
1. 将位于0x24E0(函数的第一个参数)处的缓冲区发送到地址0x203080;
2. 用户名缓冲区地址为0x203490(0x203080 + 1024 + 16);
3. 用户名缓冲区地址加16之后的序列缓冲区。
然后,它进入一个无限循环,并从0x24E0(现在是0x203080)处的缓冲区读取一个32位的整数。
读取32位整数中最重要的字节,并根据该值将控制流移至交换机的256个条目中的一个。如果仔细看一下交换机的不同分支,我们几乎可以在交换机的每个分支中观察到以下代码模式:
1. 在0x203040和0x203080之间的内存上进行一个简单的操作;
2. 一个变量增加了4(这恰好是在输入开关之前读取的整数的大小);
3. 如果开关值不等于255,则控制流程返回while循环的开始。
这种结构使我们得出的结论是,我们在本文