为什么你不能设定该指令的指令直接?
-
26-10-2019 - |
题
解决方案
你不能直接访问它,因为没有合法的使用情况。具有任何任意的指令的更改 eip
会让的分支预测非常困难,且可能会打开一堆的安全问题。
你可以编辑 eip
使用 jmp
, call
或 ret
.你就不能直接从阅读或写信给 eip
使用正常运作
设置 eip
一个登记册作为简单的 jmp eax
.你也可以做 push eax; ret
, ,这推动的价值 eax
堆然后返回(即持久性有机污染物和跳).第三个选择是 call eax
这并呼叫地址在eax.
阅读可以做这样的:
call get_eip
get_eip:
pop eax ; eax now contains the address of this instruction
其他提示
这可能是X86的可能设计。手臂做 公开其程序计数器以读/写为R15. 。不过,这是不寻常的。
它允许非常紧凑的函数序言/结语,并能够用单个指令推动或弹出多个寄存器: push {r5, lr}
进入,以及 pop {r5, pc}
返回。 (将链接寄存器的保存值弹出到程序计数器中)。
但是,它使高级 /级别的ARM实现降低了方便,并且用于AARCH64。
所以 有可能,但用尽了其中一个寄存器. 。 32位ARM具有16个整数寄存器(包括PC),因此寄存器编号需要4位用ARM机器代码进行编码。另一个登记册几乎总是被绑定为堆栈指针,因此ARM有14个通用整数登记册。 (可以将LR保存到堆栈中,因此可以并用作功能机构内部通用寄存器)。
现代X86的大部分是从8086继承的。它的设计使用相当紧凑的可变长度指令编码,只有8个寄存器,每个SRC和DST寄存器仅需要3位。
在最初的8086中,它们不是很通用,并且在16位模式下无法进行SP搭配的解决方案,因此基本上有2个寄存器(SP和BP)被绑住以堆叠堆栈的东西。这仅留下6个某种程度上的目的登记册,其中一个是PC而不是通用的登记册,将大大减少可用寄存器,从而大大增加了典型代码中的溢出/重新加载量。
AMD64添加了R8-R15和RIP相关的寻址模式。 lea rsi, [rip+whatever]
, ,以及用于直接访问静态数据和常数的RIP相关地址模式,您需要有效地与位置无关的代码。间接JMP说明完全足以写作。
通过允许使用任意说明读取或编写PC,实际上没有什么可获得的,因为您可以随时使用整数寄存器和间接跳跃来做同样的事情。 X86-64的R15与RIP相同,尤其是对于架构作为编译器目标的表演,这几乎是纯粹的弊端。 (到2000年,当设计AMD64时,手工编写的ASM怪异的东西已经非常罕见。)
因此,AMD64实际上是X86首次可以合理地获得像ARM这样的完全曝光的程序计数器,但是有很多很好的理由不这样做。
我认为他们意味着无法直接以其他寄存器访问的方式访问IP寄存器。程序员绝对可以写入IP,例如发出跳跃指令。
jmp
将设置 EIP
登记。
此代码将将EIP设置为00401000:
mov eax, 00401000
jmp eax ;set Eip to 00401000
并获得 EIP
call GetEIP
.
.
GetEIP:
mov eax, [esp]
ret