The Art of the Shellcode: A Practical Journey into x86-64 Assembly
Welcome to new series on The Art of the Shellcode: A Practical Journey into x86-64 Assembly.
Have you ever wondered what happens beneath the high-level languages like Python, Java, or C++? Beneath the comforting abstractions and memory-managed safety lies the raw, unadulterated power of the processor itself. It speaks a language of simple, brutal instructions: MOV, ADD, JMP, INT. This is the world of x86-64 Assembly.
One of the most powerful—and ethically significant—applications of this knowledge is the creation of shellcode.
Shellcode is a small, self-contained piece of code, often written in assembly, that is injected into a running program with the goal of getting it to execute our commands. Traditionally, this means spawning a shell (hence the name “shellcode”), but it can be any piece of code you want to run. It’s the payload in many software exploits, the final step in taking control of a program’s execution flow.
In this blog series, we will embark on a hands-on journey. We will start from absolute zero, assuming you’ve never seen a line of assembly before. We will build up your understanding piece by piece, from the basic syntax of x86-64 to the intricate tricks needed to craft functional shellcode. We’ll tackle the challenges head-on: dealing with null bytes, finding our own code in memory, and writing code that is as compact as it is powerful.
Syllabus
We will divide this series into two sections -
Part 1: x86-64 Assembly
- Introduction
- Computer Architecture
- Data Representation
- Assembly Language Basics
- Data Representation and Basic Arithmetic Instructions
- Flags
- Bitwise Instructions
- Branch Instructions
- Array and Addressing Modes
- Multiplication and Division Instructions
- Shift and Rotate Instructions
- Strings
- Stack and Procedures
Part 2: Shellcoding
- Introduction
- Diving into Syscall
- First Shellcode - Hello World!
- Spawning a shell
- Eliminating Bad Chars
- Bind TCP Shell
- Reverse TCP Shell