5

有谁知道任何提供 NOP 操作码替代指令的在线资源?

像'xchg ax,ax'之类的。我很确定还有一个工具,有人可以指点我那个方向吗?

4

6 回答 6

4

一些 shellcode 引擎包含nopsled 生成器,如果这是您正在寻找的。

尽管有无数种nop不同长度的等效项,但详尽的列表是不切实际的。

例如,push eax; pop eax实际上是一个nop. (假设有效esp等)

或者inc eax; dec eax(假设没有溢出或者你测试然后重置溢出标志)。

于 2011-09-29T18:52:23.177 回答
4

这个页面有一个很好的 NOP 替代列表,随着编码长度的增加:http ://www.asmpedia.org/index.php?title=NOP

于 2011-09-29T16:24:55.847 回答
2

英特尔优化手册以及英特尔和 AMD 的说明手册应该列出所有无运算等效功能。需要注意的是,它们中的大多数都是多字节无操作,用于对齐分支和代码缓存目标等。

于 2011-09-29T18:39:09.433 回答
2

NOP 的替代方案,它对 nop 雪橇没用,但对性能很有用:在现代 x86 上可以使用哪些方法来有效地扩展指令长度? (例如添加额外的前缀以使指令更长)。


通常,您的漏洞利用负载不关心寄存器值(堆栈指针除外),因此您可以使用inc eax(32 位代码中的单字节)之类的东西自由地销毁它们。 有很多单字节指令只修改寄存器,不会出错。例如 cld/ std, stc/ clc/ cmc, cwde,cdq都是单字节的。 同样在 32 位代码中,即使是 BCD 指令AAADAA可以使用,但这些指令会像大拇指一样突出,因为编译器从不使用它们。(编译器在实践中使用cdqand may cwde,但通常不使用cldor std。)

还有其他 xchg-with-eax 单字节 0x91..7 指令,除了0x90 nop它使用相同的编码xchg eax,eax,并且可以在 32 位模式下使用。(但请注意,xchg eax,eax在 64 位模式下不是 NOP;它必须使用其他编码才能将 RAX 截断为 EAX。)

对于任何多字节指令mov eax,eax如果执行开始于第一个字节以外的位置,请务必检查它是如何解码的。雪橇的全部意义在于执行必须降落在缓冲区内的某个地方,但您不知道在哪里。

如果在前缀之后开始执行,您可以使用可选前缀来制作仍然可以解码的多字节指令。 cbw0x66 cwde(操作数大小前缀)。或 REX 前缀 ( 0x40..4f),xchg rax,rcx例如。

rep前缀通常在它们不适用的指令上被安全地忽略,但在未来的 CPU 上可能会以不同的方式运行。(例如rep nop,以前只是 NOP,但现在是 .is now ,这会产生不同的结果pause。 )这对 shellcode 来说很好,你现在正试图利用一个系统,而不是未来 CPU 的未来证明。rep bsrlzcnt


如果您知道目标缓冲区对齐,那么您可以控制(通过指令指针的低位)可以跳转到哪些可能的偏移量。如果缓冲区是 4 字节对齐的(或者更具体地说,您的有效负载将以 4 字节对齐的位置结束),那么只有每 4 个字节需要作为解码的有效起点,因此您可以使用成对的 2 字节xor eax, ebx/之类的指令add ecx, edx

4 字节指令包括addss xmm0, xmm1和其他 SSE1/SSE2 指令。除非您正在利用的代码在禁用 SSE 的内核模式下运行,否则您通常可以假设您正在利用的任何机器都具有 SSE1。

您甚至可以使用 5 字节指令,例如mov eax, 0x90345612从 4 字节对齐地址开始。请注意,小端立即数的最后一个字节是0x90nop,所以如果从那里开始解码就可以了。


我的理解是,像这样的技术被广泛用于解决发现长串0x90可疑文件的入侵检测系统/病毒扫描程序。(和/或因为0x90不是可打印的 ASCII,也不是有效的 UTF-8)。

于 2018-08-25T20:35:06.487 回答
1

来自最佳答案中死链接的互联网档案。

90              nop
6690            xchg    ax,ax ; 66: switch to 16-bit operand 90: opcode 
0f1f00          nop     dword ptr [eax] ; 0f1f: 2-byte opcode 00: mod=00 reg=000 rm=000 [EAX]
0f1f4000        nop     dword ptr [eax] ; 0f1f: 2-byte opcode 40: mod=01 reg=000 rm=000 [EAX+0x00]
0f1f440000      nop     dword ptr [eax+eax] ; 0f1f: 2-byte opcode 44: mod=01 reg=000 rm=100 SIB + 0x00
660f1f440000    nop     word ptr [eax+eax] ; 66: switch to 16-bit operand 0f1f: 2-byte opcode 44: mod=01 reg=000 rm=100 SIB + 0x00
0f1f8000000000  nop     dword ptr [eax] ; 0f1f: 2-byte opcode 80: mod=10 reg=000 rm=000 [EAX+0x00000000]
于 2018-08-25T19:56:11.990 回答
0

只需考虑不改变任何东西(标志除外)的不同操作。将零添加到寄存器,或将寄存器与自身和寄存器与自身相加,将寄存器移动到自身。减去 0,或与零,并与〜0。位测试类型的指令,通常是一个 and 但目标没有被修改。

于 2011-09-29T18:50:00.317 回答