I want to execute execve("/bin/dash", &"/bin/dash", NULL) on Ubuntu 64 bit with the following 32 bit shellcode:

global _start

    xor eax, eax ; set eax = 0 to push a null without using 0x0
    push eax ; eax = null pointer

    mov edx, esp ; edx = null pointer

    ; push '/bin/dash' into stack
    ; but length of string actually needs to be divisible by 4,
    ; otherwise there will be a 0x00 in the string, so:
    ; push null pointer first, then
    ; push '////bin/dash' into stack
    push eax ; eax = null pointer
    push 0x68736164
    push 0x2f6e6962
    push 0x2f2f2f2f

    mov ebx, esp ; ebx = string pointer '////bin/dash'
    push ebx
    mov ecx, esp ; ecx = pointer to string pointer
    mov eax, 0xfffffff4 
    not eax ; eax = 0xb = pointer to execve
    int 0x80 ; interrupt system call

I compile the assembler code with the following line and then extract the machine code:

$ nasm -felf32 shellcode.asm -o x.o && ld -m elf_i386 x.o -o shellcode
$ objdump -d shellcode -M intel -s
shellcode:     file format elf32-i386

Contents of section .text:
 8048060 31c05089 e2506864 61736868 62696e2f  1.P..Phdashhbin/
 8048070 682f2f2f 2f89e353 89e1b8f4 fffffff7  h////..S........
 8048080 d0cd80                               ..P             

Disassembly of section .text:

08048060 <_start>:
 8048060:   31 c0                   xor    eax,eax
 8048062:   50                      push   eax
 8048063:   89 e2                   mov    edx,esp
 8048065:   50                      push   eax
 8048066:   68 64 61 73 68          push   0x68736164
 804806b:   68 62 69 6e 2f          push   0x2f6e6962
 8048070:   68 2f 2f 2f 2f          push   0x2f2f2f2f
 8048075:   89 e3                   mov    ebx,esp
 8048077:   53                      push   ebx
 8048078:   89 e1                   mov    ecx,esp
 804807a:   b8 f4 ff ff ff          mov    eax,0xfffffff4
 804807f:   f7 d0                   not    eax
 8048081:   cd 80                   int    0x80

Then I'm trying to execute my shellcode with this c file:

#include <stdio.h>
#include <string.h>

char *shellcode = "\x31\xc0\x50\x89\xe2\x50\x68\x64\x61\x73\x68\x68\x62\x69\x6e\x2f\x68\x2f\x2f\x2f\x2f\x89\xe3\x53\x89\xe1\xb8\xf4\xff\xff\xff\xf7\xd0\xcd\x80";

int main()
    fprintf(stdout,"Length: %d\n",strlen(shellcode));
    (*(void  (*)()) shellcode)();

I compile this file with:

gcc -m32 -fno-stack-protector test_shellcode.c -o test_shellcode

But this leads to a segmentation fault. I debugged my shellcode with gdb and it looks like my shellcode is working fine but the first line that uses the register al or ah leads to the segmentation fault.

How can I fix that?

  • When you do mov edx, esp you actually move value of esp into edx; not the value esp is pointing at. To access this value, use mov edx, [esp]. – bart1e May 22 at 21:04
  • @bart1e yeah, that was intended because per definition of the function edx needs to point to null not contain null (because it's actually an array with no values inside, so the null pointer terminates it) – winklerrr May 23 at 20:11

Wrong Parameters

I was able to solve my problem!

The function execve has the following definition:

int execve(const char *filename, char *const argv[], char *const envp[]);`
      ^                   ^                    ^                   ^
     eax                 ebx                  ecx                 edx

So the second parameter argv is not just one pointer it's actually an array of (multiple) pointers. So ecx needs to be null terminated but that wasn't the case in my code. I also found out that ecx doesn't need to point to the string /bin/dash instead it can be set to null.

So the parameters need to be set to:

eax = 0x0b
ebx = "/bin/dash"
ecx = 0x00
ecd = 0x00


My working code with just 29 bytes now looks like:

global _start

    ; set eax = 0 without using 0x00
    xor eax, eax 
    push eax ; terminating null string & reference for null pointer

    ; set edc = pointer to null
    ; set edx = pointer to null
    mov ecx, esp
    mov edx, esp

    ; push '////bin/dash' into the stack
    push 0x68736164
    push 0x2f6e6962
    push 0x2f2f2f2f

    ; set ebx = string pointer to '////bin/dash'
    mov ebx, esp

    ; set ecx = pointer to string pointer to '////bin/dash'
    push ebx

    ; set eax = 0xb (function 'execve')
    mov al, 0xb
    int 0x80 ; interrupt system call

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.