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

Assembly 在汇编中,如何在调试器的3字节空间中添加5字节指令,assembly,x86,red-zone,Assembly,X86,Red Zone,我想换一条线 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 0041DE

我想换一条线

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 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
但3字节的指令占用5字节,并溢出到它下面的两个地址:

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
可以在调试器中对预编译程序执行此操作吗

在32位代码中(无需关闭),您可以将imm8常量移动到具有3个字节的寄存器中(效率低下):

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
push   10       ; 2B
pop    eax      ; 1B
您还可以将
1
放入3B中的寄存器中

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
xor    eax, eax  ; 2B
inc    eax       ; 1B
或者,鉴于任何其他已知内容的登记册:

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
lea    eax, [ecx+/-imm8]   ; 3B
其他代码/代码大小优化技巧:

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
xor    eax,eax   ; 2B
cdq              ; 1B to zero edx as well

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
其中许多代码也适用于16位和64位代码。例如,请参见my.

在32位代码中(没有可关闭的代码),您可以使用3个字节将imm8常量移动到寄存器中(效率低下):

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
push   10       ; 2B
pop    eax      ; 1B
您还可以将
1
放入3B中的寄存器中

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
xor    eax, eax  ; 2B
inc    eax       ; 1B
或者,鉴于任何其他已知内容的登记册:

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
lea    eax, [ecx+/-imm8]   ; 3B
其他代码/代码大小优化技巧:

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
xor    eax,eax   ; 2B
cdq              ; 1B to zero edx as well

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    

其中许多代码也适用于16位和64位代码。例如,请参见my。

如果在3字节区域周围还有一些空格,则可以将新代码放在那里,然后执行一次近似跳转,然后执行所需操作并跳回

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
该技术用于在Windows中实现热修补。它是通过将
MOV EDI,EDI
作为2字节
NOP
放在函数的开头来完成的。然后,当需要修补函数时,它们会用
JMP$-5
替换该“NOP”,并在函数之前的5个字节中跳转到新函数

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
  • 0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
    0041DE96 | 0C 83                    | or al,83                                    
    0041DE98 | F8                       | clc                                    
    
  • 0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
    0041DE96 | 0C 83                    | or al,83                                    
    0041DE98 | F8                       | clc                                    
    
所以现在基本上你需要改变

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
mov eax, dword ptr ds:[esi+64]
add esp, C
cmp eax, 1

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    

使用此方法,您可以将原始指令替换为任何指令序列。但是,对于设置小值,那么Peter的解决方案更好

如果在3字节区域周围留有一些空格,您可以将新代码放在那里并进行一次近距离跳转,做您需要的并跳回去

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
该技术用于在Windows中实现热修补。它是通过将
MOV EDI,EDI
作为2字节
NOP
放在函数的开头来完成的。然后,当需要修补函数时,它们会用
JMP$-5
替换该“NOP”,并在函数之前的5个字节中跳转到新函数

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
  • 0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
    0041DE96 | 0C 83                    | or al,83                                    
    0041DE98 | F8                       | clc                                    
    
  • 0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
    0041DE96 | 0C 83                    | or al,83                                    
    0041DE98 | F8                       | clc                                    
    
所以现在基本上你需要改变

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    
mov eax, dword ptr ds:[esi+64]
add esp, C
cmp eax, 1

0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc                                    

使用此方法,您可以将原始指令替换为任何指令序列。但是,对于设置较小的值,Peter的解决方案更好

no。在插入点之后,如果不修改代码的其余部分,就可以将所有内容移动2个字节。或者希望其他寄存器包含一个零,这样就不需要在其中嵌入32位的“零”。我需要寄存器中不是零的任何数字。为什么不
xor eax,eax
?这将使寄存器归零,只使用一两个字节。我想要相反的结果。寄存器中的非零数字。我只需要你的想法。只需添加任何其他寄存器。我不小心复制了超过0,在上面的例子中我是指10。否。在插入点之后,必须对代码的其余部分进行黑客攻击,将所有内容移动2个字节。或者希望其他寄存器包含一个零,这样就不需要在其中嵌入32位的“零”。我需要寄存器中不是零的任何数字。为什么不
xor eax,eax
?这将使寄存器归零,只使用一两个字节。我想要相反的结果。寄存器中的非零数字。我只需要你的想法。只需添加任何其他寄存器。我无意中复制了超过0,在上面的示例中我是指10。您在注释中说,如果您希望ecx=eax,则比MOV短,但您在代码中使用了通用的xchg eax,r32。也许你的意思是xchg eax,ecx来匹配评论。@MichaelPetch:谢谢,我先写了ecx,然后把它改成了泛型。但我认为你是对的,在评论中讨论一个具体的例子会更好。(我忘记更新了,xD)前两个看起来很有希望,我明天醒来时必须试试。我可以只增加eax,因为我知道它将为零,但我也可以使用一个寄存器来保存地址(我知道它不会是负数),就像上面的esi一样。现在有人让我思考了很多方法。你在评论中说,如果你想要ecx=eax,那么比MOV短,但是你在代码中使用了通用的xchg-eax,r32。也许你的意思是xchg eax,ecx来匹配评论。@MichaelPetch:谢谢,我先写了ecx,然后把它改成了泛型。但我认为你是对的,在评论中讨论一个具体的例子会更好。(我忘记更新了,xD)前两个看起来很有希望,我明天醒来时必须试试。我可以只增加eax,因为我知道它将为零,但我也可以使用一个寄存器来保存地址(我知道它不会是负数),就像上面的esi一样。现在有很多方法可以做到,有人让我思考,“做一个近跳转,”--一个近32位的跳转不适合3个字节。也许你的意思是短跳转(2字节)。@ecm是的。我认为32位跳转是“远跳转”和“近跳转”——近32位跳转不适合3个字节。也许你的意思是短跳转(2字节)。@ecm是的。我以为32位跳远就是跳远
0041DE91 | B8 0A 00 00 00           | mov eax,10                                    
0041DE96 | 0C 83                    | or al,83                                    
0041DE98 | F8                       | clc