Shellcode
What's a shellcode ?
A shellcode is a string of characters representing an executable binary code capable of launching any application on the machine. In most cases, a shellcode opens a shell to gain full access to the machine. Generally, shellcodes are injected into the machine's memory by exploiting a stack buffer overflow
, use after free
, heap buffer overflow
vulnerabilities. A shellcode basically creates a shell which allows it to execute any code the attacker wants.
Basic shellcode.
Before starting anything, here's some useful informations. A shellcode is generally written in assembly. That's mean you have to write different shellcodes according to the target's operating system (Linux, OSX, BSD, Windows...) and processor architecture (x86, x64, arm...). You can find pre-maked shellcodes at shell storm.
Here, we are going to make shellcode for x64 linux systems.
This code executes the execve
system call to run /bin/sh
with NULL arguments and environment. It zeroes out rsi
and rdx
(setting argv
and envp
to NULL), sets rdi
to point to the string /bin//sh
, places the execve
syscall number (59) in rax
, and invokes the syscall.
We can "compile" this code using the following command.
nasm -f elf64 -o shell.o <the_shellcode_file>
: Uses NASM to assemble the shellcode source file into a 64-bit ELF object file namedshell.o
.ld -o shell shell.o
: Uses the linker to create an executable namedshell
from theshell.o
object file.
This command sequence compiles and links your assembly shellcode into an executable binary that can be run on a 64-bit Linux system.
Finally, you can use the binutils
to get the string of characters representing an executable binary code.
You can try your shellcode with the following script. This code is used to provide a C template to paste shellcode into and be able to run it live from within an ELF binary's char buffer. This allows you to create a buffer with the shellcode globally and this program will mark it as RWX
using mprotect()
and then finally jump into. This code is made by Travis Phillips.
Compile it like this.
Polymorphic shellcode
Polymorphic shellcode changes its appearance every time it is generated, but the core functionality of the code remains the same. This is achieved through techniques such as:
Encryption: The shellcode is encrypted using various encryption algorithms, and a decryption routine is included that decrypts the shellcode at runtime.
Variable Substitution: Changing variable names, register usage, and using different instructions that achieve the same result.
Instruction Substitution: Replacing instructions with equivalent instructions or instruction sequences (e.g., replacing a
MOV
instruction with a combination ofPUSH
andPOP
).
The key characteristic of polymorphic shellcode is that while the code looks different each time it is generated, it performs the same operations when executed.
The rest is coming soon...
Metamorphic shellcode
Metamorphic shellcode takes the obfuscation process a step further by not only changing the appearance of the code but also altering its internal structure and logic. This involves:
Code Reordering: Changing the order of instructions or code blocks in a way that doesn't affect the overall functionality.
Code Insertion: Adding junk or no-op instructions that do not affect the program's logic.
Control Flow Modification: Altering the control flow by using techniques like changing loops, reordering branches, and adding conditional statements that always evaluate to true.
The metamorphic approach modifies the actual code structure, making it more difficult to detect patterns that anti-virus software might rely on. As a result, the generated shellcode can look drastically different in terms of both appearance and structure, even though it ultimately performs the same task.
The rest is coming soon...
I would like to thank:
Last updated