fl3shware/ReWired
GitHub: fl3shware/ReWired
一个以《Serial Experiments Lain》为主题的逆向工程 CTF 挑战,要求参与者分析经过 strip 处理的 Linux 二进制文件并通过 XOR 解密还原密码。
Stars: 0 | Forks: 0
解题报告
## The Wired 解题报告 ## 初始分析 该二进制文件已被 strip 处理: ``` thewired: ... stripped ``` 使用 `readelf -SW` 检查该二进制文件,发现了几个不寻常的自定义 section: ``` .no_matter_where_you_go_everyone_is_connected .im_real .why_are_you_crying_lain ``` 在不带任何参数的情况下运行该二进制文件,输出如下: ``` $ ./thewired [-] The Wired is just a higher field of reality ``` 程序还会在当前目录下写入一个名为 `lain_is_here.png` 的图像。 带参数运行该二进制文件会触发密码验证: ``` $ ./thewired hi [-] Incorrect Password ``` ## 密码验证 在 Ghidra 的反编译器中(已修改变量名),密码检查逻辑被识别如下: ``` password = strcmp(*(char **)(argv + 8), (char *)password_buf); ``` 这表明用户提供的参数会与存储在 `password_buf` 中的字符串进行比较,该字符串长度为 36 字节(包含 null 终止符): ``` byte password_buf[36]; ``` 随后,程序会检查 `password` 是否等于 `0`(即 `strcmp()` 是否返回匹配结果)。如果比较成功,它会对两块内存区域执行 XOR 操作,然后打印身份验证消息: ``` i = 0; if (password == 0) { do { decrypted_msg[i] = (&key)[i % 12] ^ (&DAT_00104060)[i]; i = i + 1; } while (i != 173); decrypted_msg[0xac] = 0; printf("%s", decrypted_msg); goto EOF; } ``` `&DAT_0012f758` 似乎包含 XOR key,因为它在三个独立的解密例程中被引用: 1. `password_buf[i] = (&DAT_0012f758)[i % 12] ^ (&DAT_00104120)[i];` 2. `decrypted_msg[i] = (&DAT_0012f758)[i % 12] ^ (&DAT_0012f6f0)[i];` 3. `decrypted_msg[i] = (&DAT_0012f758)[i % 12] ^ (&DAT_0012f720)[i];` 由此我们可以推测,程序以加密形式存储了多个字符串,并在 runtime 使用 12 字节的循环 XOR key 对其进行解密。这可能包括密码缓冲区以及执行期间显示的各种状态消息。 `password_buf[i]` 保存在 `&DAT_00104120` 内存位置: ``` index address value (hex) char 0 0x00104120 0x59 Y 1 0x00104121 0x02 . 2 0x00104122 0x31 1 3 0x00104123 0x14 . 4 0x00104124 0x42 B 5 0x00104125 0x1A . 6 0x00104126 0x3A : 7 0x00104127 0x1E . 8 0x00104128 0x1C . 9 0x00104129 0x1F . 10 0x0010412A 0x0A . 11 0x0010412B 0x31 1 12 0x0010412C 0x5D ] 13 0x0010412D 0x02 . 14 0x0010412E 0x1C . 15 0x0010412F 0x1C . 16 0x00104130 0x4F O 17 0x00104131 0x1A . 18 0x00104132 0x3A : 19 0x00104133 0x17 . 20 0x00104134 0x0B . 21 0x00104135 0x19 . 22 0x00104136 0x0A . 23 0x00104137 0x1C . 24 0x00104138 0x47 G 25 0x00104139 0x0A . 26 0x0010413A 0x0B . 27 0x0010413B 0x1B . 28 0x0010413C 0x5A Z 29 0x0010413D 0x05 . 30 0x0010413E 0x3A : 31 0x0010413F 0x1E . 32 0x00104140 0x12 . 33 0x00104141 0x00 . 34 0x00104142 0x01 . 35 0x00104143 0x6E n ``` 加密后的密码: ``` 0x59, 0x02, 0x31, 0x14, 0x42, 0x1A, 0x3A, 0x1E, 0x1C, 0x1F, 0x0A, 0x31, 0x5D, 0x02, 0x1C, 0x1C, 0x4F, 0x1A, 0x3A, 0x17, 0x0B, 0x19, 0x0A, 0x1C, 0x47, 0x0A, 0x0B, 0x1B, 0x5A, 0x05, 0x3A, 0x1E, 0x12, 0x00, 0x01, 0x6E ``` ## Key 验证 .text section 中保存着 4 个数据段,其中一个是与 key(`DAT_0012f758`)相同的数据段: ``` _DAT_0012f758 = DAT_0012f6ca; _DAT_0012f75c = DAT_0012f6ce; _DAT_0012f75e = DAT_0012f6c4; _DAT_0012f762 = DAT_0012f6c8; ``` 在反汇编器中进一步分析这些数据段,显示它同样包含 12 个字节,这意味着它就是 key(很可能是在 runtime 构建的): ``` DAT_0012f6c4 0012f6c4 65 72 73 69 undefined4 69737265h DAT_0012f6c8 0012f6c8 6f 6e undefined2 6E6Fh DAT_0012f6ca 0012f6ca 2e 67 6e 75 undefined4 756E672Eh DAT_0012f6ce 0012f6ce 2e 76 undefined2 762Eh ``` 解密 Key: ``` 0x2e, 0x67, 0x6e, 0x75, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e ``` ## 解密 Bash 脚本: ``` #!/usr/bin/env bash python3 <<'PY' data = bytes([ 0x59, 0x02, 0x31, 0x14, 0x42, 0x1A, 0x3A, 0x1E, 0x1C, 0x1F, 0x0A, 0x31, 0x5D, 0x02, 0x1C, 0x1C, 0x4F, 0x1A, 0x3A, 0x17, 0x0B, 0x19, 0x0A, 0x1C, 0x47, 0x0A, 0x0B, 0x1B, 0x5A, 0x05, 0x3A, 0x1E, 0x12, 0x00, 0x01, 0x6E ]) key = bytes([ 0x2e, 0x67, 0x6e, 0x75, 0x2e, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e ]) out = bytearray(len(data)) for i in range(len(data)): out[i] = data[i] ^ key[i % len(key)] print("BYTES:", list(out)) print("ASCII:", out.decode(errors="replace")) PY ``` 输出: ``` $ ./script.sh BYTES: [119, 101, 95, 97, 108, 108, 95, 108, 111, 118, 101, 95, 115, 101, 114, 105, 97, 108, 95, 101, 120, 112, 101, 114, 105, 109, 101, 110, 116, 115, 95, 108, 97, 105, 110, 0] ASCII: we_all_love_serial_experiments_lain ``` ## 反调试技术 此外,.text section 中存在使用反调试技术的迹象,该技术可以检测在 `FUN_00101380`(即身份验证逻辑函数)内部放置的任何 INT 3 (0xCC) 指令。 ``` do { if (FUN_00101380[*plVar1] == (code)0xcc) { ... do { ... } ``` ## 解决方案 **we_all_love_serial_experiments_lain** ``` $ ./thewired we_all_love_serial_experiments_lain ================================ THE WIRED ================================ ACCESS GRANTED Welcome to The Wired. Everyone is connected. [ONLINE] ``` ## 未来改进 该二进制文件在保护其逻辑的方式上存在几个弱点。key 的存储方式实际上可以恢复为明文,这使得它很容易被提取并用于解密数据。除此之外,尽管存在反调试检查,但它并不能真正阻止静态分析,因为只需检查二进制文件,一切仍然可以被完全重构。标签:x86-64, 云资产清单, 客户端加密, 网络安全, 逆向工具, 逆向工程, 隐私保护