【问题标题】:Get the start of the previous instruction from an address从地址获取上一条指令的开始
【发布时间】:2016-03-18 23:37:59
【问题描述】:

我们在一个缓冲区中,正在查看 x86 操作码。 |标记当前指针。

68 0F 00 6A 90 | 00

找到下一条指令的开始很容易,因为电流的大小是可以确定的。但是你怎么能稍微准确地猜出前一个的开始呢?

68 0F 00 6A 90 - 总共 5 个字节,结束于 |

0F 00 6A 90 - 总共 4 个字节,结束于 |

00 6A 90 - 共 3 个字节,结束于 |

6A 90 - 共 2 个字节,结束于 |

90 - 总共 1 个字节,以 | 结束

显然这不是一个实际示例,但它说明了问题所在。这与其说是一个问题,倒不如说是一个好奇心,但现代反汇编程序是如何准确猜测的呢?他们是否存储带有调用/跳转引用的点并找到与当前指令结束的最近标签的最近地址?

【问题讨论】:

    标签: assembly x86


    【解决方案1】:

    使用这样的可变长度指令集,您无法准确地线性反汇编。您必须从入口点开始并遵循所有可能的代码路径,当然,如果反汇编程序仅此而已,则很容易绊倒(强制条件然后使用条件分支,这只会采用一条路径,并将数据留在未使用的路径中,这会导致以下指令解码失败)。更糟糕的是,如果您只是尝试从入口点线性执行而不检查数据(例如,当编译器在无条件分支之后放置轮询数据或返回您的反汇编程序视为指令数据时)。

    你不能真正准确地倒退,除非你遵循代码路径,有一个分支可以让你到达那里或在它前面的某个地方执行。

    【讨论】:

    • 谢谢,我在想这样的事情。你知道像 olly 这样的程序是如何进入内存中的一个随机位置并很好地工作的吗?还是最终会成功?
    • 不,我不知道,我怀疑但没有检查某些文件格式是否会留下信息,例如 gnu objdump 是如何做得这么好的?编译器生成的代码将非常干净且易于反汇编,需要尝试调试工具以查看它们的实际性能。尽管如果使用原始二进制文件而不是包含大量调试信息的格式,跳转表或函数指针也可能会出错。编译调试应该添加信息来帮助解决这种事情,也可以做一些实验......
    • 如果你想清楚了,真的没有别的办法,处理器显然可以找到它的方法,因为它正在完整地执行每条指令。反汇编程序可以尝试这样做,但它仍然可能无法正常工作,因为某些路径取决于用户输入。因此,如果没有文件格式的帮助,并且无法通过每个代码路径执行代码,那怎么可能呢?你能做的最好的就是解码足以知道每条指令的长度,并遵循所有可能的分支,假设条件的每条路径都被采用。
    猜你喜欢
    • 2012-05-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-18
    • 2018-03-18
    • 2022-07-16
    • 2023-04-08
    相关资源
    最近更新 更多