【问题标题】: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 指令像 AAADAA 是可以使用的,但它们会像大拇指一样突出,因为编译器从不使用它们。 (编译器在实践中会使用cdqcwde,但通常不会使用cldstd。)

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

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

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

rep 前缀通常在它们不适用的指令上被安全地忽略,但在未来的 CPU 上可能会以不同的方式运行。 (例如,rep nop 以前只是 NOP,但现在是 pauserep 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 00add [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
    相关资源
    最近更新 更多