Writing a Shell Code for Linux
Shellcoding is the art of writing position-independent code that can be used as the payload in exploitation scenarios. In this guide, we'll explore how to write shellcode for x86 Linux systems, starting with simple examples and progressively increasing complexity. Understanding Shellcode Basics Before diving into code, let's understand some key concepts:
Position-Independence: Shellcode must run regardless of where in memory it's loaded Null-Free: Often shellcode must avoid null bytes (0x00) as these can terminate string processing System Calls: Linux shellcode typically uses system calls to interact with the kernel Assembly Language: Shellcode is written in assembly for precise control and minimal size
System Call Conventions in x86 Linux In x86 Linux, system calls follow these conventions:
System call number goes in EAX register Arguments go in EBX, ECX, EDX, ESI, EDI, EBP (in that order) The int 0x80 instruction triggers the system call
Example 1: Exit Shellcode
#include <stdlib.h>
void main(){
exit(5);
}
thilan@ubuntu:~$ gcc exit.c -o exit -m32
thilan@ubuntu:~$ ./exit
thilan@ubuntu:~$ echo $?
5
thilan@ubuntu:~$ objdump -M intel -d exit
0804841d <main>:
804841d: 55 push ebp
804841e: 89 e5 mov ebp,esp
8048420: 83 e4 f0 and esp,0xfffffff0
8048423: 83 ec 10 sub esp,0x10
8048426: c7 04 24 05 00 00 00 mov DWORD PTR [esp],0x5
804842d: e8 ce fe ff ff call 8048300 <exit@plt>
8048432: 66 90 xchg ax,ax
8048434: 66 90 xchg ax,ax
8048436: 66 90 xchg ax,ax
8048438: 66 90 xchg ax,ax
804843a: 66 90 xchg ax,ax
804843c: 66 90 xchg ax,ax
804843e: 66 90 xchg ax,ax