嘿,我很难解决我的作业。
然后 x86 处理器执行命令 EIP 寄存器(计数器)值增加 1 个字节或几个字节,具体取决于命令的类型。我们必须使用哪些指令才能使 EIP 值超过 100 个字节?
答案是:JMP | 添加 | 子 | 推 | 新西兰 | 穆尔 | 致电 | JZ
据我所知,EIP 是我们不能使用的特殊情况寄存器。它被称为扩展指令指针。并且要将其值增加到 100 字节以上,我们需要找出每个命令对 EIP 值增加了多少?
嘿,我很难解决我的作业。
然后 x86 处理器执行命令 EIP 寄存器(计数器)值增加 1 个字节或几个字节,具体取决于命令的类型。我们必须使用哪些指令才能使 EIP 值超过 100 个字节?
答案是:JMP | 添加 | 子 | 推 | 新西兰 | 穆尔 | 致电 | JZ
据我所知,EIP 是我们不能使用的特殊情况寄存器。它被称为扩展指令指针。并且要将其值增加到 100 字节以上,我们需要找出每个命令对 EIP 值增加了多少?
任何这些指令都可以#PF
(页面错误异常)在内存操作数上(或其他方式取决于指令)并将 CS:EIP 更改为从 IDT 加载的全新值。例如push dword [0]
。这将包括将 EIP 更改超过 100,除非您当前的 EIP 在页面错误异常处理程序地址的 100 个字节内。
或者,如果我们正在讨论异常处理程序返回的位置,如果您的进程为 SIGSEGV 安装了信号处理程序,内核可以传递该信号,从而有效地将您的进程中的 EIP 更改为您的 segfault 信号处理程序。
但我认为这个问题的意图是通过特定的期望相对量来改变 EIP,例如达到另一个代码块。(也不会更改代码段 CS,因此如果您从那里开始,则保持在用户模式。)即距当前 EIP 100 个字节。措辞很尴尬,可以理解为将 EIP 设置为任何大于 100 的绝对值,但 x86 分支是相对的,这样问题就更有意义了。
正如@zx485 指出的那样,您需要一个控制转移指令,也就是跳转或分支。386(即任何具有 EIP 而不仅仅是 16 位 IP 的机器)支持jcc rel32
条件近跳转以及较短的jcc rel8
短跳转,因此条件跳转可以到达整个 32 位地址空间中的任何位置,与jmp rel32
和相同call rel32
。 https://www.felixcloutier.com/x86/jcc。
但即使是jcc rel8
(如 JZ 或 JNZ)或jmp rel8
编码也可以达到相对于指令结尾的 -128 到 +127 个字节。(有符号 8 位 2 的补码分支位移。)
对此有几个可能的答案:
使用 relative JMP rel8
:许多汇编器使用这样的语法:
JMP $+100
其中$
是 EIP 的当前值( 的开头JMP
),而 100 是要添加到该位置的十进制值。它JMP
本身占用两个字节 - 从指令编码中的 100 计算中减去。所以代码是
EB 62 (Address after the JMP + 98d=62h)
您可以以相同的方式使用条件跳转,例如JNZ
和JZ
which 函数。
你也可以使用这样的亲戚CALL rel32
:
CALL $+100
在这种情况下,指令长度不同( =5 )。计数在 CALL之后开始,所以指令是
E8 5F 00 00 00 (Address after the CALL + 95d=5Fh)
请注意,在执行跳转之前,后面的地址CALL
也会被PUSH
编入堆栈。
指令 ADD, SUB, PUSH, MUL 对 EIP 没有任何影响,除了它们自己的指令长度提前。
因此,您也可以将它们按顺序组合以推进 100 个字节,但这个答案是微不足道的。