Dies ist eine alte Version des Dokuments!


NOP sleds

To directly transfer control flow to our shellcode, we need to specify its address as the return address of the current function. However, guessing the exact address can be very hard, especially on remote machines. Even minor system differences can lead to a different stack layout.

Example: Remember that argv[0] contains the execution path of the program. Starting the binary from a different directory results in a different execution path and thus a different stack layout.

Even an offset of a single byte to the correct address breaks the exploit. See the following x86 assemnbly code simply exiting the program:

mov eax, 1
mov ebx, 0
int 0x80

FIXME compilation

Disassembling the object file with objdump shows the correct result:

$ objdump -d -M intel-mnemonic correct_offset.o 

correct_offset.o:     file format elf32-i386


Disassembly of section .text:

00000000 <.text>:
   0:   b8 01 00 00 00          mov    eax,0x1
   5:   bb 00 00 00 00          mov    ebx,0x0
   a:   cd 80                   int    0x80

But if only the very first byte (value 0xb8) of the opcode is deleted, the instructions change their meaning:

$ objdump -d -M intel-mnemonic incorrect_offset.o

incorrect_offset.o:     file format elf32-i386


Disassembly of section text:

00000000 <text>:
   0:   01 00                   add    DWORD PTR [eax],eax
   2:   00 00                   add    BYTE PTR [eax],al
   4:   bb 00 00 00 00          mov    ebx,0x0
   9:   cd 80                   int    0x80
        ...

Note that even for this tiny example the resulting code is significantly different from the original one.

What we are trying to do now is to create some kind of memory area in front of our code where we can safely redirect execution to. By definition the bytes in this area must be valid opcodes. As seen before, only one single byte of offset at the instruction address can destroy any meaning of the code. To avoid this, we need to find an instruction that is only a single byte long. Our final requirement for the instruction is to not affect any registers (except for the instruction pointer, which is naturally incremented by one after execution). The x86 instruction set provides an instruction that fulfills all our requirements - the NOP (No OPeration) instruction. Having an opcode of 0x90, it is usually implemented as an alias instruction to the following code1):

xchg eax,eax

Next, we will take a look at a very simple example that makes use of this technique called NOP sled.

FIXME continue