我很难扭转以下循环:
│ ┌─< 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 个字节,但是当被这个异或时,应该包含的值(加载到程序的另一部分)返回乱码。
如果需要,我可以发布更多的拆解。谢谢你的帮助。