需要帮助扭转这个循环

逆向工程 拆卸 C
2021-06-30 23:23:41

我很难扭转以下循环:

│       ┌─< 0x100001fea      723b           jb 0x100002027
│       │   0x100001fec      31db           xor ebx, ebx               ; ebx = 0
│       │   0x100001fee      41bc04000000   mov r12d, 4
│       │   0x100001ff4      6666662e0f1f.  nop word cs:[rax + rax]
│      ┌──> 0x100002000      418b441d00     mov eax, dword [r13 + rbx]
│      |│   0x100002005      b959b699f7     mov ecx, 0xf799b659
│      |│   0x10000200a      31c8           xor eax, ecx
│      |│   0x10000200c      418907         mov dword [r15], eax
│      |│   0x10000200f      4189041e       mov dword [r14 + rbx], eax
│      |│   0x100002013      4963dc         movsxd rbx, r12d
│      |│   0x100002016      4c8d6304       lea r12, [rbx + 4]
│      |│   0x10000201a      4c89ef         mov rdi, r13               ; const char * s
│      |│   0x10000201d      e8d0080000     call sym.imp.strlen        ; size_t strlen(const char *s)
│      |│   0x100002022      4939c4         cmp r12, rax
│      └──< 0x100002025      76d9           jbe 0x100002000
│       └─> 0x100002027      488b05d20f00.  mov rax, qword [reloc.__stack_chk_guard_0] ; [0x100003000:8]=0

r13 和 r14 包含堆上的字符串,r15 包含指向大小为 4 的缓冲区的指针。我尝试用 C 编写等效代码,其中 second_string 是 r13,return_string 是 r14,value_holder 是 r15,而 atoi_res 是 r12(d) .

int ebx = 0;

atoi_res = 4;

while(1){
    ((int *)second_string)[ebx] ^= 0xf799b659;
    *value_holder = ((int *)second_string)[ebx];
    ((int *)return_string)[ebx] = ((int *)second_string)[ebx];

    ebx = atoi_res;
    if(strlen(second_string) > 8) break;
}   

这对我来说似乎不对:

  • 没有办法跳出循环
  • 在 disas 中(我在伪代码中修复了这个),我们取消引用一个常量值 8,然后lea再次调用它。这不会是段错误吗?
  • second_string 一次被这个常量异或 4 个字节,但是当被这个异或时,应该包含的值(加载到程序的另一部分)返回乱码。

如果需要,我可以发布更多的拆解。谢谢你的帮助。

1个回答

这只是采用 r13 指向的 cstring,一次异或一个值为 0xf799b659 的双字,并存储在 r14 指向的内存中。

我认为您的困惑在于lea指令的作用。它只是加载内存地址而不是内存值本身。在这种情况下,它只是用作快速添加操作。编译器通常将它用于简单的加法或乘法,这比 add/mul/etc 指令更快。在 的情况下lea r12, [rbx + 4],这只是 r12 = rbx + 4;根本没有内存访问。rbx被用作字符串的当前字节索引,r12并被用作下一个字节索引。