我正在尝试更改此行
0041DE91 | 8B 46 64 | mov eax,dword ptr ds:[esi+64]
0041DE94 | 83 C4 0C | add esp,C
0041DE97 | 83 F8 01 | cmp eax,1
到
0041DE91 | mov eax, 10
但是3个字节的指令占用5个字节并溢出到它下面的两个地址:
0041DE91 | B8 0A 00 00 00 | mov eax,10
0041DE96 | 0C 83 | or al,83
0041DE98 | F8 | clc
是否可以在调试器中对预编译的程序执行此操作?
答案 0 :(得分:5)
在32位代码中(没有red-zone到clobber)你可以用3个字节将imm8常量移动到寄存器中(效率低下):
push 10 ; 2B
pop eax ; 1B
您还可以将1
放入3B
xor eax, eax ; 2B
inc eax ; 1B
或者,给出已知内容的任何其他注册:
lea eax, [ecx+/-imm8] ; 3B
其他代码 - 高尔夫/代码大小优化技巧:
xor eax,eax ; 2B
cdq ; 1B to zero edx as well
xchg eax, ecx ; 1B. Shorter than MOV if you want ecx=eax and can trash eax (or both parts are actually useful)
其中许多也适用于16位和64位代码。例如,请参阅我的adler32 in 32B of x86-64 machine code, and the x86-16 version。
答案 1 :(得分:4)
如果在3字节空间周围留有一些空格,你可以将新代码放在那里并进行近距离跳跃,做你需要的并跳回来。
该技术用于在Windows中实现热补丁。通过将MOV EDI, EDI
作为2字节NOP
放在函数的开头来完成。然后当需要修补函数时,它们会替换#34; NOP"使用JMP $-5
并完全跳转到新函数将放在函数
所以现在基本上你需要改变
mov eax, dword ptr ds:[esi+64]
add esp, C
cmp eax, 1
到
jmp new_instruction
continue:
add esp, C
cmp eax, 1
...
new_instruction:
move eax, 10
jmp continue