Search code examples
assemblyx86shellcode

Getting null bytes out of Windows shellcode


The code in question:

mov ebx, fs:30h

Consequent shellcode:

648b1d30000000

I can't seem to figure out how to write this without null bytes.


Solution

  • Your own answer (of using the destination register to construct the offset for the load) works but wastes some bytes.

    The 30h can fit in a disp8 in an addressing mode instead of an imm8 in a separate instruction.

      xor ebx, ebx
      mov ebx, fs:[ebx+30h]    ; or [rbx+30h] in 64-bit code.
    

    Some register is needed as part of the addressing mode; there's no way to use a disp8 without a register.


    In 64-bit code, RIP-relative addressing doesn't help for shellcode (which could end up injected at any unknown absolute address). But it is possible to generate a 30h offset as RIP+rel32 == 30h if you know the absolute address the code will run from, and it's within +-2GiB of 30h.

    YASM allows relative references to absolute addresses. (NASM doesn't like it.)

      mov  ebx, [fs: rel 30h]
    

    Disassembly of yasm -felf64 foo.asm && ld foo.o on Linux, which makes a non-PIE executable (not position-independent, can only run with .text at the address it's linked for.) objdump -drwC -Mintel output:

      401000:    64 8b 1d 29 f0 bf ff    mov  ebx,DWORD PTR fs:[rip+0xffffffffffbff029]   # 30
    

    But NASM makes the cowardly complaint: "foo.asm:1: warning: absolute address can not be RIP-relative [-w+ea-absolute]" and assembles it to a [disp32] absolute address (which in x86-64 requires a SIB byte to encode.)

      401000:    64 8b 1c 25 30 00 00 00      mov    ebx,DWORD PTR fs:0x30
    

    IIRC, with some trickery one can convince GAS to emit RIP-relative addressing of an absolute address.

    If Windows has a relocation-entry type for reaching an absolute address via a relative reference, it could also support what YASM does, in code that isn't LargeAddressAware so the rel32 can reach.