有谁知道任何提供 NOP 操作码替代指令的在线资源?
像'xchg ax,ax'之类的。我很确定还有一个工具,有人可以指点我那个方向吗?
一些 shellcode 引擎包含nop
sled 生成器,如果这是您正在寻找的。
尽管有无数种nop
不同长度的等效项,但详尽的列表是不切实际的。
例如,push eax; pop eax
实际上是一个nop
. (假设有效esp
等)
或者inc eax; dec eax
(假设没有溢出或者你测试然后重置溢出标志)。
这个页面有一个很好的 NOP 替代列表,随着编码长度的增加:http ://www.asmpedia.org/index.php?title=NOP
英特尔优化手册以及英特尔和 AMD 的说明手册应该列出所有无运算等效功能。需要注意的是,它们中的大多数都是多字节无操作,用于对齐分支和代码缓存目标等。
NOP 的替代方案,它对 nop 雪橇没用,但对性能很有用:在现代 x86 上可以使用哪些方法来有效地扩展指令长度? (例如添加额外的前缀以使指令更长)。
通常,您的漏洞利用负载不关心寄存器值(堆栈指针除外),因此您可以使用inc eax
(32 位代码中的单字节)之类的东西自由地销毁它们。 有很多单字节指令只修改寄存器,不会出错。例如 cld
/ std
, stc
/ clc
/ cmc
, cwde
,cdq
都是单字节的。 同样在 32 位代码中,即使是 BCD 指令AAA
也DAA
可以使用,但这些指令会像大拇指一样突出,因为编译器从不使用它们。(编译器在实践中使用cdq
and may cwde
,但通常不使用cld
or std
。)
还有其他 xchg-with-eax 单字节 0x91..7 指令,除了0x90 nop
它使用相同的编码xchg eax,eax
,并且可以在 32 位模式下使用。(但请注意,xchg eax,eax
在 64 位模式下不是 NOP;它必须使用其他编码才能将 RAX 截断为 EAX。)
对于任何多字节指令mov eax,eax
,如果执行开始于第一个字节以外的位置,请务必检查它是如何解码的。雪橇的全部意义在于执行必须降落在缓冲区内的某个地方,但您不知道在哪里。
如果在前缀之后开始执行,您可以使用可选前缀来制作仍然可以解码的多字节指令。 cbw
是0x66 cwde
(操作数大小前缀)。或 REX 前缀 ( 0x40..4f
),xchg rax,rcx
例如。
rep
前缀通常在它们不适用的指令上被安全地忽略,但在未来的 CPU 上可能会以不同的方式运行。(例如rep nop
,以前只是 NOP,但现在是 .is now ,这会产生不同的结果pause
。 )这对 shellcode 来说很好,你现在正试图利用一个系统,而不是未来 CPU 的未来证明。rep bsr
lzcnt
如果您知道目标缓冲区对齐,那么您可以控制(通过指令指针的低位)可以跳转到哪些可能的偏移量。如果缓冲区是 4 字节对齐的(或者更具体地说,您的有效负载将以 4 字节对齐的位置结束),那么只有每 4 个字节需要作为解码的有效起点,因此您可以使用成对的 2 字节xor eax, ebx
/之类的指令add ecx, edx
。
4 字节指令包括addss xmm0, xmm1
和其他 SSE1/SSE2 指令。除非您正在利用的代码在禁用 SSE 的内核模式下运行,否则您通常可以假设您正在利用的任何机器都具有 SSE1。
您甚至可以使用 5 字节指令,例如mov eax, 0x90345612
从 4 字节对齐地址开始。请注意,小端立即数的最后一个字节是0x90
nop,所以如果从那里开始解码就可以了。
我的理解是,像这样的技术被广泛用于解决发现长串0x90
可疑文件的入侵检测系统/病毒扫描程序。(和/或因为0x90
不是可打印的 ASCII,也不是有效的 UTF-8)。
来自最佳答案中死链接的互联网档案。
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]
只需考虑不改变任何东西(标志除外)的不同操作。将零添加到寄存器,或将寄存器与自身和寄存器与自身相加,将寄存器移动到自身。减去 0,或与零,并与〜0。位测试类型的指令,通常是一个 and 但目标没有被修改。