cgccsegmentation-faultshellcodeobjdump

Shellcode execution error Segmentation Fault in C


I tried to execute shellcode in c. But I got Segmentation Fault error. I tried on Kali Linux virtual machine. The purpose of shellcode is to print hello shellcode to the screen It's mine code:

// shellcode_example.c
#include <stdio.h>

int main() {
    printf("Hello, Shellcode!\n");
    return 0;
}

It's extract of hex code:

gcc -o shellcode_example shellcode_example.c
objdump -d -M intel shellcode_example
080484b6 <main>:
  80484b6:   55                      push   ebp
  80484b7:   89 e5                   mov    ebp,esp
  80484b9:   83 ec 08                sub    esp,0x8
  80484bc:   68 60 86 04 08          push   0x8048660
  80484c1:   e8 aa fe ff ff          call   8048370 <puts@plt>
  80484c6:   83 c4 04                add    esp,0x4
  80484c9:   b8 00 00 00 00          mov    eax,0x0
  80484ce:   c9                      leave
  80484cf:   c3                      ret

It's shellcode execution:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>

// Shellcode: Bu, örnek bir NOP (no-operation) shellcode'dur
unsigned char shellcode[] = {
    0x90, 0x90, 0x90, 0x90, 0xC3 // Think, it's mine shellcode.
};

int main() {
    
    void *mem = mmap(NULL, sizeof(shellcode), PROT_READ | PROT_WRITE | PROT_EXEC, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);

    if (mem == MAP_FAILED) {
        perror("mmap");
        return 1;
    }

    // Shellcode'ı tahsis edilen belleğe kopyala
    memcpy(mem, shellcode, sizeof(shellcode));

    // Bir işlev işaretçisi oluştur ve bellek konumuna dönüştür
    typedef void (*ShellcodeFunction)();
    ShellcodeFunction func = (ShellcodeFunction)mem;

    // Shellcode'ı yürüt
    func();

    // Tahsis edilen belleği serbest bırak
    munmap(mem, sizeof(shellcode));

    return 0;
}

Is there any solution ? I tried all solution on Internet.

I tried to:

gcc -fno-stack-protector -z execstack -O OutputFileName yourShellCode.c

I used local and global variable but no change.

Update:

Here is my new shell code:

unsigned char shellcode[] = {
 0xb8, 0x04, 0x00, 0x00, 0x00, 0xbb, 0x01, 0x00,
 0x00, 0x00, 0xb9 ,0x00 ,0xa0 ,0x04, 0x08, 0xba,
 0x0d ,0x00 ,0x00, 0x00 ,0xcd ,0x80 ,0xb8, 0x01,
 0x00 ,0x00 ,0x00, 0x31, 0xdb, 0xcd, 0x80
};

and asm code of shellcode:

section .data
     hello db 'Hello, World!',0
section .text
     global _start  _start:     
      ; write system call
     mov eax, 4
     mov ebx, 1
     mov ecx, hello
     mov edx, 13
     int 0x80
      ; exit system call
     mov eax, 1
     xor ebx, ebx
     int 0x80

Solution

  • Update:

    I "over-indexed" on the "shell code" payload. Your actual target of the injection doesn't use your shell code at all -- it simply executes 4 NOPs followed by RET, and thus doesn't do anything.

    Update 2: The new shell code disassembles to:

    objdump -D xx.o
    
    0000000000000000 <shellcode>:
       0:   b8 04 00 00 00          mov    $0x4,%eax
       5:   bb 01 00 00 00          mov    $0x1,%ebx
       a:   b9 00 a0 04 08          mov    $0x804a000,%ecx
       f:   ba 0d 00 00 00          mov    $0xd,%edx
      14:   cd 80                   int    $0x80
      16:   b8 01 00 00 00          mov    $0x1,%eax
      1b:   31 db                   xor    %ebx,%ebx
      1d:   cd 80                   int    $0x80
    

    Note the 0x804a000 address. This shell code is position dependent and will not run correctly unless mmap returns exactly the 0x804a000 address.

    You need to make this code position-independent (by using PC-relative addressing or pushing the Hello ... string on the stack and passing the stack address to the write system call).


    objdump -d -M intel shellcode_example

    The objdump shows two things which are wrong:

    1. You've built a position-dependent binary
    2. You've built it to call into dynamically-linked libc (puts here).

    A position-dependent binary must be loaded at the address it was linked at (0x08048000 here). You can't mmap that binary at arbitrary address and expect it to work).

    And a dynamically linked binary requires that the runtime loader sets up that binary's program linkage table (so calls to puts@plt get resolved to the symbol definition inside libc.so). But the runtime loader is completely unaware of this binary's existence, and so doesn't do anything for that binary.

    TL;DR: "shell code" must avoid using absolute addresses and dynamic linking (which is why it usually is written in assembly).