Blog | G5 Cyber Security

Understanding C Shellcode

TL;DR

C shellcode is machine code written in a way that can be injected and executed by another process. It’s often used in exploits to gain control of a system. This guide explains how it works, how to create simple shellcode, and basic techniques for testing it.

What is Shellcode?

Shellcode is a small piece of code, typically written in assembly language (often derived from C), designed to be injected into a vulnerable process. When executed, this code performs malicious actions – like spawning a shell, creating a backdoor, or modifying system files. The ‘shell’ part refers to the common goal of opening a command shell on the target machine.

Why use C (or rather, why compile from C)?

While you write shellcode in assembly language ultimately, compiling from C offers several advantages:

The key is that you compile your C code into machine code, then extract that machine code as a byte array to be used as shellcode.

Creating Simple Shellcode (Example: Executing /bin/sh)

  1. Write the C Code: This example spawns a shell.
  2. #include 
    #include 
    #include 
    
    int main() {
      char *command = "/bin/sh";
      system(command);
      return 0;
    }
    
  3. Compile the Code: Use GCC to compile the code into an executable, and then extract the machine code. We’ll use a few flags for this:
    • -fno-stack-protector: Disables stack protection mechanisms that can interfere with shellcode extraction.
    • -z execstack: Allows execution of code on the stack (necessary for injection). Warning: This is a security risk and should only be used in controlled environments.
    • -m32 or -m64: Specifies the architecture (32-bit or 64-bit) – match this to your target system!
    gcc -fno-stack-protector -z execstack -m32 shell.c -o shell
    objdump -d shell | grep "
  4. Extract the Shellcode: The objdump command will output assembly code. You need to find the machine code instructions within the

Testing Shellcode

  1. Simple Test Program: Create a C program to execute the shellcode directly.
    #include 
    #include 
    #include 
    
    int main() {
      unsigned char shellcode[] = { /* Your shellcode bytes here */ };
      int (*func)() = (int (*)())shellcode;
      func();
      return 0;
    }
    
  2. Compile and Run: Compile the test program and run it. If your shellcode is correct, you should see the expected behavior (e.g., a shell prompt).

    Remember to compile with -fno-stack-protector -z execstack.

  3. Debugging: Use a debugger (like GDB) to step through the execution of your test program and verify that the shellcode is being executed correctly.

Important Considerations

Exit mobile version