在汇编中,如何在调试器的3字节空间中添加5字节指令

时间:2016-11-01 15:28:57

标签: assembly x86

我正在尝试更改此行

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                                    

是否可以在调试器中对预编译的程序执行此操作?

2 个答案:

答案 0 :(得分:5)

在32位代码中(没有到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并完全跳转到新函数将放在函数

之前的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