【问题标题】:What happens when jmp to the address in between 2 instructions?当 jmp 到 2 条指令之间的地址时会发生什么?
【发布时间】:2013-10-27 14:00:27
【问题描述】:

我在看一个程序的gdb反汇编

...
0x8048085: cmp    eax,ecx
0x8048087: je     0x804809f
0x8048089: mov    DWORD PTR [esp+0x4],0x21
0x8048091: mov    DWORD PTR [esp],0x8048160
0x8048098: jmp    0x8048157
0x804809d: mov    esi,0x115e8ba
0x80480a2: add    BYTE PTR [eax],al
...

在第二条指令中,有一个跳转到地址 0x...9f,它是之后的两条指令之间。我知道理论上一切都是可能的,因为只要我们向他提供要执行的内容的地址,处理器就不应该关心,但仍然......如果有人可以解释,谢谢

更新:好的,地址似乎有问题。但这是更大代码(200 行)的 sn-p 部分。我查看了“调用 0x ...”的位置,并用标签替换了它们,代码如下所示:

func1:
   ...
   asm
   ...
   call func2
   ...
   ret
func2:
   ...
   asm
   ...
   ret
...

尽管我很想购买反汇编在某个时候在地址中被绊倒的事实,但这与它所说的任何地方都调用 0x...,即 0x 之前的指令这一事实无关。 ..是一个“ret”。如果地址在某处有偏移,这将是不正确的

【问题讨论】:

  • 地址 A2 的指令也是垃圾。您的反汇编程序只是被 JMP 之后的两个额外的垃圾字节绊倒了。为什么它们在那里是不可猜测的,填充字节绝对不是不寻常的,但对于未对齐的分支目标地址来说却不是。
  • 我更新了问题

标签: assembly


【解决方案1】:

我的第一个猜测是0x804809d 处插入了一些填充数据。这意味着该部分的反汇编应该从0x804809f开始。

根据列出的地址,反汇编也有可能在此过程的早期出现了一些错误。

【讨论】:

  • 填充数据是什么意思?
  • 为确保跳转尽可能快,编译器可能会插入填充数据以确保所有跳转目标的地址都是 8 的倍数。
【解决方案2】:

是的,这是可能的,但值得一提的是这里的对齐问题:Why should code be aligned to even-address boundaries on x86?

我看到了为什么可以这样做的几种可能性:

  • 自修改代码(当实际有意义的指令将在开始后写入该地址时)
  • 将一条指令的数据解释为操作码(类似于this
  • 只是跳转地址错误(甚至可能是编译器错误,但不是必须的)

【讨论】:

  • 我不知道它是否回答了我的问题(我不知道它是否有答案)但是这里的一些提示和链接非常好,只是想 +1 那些
【解决方案3】:

可变字长指令集的反汇编很棘手,我猜你不是在看真正的代码,或者反汇编器有问题。

【讨论】:

  • 有比 gdb -> disas 命令更好的工具吗?我在我的程序上使用了 objdump,我想我得到了同样的东西。为什么反汇编这么复杂?必须只有一种方法来处理某些代码吗?
  • 执行代码和反汇编是有区别的。要正确反汇编可变字长,您将按照执行顺序执行代码,但这仍然可能失败(长篇大论)。此外,gdb/objdump 的工作方式与您用于创建此文件的工具有关,您也可以将它们绊倒。用 x86 解决 esp 是一个极其困难的问题,这就是为什么最好的反汇编程序远非完美的原因。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-17
  • 1970-01-01
  • 2012-02-12
  • 2021-09-14
  • 2016-01-06
  • 2021-09-11
相关资源
最近更新 更多