babyre
附件
- babygame
分析
IDA打开,定位到main函数:
1 | void __fastcall main(int a1, char **a2, char **a3) |
可以看到password1是走迷宫之类的一关, 根据switch里面的操作确定出了迷宫的长宽, 最开始以为就是一个平面的走迷宫, 最后发现flag提交不上去(password2、3都正确)才知道是一个立体的5x5x6迷宫.
那么迷宫部分就不再多说了, 接着看password2. 其中 sub_561F47600C22
是加密过程, sub_561F47600F67
用于检测, 密文是字符串 sctf_9102
.
1 | void __fastcall sub_561F47600C22(const char *a1, __int64 a2) |
其中的明文左移6位进行或运算、AND 0x3F取后六位、四字节为一组与base64算法有很多相似之处, 另外, dword_561F47601740
存放着加密使用到的Table.
懒得写脚本了, 直接在py命令行找出 sctf_9102
对应的Table值了.
1 | import libnum |
接下来通过上面的值 [28, 54, 13, 52, 25, 37, 60, 57, 12, 19, 0, 50,]
找出其在Table中的索引值组合成字符串就可以了(见解密代码中的decrypt2函数).
最后看password3, 核心代码就在一个 sub_561F47600FFA
函数里面, v8是比较用的密文, 该函数首先使用 sub_561F4760078A
将 a1 每四个字节为一组并使用 BYTE_SWAP 在组内进行逆序存储到v10的0至3号索引处.
1 | __int64 __fastcall sub_561F47600FFA(char *a1) |
随后, 循环加密v10并将其进行拓展, 从4号索引到29号索引就是拓展出的. 拓展的规律是v10[i] = sub_561F4760143B(v10[i - 4], v10[i - 3], v10[i - 2], v10[i - 1])
. 最后再次将v10的26至29号索引对应的值打乱到v9中, 随即将v8、v9进行比较.
1 | __int64 __fastcall sub_55555540143B(int a1, int a2, int a3, unsigned int a4) |
对于v10的索引为4到29元素, 每个值只与它前面四个值有关, 比如 v10[29] = v10[25] ^ sub_561F47601464(v10[24], v10[23], v10[22])
、v10[4] = v10[3] ^ sub_561F47601464(v10[2], v10[1], v10[0])
. sub_561F47601464
只负责计算出最外层xor所使用的key无需逆向. 所以只需模拟 sub_55555540143B
和 sub_561F47601464
即可. 另外不难看出, v10[25] = v10[29] ^ sub_561F47601464(v10[24], v10[23], v10[22])
、v10[3] = v10[4] ^ sub_561F47601464(v10[2], v10[1], v10[0])
.
解密代码
因为是C++代码, 而且用到了IDA提供的头文件defs.h
, 所以需要将头文件复制到C++代码同一目录下或自己设置C++编译器寻找头文件的规则.
1 | /* |