开发者

Alternatives to NOP for shellcode nop sleds

Does anyone know of any online source that provides instruction alternatives to a NOP opcode ?

Like 'xchg ax, ax' and the likes. I'm pretty sure that there is also a tool for it开发者_StackOverflow中文版, can someone point me to that direction please ?


Some shellcode engines contain nop sled generators, if that is what you're looking for.

Though there are an infinite variety of nop-equivalents of various lengths, so an exhaustive listing is impractical.

For instance, push eax; pop eax is effectively a nop. (assuming a valid esp, etc, etc)

Or inc eax; dec eax (assuming no overflow or you test then reset the overflow flag).


This page has a nice list of NOP alternatives with increasing encoding lengths: http://www.asmpedia.org/index.php?title=NOP


An alternative to NOP that's useless for nop sleds, but useful for performance: What methods can be used to efficiently extend instruction length on modern x86? (e.g. add extra prefixes to make instructions longer).


Normally your exploit payload doesn't care about register values (other than the stack pointer), so you can freely destroy them with things like inc eax (single-byte in 32-bit code). There are lots of single-byte instructions that only modify registers and won't fault. e.g. cld/std, stc/clc/cmc, cwde, cdq are all single-byte. Again in 32-bit code, even BCD instructions like AAA or DAA are usable, but those will stick out like a sore thumb because compilers never use them. (Compilers do in practice use cdq and maybe cwde, but typically not cld or std.)

Also the other xchg-with-eax one-byte 0x91..7 instructions, other than 0x90 nop which uses the same encoding that xchg eax,eax would have, and could in 32-bit mode. (But note that xchg eax,eax in 64-bit mode isn't a NOP; it has to use the other encoding so it can truncate RAX to EAX.)

With any multi-byte instruction like mov eax,eax, make sure to check how it decodes if execution starts at something other than the first byte. The whole point of a sled is that execution has to land somewhere inside the buffer but you don't know where.

You can use optional prefixes to make multi-byte instructions that still decode ok if execution starts after the prefix. cbw is 0x66 cwde (operand-size prefix). Or REX prefixes (0x40..4f), so xchg rax,rcx for example.

rep prefixes are typically ignored safely on instructions they don't apply to, but may run differently on future CPUs. (e.g. rep nop used to just be NOP, but now it's pause. rep bsr is now lzcnt, which produces a different result.) This is fine for shellcode, you're trying to exploit one system now, not be future-proof for future CPUs.


If you know the target buffer alignment, then you control (via the low bits of the instruction pointer) which possible offsets you can jump to. If the buffer is 4-byte aligned (or more specifically that your payload will end up a 4-byte aligned location), then only every 4th byte needs to be a valid starting point for decoding, so you can use pairs of 2-byte instructions like xor eax, ebx / add ecx, edx.

4-byte instructions include addss xmm0, xmm1 and other SSE1/SSE2 instructions. Unless the code you're exploiting is running in kernel mode with SSE disabled, you can normally assume that whatever machine you're exploiting has SSE1.

You could even use a 5-byte instruction like mov eax, 0x90345612 starting at a 4-byte aligned address. Note that the last byte of the little-endian immediate is 0x90 nop, so it's ok if decoding starts there.


My understanding is that techniques like this are widely used to work around intrusion-detection systems / virus scanners that find long strings of 0x90 suspicious. (And/or because 0x90 is not printable ASCII, and not valid UTF-8).


The intel optimization manual and the instruction manuals for intel and AMD should have listing of all the no op equivalent functions. It should be noted that most of them are multi byte no ops, to be used for aligning branch and code cache targets etc.


From the internet archive of the dead link in the top answer.

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]


just think through the different operations that dont change anything (other than flags). add zero to a register, or the register with itself and the register with itself, move the register to itself. subtract 0, or with zero, and with ~0. A bit test type instruction, usually an and but the destination is not modified.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜