reverse
rtMaze
首先打开题目发现只有一个linux脚本和bin文件. 根据脚本里的QEMU以及对bin进行file后, 可以推断是一个固件逆向之类的题目, 且架构为ARM.
1 | if [ ! -f "sd.bin" ]; then |
运行qemu.sh后, 输入get_flag会发现要先解一个迷宫, 我输入一个’a’发现就可以, 但是到后面会发现这样投机取巧是不行的, 正确的解法如下:
使用IDA打开rmMaze.bin, 将基址设为0x60010000.
由LDR PC, =sub_6001E684
可知固件入口函数是在sub_6001E684.
固件里的函数太多, 直接搜索flag字符串:
在字符串input your flag: />
这里, 发现有xref, 跳转到sub_600100B4
:
基本可以判断sub_600100B4
就是我们要找的核心函数:
伪代码如下:
1 | int __fastcall sub_600100B4(int a1) |
首先是读取我们的输入到Str, 如下:
1 | printf_60013F3C("input your flag: />"); |
然后会判断Str长度是否为40:
1 | if ( strlen_6005AA98((int)Str) == 40 ) |
下一步是用0x61
填充我们在解迷宫那一步输入的key为48字节:
1 | v5 = strlen_6005AA98(a1); |
接下来的两个do-while循环在动态调试后发现就是一个memcpy:
1 | v9 = 0; |
接下来就是最最核心的加密环节:
1 | v16 = Str_v34; |
其中, v22 = v21 - 12 * (((int)((unsigned __int64)(v21 * (__int64)(int)&MEMORY[0x2AAAAAAB]) >> 32) >> 1) - (v21 >> 31));
其实就是v22 = v12 % 12;
因为我改了一下某个数组的lvar type
影响这里识别不出来了.
很明显这里的sub_60010AB8
是加密函数, 在加密之前的do-while会将key_v35里的数据复制到v31中, 每次sub_60010AB8
加密Str_v34的两个DWORD, 可以大胆猜测sub_60010AB8
里面和TEA算法有关.
1 | ROM:60010AB8 ; unsigned int *__fastcall sub_60010AB8(unsigned int *result, int) |
这里就不得不吐槽一下IDA的F5, 我第一次也是直接用F5看的加密函数sub_60010AB8
, 但是从a2 + 4 * ((i >> 11) & 3))
可以发现a2必须是一个13个元素的DWORD数组, 这就很反直觉, 在动态调试时候也证实a2是一个4元素的DWORD数组.
1 | unsigned int *__fastcall sub_60010AB8(unsigned int *result, int a2) |
所以我通过动态调试和读汇编代码(主要还是猜), 逆出了正确的加密方法:
1 | void encrypt(uint32_t *v, uint32_t *k) |
在加密结束之后, 就到了判断和输出结果的地方了:
1 | v24 = v32; |
可以看到是将加密后的结果和v32进行比较, v32在前面已经进行初始化了:
1 | v32[0] = 0xBD7CA3FA; |
由此, 大体的逻辑我们以及找到, 下面就是解密环节了:
1 |
|
计算出flag:
完成: