【问题标题】:Alternatives to NOP for shellcode nop sledsshellcode nop sleds 的 NOP 替代品
【发布时间】:2011-09-29 16:13:17
【问题描述】:

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

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

【问题讨论】:

  • 能否产生nop替代品?
  • 出于好奇,您寻找 nop 替代品的目的是什么?

标签: security assembly x86 shellcode


【解决方案1】:

此页面有一个不错的 NOP 替代列表,编码长度增加:http://www.asmpedia.org/index.php?title=NOP

【讨论】:

  • 问题在于这主要是关于 nop 本身。我也想要“mov ax, ax”之类的指令。
  • 截止日期,有什么替代方案或成就吗?
  • 嗯——太糟糕了。看起来回程机器也没有它。如果我很快找不到可靠的来源,我将删除我的答案。
  • 哦,OmnipotentEntity 居然在下面贴了一段摘录。
【解决方案2】:

一些 shellcode 引擎包含 nop sled 生成器,如果您正在寻找的话。

虽然nop-等价物有无数种长度,但详尽列出是不切实际的。

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

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

【讨论】:

  • 是的,我在想它们,或者像'xor eax,0'之类的东西。我希望有一个清单或其他东西。正如我所说,我很确定我在过去看到过这样的工具。
  • 如果你想写一个生成器:一个非常懒惰的做法是将机器状态保存到堆栈中,然后生成随机指令(那些不接触内存或导致中断的指令)提高),然后重新加载机器状态。 (多态 shellcode 通常会做类似的事情,尽管可能会有更多限制,例如仅使用单字节指令。)
【解决方案3】:

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

【讨论】:

【解决方案4】:

NOP 的替代方案,对 nop 雪橇无用,但对性能很有用:What methods can be used to efficiently extend instruction length on modern x86?(例如,添加额外的前缀以使指令更长)。


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

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

对于像mov eax,eax 这样的任何多字节指令,请确保检查它是否从第一个字节以外的位置开始执行解码。 sled 的全部意义在于执行必须在缓冲区内的某个地方着陆,但您不知道在哪里。

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

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


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

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

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


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

【讨论】:

    【解决方案5】:

    来自顶部答案中死链接的互联网档案。

    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]
    

    【讨论】:

    • 这不能用作 NOP 雪橇。如果执行落在这些长指令之一的中间,它可能会出错。例如00 00 是 add [rax], al
    • 如果你能保证着陆的对齐就可以了。但是,是的,我同意。
    【解决方案6】:

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

    【讨论】:

    • 如果它改变了标志,那并不是真正的 NOP。
    • 我同意,这取决于发布者实际在寻找什么操作,对寄存器不做任何事情或对寄存器和标志不做任何事情。
    猜你喜欢
    • 2013-11-27
    • 1970-01-01
    • 2019-03-30
    • 2018-07-17
    • 2018-11-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-23
    相关资源
    最近更新 更多