1

嘿,我很难解决我的作业。

然后 x86 处理器执行命令 EIP 寄存器(计数器)值增加 1 个字节或几个字节,具体取决于命令的类型。我们必须使用哪些指令才能使 EIP 值超过 100 个字节?

答案是:JMP | 添加 | 子 | 推 | 新西兰 | 穆尔 | 致电 | JZ

据我所知,EIP 是我们不能使用的特殊情况寄存器。它被称为扩展指令指针。并且要将其值增加到 100 字节以上,我们需要找出每个命令对 EIP 值增加了多少?

4

2 回答 2

3

任何这些指令都可以#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 rel32https://www.felixcloutier.com/x86/jcc

但即使是jcc rel8(如 JZ 或 JNZ)或jmp rel8编码也可以达到相对于指令结尾的 -128 到 +127 个字节。(有符号 8 位 2 的补码分支位移。)

于 2020-01-15T23:44:18.833 回答
2

对此有几个可能的答案:

  1. 使用 relative JMP rel8:许多汇编器使用这样的语法:

    JMP $+100 
    

    其中$是 EIP 的当前值( 的开头JMP),而 100 是要添加到该位置的十进制值。它JMP本身占用两个字节 - 从指令编码中的 100 计算中减去。所以代码是

    EB 62               (Address after the JMP + 98d=62h)
    
  2. 您可以以相同的方式使用条件跳转,例如JNZJZwhich 函数。

  3. 你也可以使用这样的亲戚CALL rel32

    CALL $+100
    

    在这种情况下,指令长度不同( =5 )。计数在 CALL之后开始,所以指令是

    E8 5F 00 00 00      (Address after the CALL + 95d=5Fh)
    

    请注意,在执行跳转之前,后面的地址CALL也会被PUSH编入堆栈。

  4. 指令 ADD, SUB, PUSH, MUL 对 EIP 没有任何影响,除了它们自己的指令长度提前。

    因此,您也可以将它们按顺序组合以推进 100 个字节,但这个答案是微不足道的。

于 2020-01-15T22:51:59.010 回答