我需要写一些我将写入另一个过程的地址空间(已经在运行(
本质上,我想做的是每次调用此组件时,它将比较堆栈的值与预定义值,然后如果它匹配预定的值,我想调用一个函数,它的指针将很难被编码到组件中,如果没有,我希望大会本质上什么都不做,所以返回。
到目前为止,我有以下操作(只是要发布X86的摘要以使事情变得简单(
mov eax, [esp+0x04] ; this is the value from the stack
cmp eax, 0x01 ; this is the predefined value I am comparing to
如上所述,如果EAX中的值匹配0x01,我希望它跳到函数(预定义的指针,因此可以进行硬码进入汇编(,否则我希望sub例程返回。问题是我不使用标签,我不知道该怎么做,我不相信我将能够使用,因为这将在另一个过程的上下文中执行,因此地址不会从0开始(对于组件,我将打电话。(
我听说您可以相对跳跃,但是我在这些行实施某些方面遇到了麻烦。
有人可以向我展示如何使用相对跳跃或其他方法来实现这一目标?
您正在将其注入已经运行的过程中,因此在复制此过程时,您肯定有可用的源和目标地址。
x86条件分支可提供32位rel32
位移,相对于分支指令的 END 。即,如果分支条件为真,则它们在常规设置RIP =本指令结束后进行RIP += rel32
。
jz rel32
是使有条件的尾随到另一个功能的好方法,或者掉入ret
指令。
有关OPCODES,请参见https://www.felixcloutier.com/x86/jcc。$确切地在NASM中工作?有一个手动编码call rel32
的示例,以及由此产生的机器代码。
还将跳跃命令写入x86-64二进制文件,以进行另一个Q& a关于分支编码。
mov eax, [esp+0x04]
cmp eax, 1
db 0x0f, 0x84 ; opcode for je rel32
branch_offset: dd 0 ; the rel32 itself
; fall-through path
ret
将其组装到机器代码中后,您应该编写代码以修改该dword(又称int32_t
(0一旦知道目标过程中的源和目标地址。0
只是一个占位符。
(je +0
将仅转到ZF是否设置的下一个指令。(
,或者如果您知道源地址和目标地址,则可以在组装时间为您完成数学:
bits 64
org 0x12345 ; this block of code will start at this address
cmp dword [rsp+4], 1
je 0x123456
ret
将其组装成平坦的二进制文件,给了我们:
$ yasm -f bin -l /dev/stdout jz.asm
1 %line 1+1 jz.asm
2 [bits 64]
3 [org 0x12345]
4
5 00000000 837C240401 cmp dword [rsp+4], 1
6 00000005 0F84FD101100 je 0x123456
7 0000000B C3 ret
8
9 0000000C B854230100 mov eax, $
ORG
指令似乎不适用于NASM,只有Yasm。我不知道为什么。
mov
指令在那里查看汇编器认为其组装的地址。使用NASM,我们获得B8[0C000000]
,而不是预期的54 23 01 00
作为mov
指令的直接(其自己的地址(。
如果您提前知道相对位移是一个组装时间常数(但不是绝对地址(,那也很好。
在NASM语法中,je +0x555555
汇编到0F 84 55 55 55 00
。
,但不是yasm:在yasm +0x555555
中只是绝对地址0x555555
作为分支目标。
相关:
- 如何为MASM中接近直接的亲戚呼叫/JMP编写绝对目标(TL:DR您不能(
- 在X86机器代码中调用绝对指针 - 显示如何编码相对分支,并在无法完成
jcc rel32
工作的情况下将地址移动到寄存器并使用jmp reg
。