3

背景:我编写了一个 python 脚本来检查 IP 数据包,特别是数据包的有效负载/数据,以检测它是否可以用于缓冲区(堆栈)溢出。现在据我了解,NOP sled 用于填充堆栈,以便指令指针最终会运行到您的漏洞利用代码中,我可以通过查找重复出现的 0x90 轻松检测到这一点。在 SQL slammer 的情况下,我已经看到有很多 NOP 命令的代码只有 8 个,所以我可能至少可以使用 8 个。

现在我的问题是,合法代码中经常使用 NOP 雪橇吗?如果答案是肯定的,是否有一些特定情况(这意味着我可以查找这些情况,然后将数据包排除为可能无害)还是这种方法对于识别恶意代码不实用?

4

3 回答 3

9

编译器将生成 NOP 以对齐代码——例如,在 x86 的某些迭代中,如果跳转目​​标对齐到 4、8 甚至 16 字节边界,则跳转执行得更快

一些编译器在可能的情况下尝试使用“长 NOP”——占用超过一个字节空间的单个指令,并且可能正式执行某些操作,但对处理器状态没有影响——因为在x86 架构的某些迭代中,这是快点。例如,66 90是一个两字节的 NOP,并且8d 74 26 00是一个四字节的 NOP(从技术上讲lea 0(%esi,%eiz,1),%esi,但正如您所看到的,它只是将值复制%esi到自身,所以没有效果)。但是,这些不能在所有情况下都使用,并且在某些 x86 上最快的序列在其他 x86 上通常非常,令人沮丧。我还没有阅读当前的微优化指南,但如果英特尔和 AMD 正在努力制作一系列微优化指南,我不会感到惊讶90s 执行长 NOP 的最快方法,并让他们的编译器匹配。

于 2011-10-17T00:27:37.757 回答
3

来自维基百科

NOP 最常用于时序目的,强制内存对齐,防止危险,占用分支延迟槽,或作为占位符,在程序开发的后期由活动指令替换(或替换已删除的指令)重构将是有问题的或耗时的)。在某些情况下,NOP 可能会产生轻微的副作用;例如,在摩托罗拉 68000 系列处理器上,NOP 操作码将导致流水线同步。

此外,0x90可以想象编译器可以将其用作未初始化数组的填充物,以防数组中的数据被解释为操作码,它什么也不做。您会在 Visual Studio 中看到类似的效果,它会填充未初始化的数组,0xCCint 3会导致断点停止。

此外,可执行文件中的任何数据都可能包含任意数量的数据,0x90并且区分它和代码可能并非易事。

于 2011-10-17T00:27:19.863 回答
2

我刚刚查看了我编译的最后一个二进制文件(Linux 上的非恶意 x86 代码),发现:

016b5e0 458b c9ec 90c3 9090 9090 9090 9090 9090

我认为您可以得出结论,找到重复的 0x90 序列并不一定表示恶意意图。

于 2011-10-17T00:24:17.503 回答