Search code examples
cassemblynasmshellcode

How to convert an assembler program to shellcode correctly?


I programmed a program in nasm (x64) which should execute /bin/bash, and that works fine. Then i ran the program with objdump -D and i wrote down the machine code like this: \xbb\x68\x53\x48\xbb\x2f\x62\x69\x6e\x2f\x62\x61\x73\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05. Then i ran this with ./shell $(python -c 'print "\xbb\x68\x53\x48\xbb\x2f\x62\x69\x6e\x2f\x62\x61\x73\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05"') and i got an illegal instruction. But the assembler program worked fine! Can someone help?

shell.c:

int main(int argc, char **argv) {
    int (*func)();
    func = (int (*)()) argv[1];
    (int)(*func)();
}

bash.asm:

section .text
global start
start:
    mov rbx, 0x68
    push rbx
    mov rbx, 0x7361622f6e69622f
    push rbx
    mov rdi, rsp
    push rax
    push rdi
    mov rsi, rsp
    mov al, 59
    syscall

objdump:

./bash:     file format elf64-x86-64


Disassembly of section .text:

0000000000401000 <start>:
  401000:   bb 68 00 00 00          mov    $0x68,%ebx
  401005:   53                      push   %rbx
  401006:   48 bb 2f 62 69 6e 2f    movabs $0x7361622f6e69622f,%rbx
  40100d:   62 61 73 
  401010:   53                      push   %rbx
  401011:   48 89 e7                mov    %rsp,%rdi
  401014:   50                      push   %rax
  401015:   57                      push   %rdi
  401016:   48 89 e6                mov    %rsp,%rsi
  401019:   b0 3b                   mov    $0x3b,%al
  40101b:   0f 05                   syscall

Solution

  • You are omitting the zero bytes here:

    \xbb\x68\x53\x48\xbb\x2f\x62\x69\x6e\x2f\x62\x61\x73\x53\x48\x89\xe7\x50\x57\x48\x89\xe6\xb0\x3b\x0f\x05
    

    as opposed to

      401000:   bb 68 00 00 00          mov    $0x68,%ebx
    

    The zero bytes are part of the instructions and cannot be skipped. So you have to include them.

    The problem is, however, that the zero bytes would terminate the argument string and hence have to be avoided. It is your duty as shellcode designer to construct it in a way, that it does not include byte values that may not occur. In many cases this means no zero bytes, because the shellcode is injected as a C string, but other values may be problematic in other situations, too.