-
-
[分享]Unicorn/Qemu在Windows 64位下可能存在的内存映射问题
-
发表于: 1小时前 45
-
昨天调试论坛的一个windows 64位混淆样本发生崩溃,利用windbg和agent强大的能力调试排查发现如下内容,仿真程序发生tcg崩溃。
vmpdump!tcg_op_remove_x86_64+0x2280:mov byte ptr [r11],dl ds:00000161`80000000=?? ; 另一次 r11=0x00000229`80000000
根因是 Unicorn 2.1.4 在 Windows 上分配 JIT code buffer 时只调用 VirtualAlloc(NULL, size, MEM_RESERVE),没有限制基址。x64dbg 进程里,这块 1GiB 的 reserve 被分配到了 4GiB 对齐的高位地址(两次现场分别是 0x229_0000_0000、0x161_0000_0000),导致 TCG 的 32 位相对寻址和指针计算在 +2GiB 处溢出,code_ptr 变成 base + 0x8000_0000,tcg_out8 直接把字节写到未映射区。
QEMU 历史上有一个 SPARC64 的修复:code_gen_buffer 被映射到离 text segment 8GB 远的地方,导致 TCG 生成的 call 指令超出 2GB 范围而崩溃,修复方式是强制把 buffer 映射到 2GB 以下(MAP_FIXED 到 0x60000000)。c02K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6S2L8X3c8J5L8$3W2V1i4K6u0W2k6$3!0G2k6$3I4W2M7$3!0#2M7X3y4W2i4K6u0W2j5$3!0E0i4K6u0r3N6s2u0#2M7%4c8&6i4K6u0r3k6i4S2@1k6i4u0F1j5h3I4Q4x3V1k6I4k6h3#2#2i4K6u0r3i4K6u0n7i4K6u0r3y4r3y4V1x3K6q4S2k6o6t1$3y4r3t1I4x3e0t1%4y4r3j5I4z5e0W2T1j5X3b7^5k6e0V1$3y4o6M7@1k6o6S2U0k6r3f1$3x3r3x3@1x3W2)9J5y4e0g2q4i4K6t1#2x3U0q4Q4x3V1k6W2P5r3g2U0i4K6u0W2j5H3`.`.
| 这个 2GiB 是有明确来源的常量: translate-all.c:750-751 #if defined(__x86_64__) # define MAX_CODE_GEN_BUFFER_SIZE (2 * GiB) 而 64 位宿主默认只分配 1GiB(translate-all.c:779)。我们没用 uc_ctl_set_tcg_buffer_size,全仓 grep 无调用,所以 buffer 实际是 1GiB。code_ptr 落在 base + 2GiB,已经越过了整个 1GiB reserve,原因就在于 32 位相对偏移计算发生溢出,直接落到了 2GiB 边界。 translate-all.c:999 return VirtualAlloc(NULL, size, MEM_RESERVE, PAGE_EXECUTE_READWRITE); 分配之后没有任何“必须落在 2GiB 以内”的校验;而 x86_64 TCG 的 goto_tb、jmp rel32 天然要求 code buffer 与宿主代码的距离在 ±2GiB 内。 |
最终修复正常

[招生]科锐逆向工程师培训(2026年11月13日实地,远程教学同时开班, 第57期)