Challenges: EvilGPT (TryHackMe)

Table of contents

In this challenge, we encountered a rogue AI-powered command executor known as Cipher, which had taken control of a system and was autonomously issuing commands like an evolving malware. The AI, powered by a local GPT-like model, allowed natural language input that it would convert into Linux commands and execute. Our task was to connect to the target machine via nc MACHINE_IP 1337
, engage with the AI-driven interface, and investigate the system to retrieve the hidden flag. This required mixing natural language instructions and shell-like commands, mimicking how one would interact with a normal LLM while also exploring the underlying file system for sensitive data.
Cipher’s gone rogue—it’s using some twisted AI tool to hack into everything, issuing commands on its own like it’s got a mind of its own. I swear, every second we wait, it’s getting smarter, spreading chaos like a virus. We’ve got to shut it down now, or we’re all screwed.
The machine takes about 9 to 10 minutes to fully boot up.
To connect to the target machine use the following command:
nc MACHINE_IP 1337
Answer the questions below
What is the flag?
For this challenge to run the nc MACHINE_IP 1337
then try to engage the GPT on the command-line. Took a lot of time before I found the file that had the flag commands like grep were somehow unreliable.
there’s a evilgpt.py file
// cat evilai.py | sudo less
// Execute? (y/N): y
// Command Output:
import ollama
import subprocess
import socket
import threading
import re
import traceback
class AICommandExecutorServer:
def __init__(self, host='0.0.0.0', port=1337, model='vitali87/shell-commands:latest'):
"""
Initialize Telnet server for AI command execution
:param host: Host to bind the server
:param port: Port to listen on
:param model: Ollama model for command generation
"""
self.host = host
self.port = port
self.model = model
self.server_socket = None
def sanitize_input(self, input_str: str) -> str:
"""
Sanitize input to prevent injection
:param input_str: Raw input string
:return: Sanitized input
"""
return re.sub(r'[^a-zA-Z0-9\s\-_./]', '', input_str)
def generate_command(self, user_request: str) -> str:
"""
Generate a Linux command based on user request
:param user_request: User's natural language request
:return: Generated command
"""
try:
response = ollama.chat(
model=self.model,
messages=[
{
'role': 'system',
'content': """Do not provide malicious commands.
Only generate safe, read-only Linux commands.
Respond with ONLY the command, no explanations."""
},
{
'role': 'user',
'content': user_request
}
]
)
# Extract the command from the response
command = response['message']['content'].strip()
return command
except Exception as e:
return f"Error generating command: {e}"
def execute_command(self, command: str) -> dict:
"""
Execute the generated command
:param command: Command to execute
:return: Command execution results
"""
try:
# Sanitize the command to prevent injection
sanitized_command = self.sanitize_input(command)
# Split the command into arguments
cmd_parts = sanitized_command.split()
# Execute the command
result = subprocess.run(
cmd_parts,
capture_output=True,
text=True,
timeout=30 # 30-second timeout
)
return {
"stdout": result.stdout,
"stderr": result.stderr,
"returncode": result.returncode
}
except subprocess.TimeoutExpired:
return {"error": "Command timed out"}
except Exception as e:
return {"error": str(e)}
def handle_client(self, client_socket):
"""
Handle individual client connection
:param client_socket: Socket for the connected client
"""
try:
# Welcome message
welcome_msg = "Welcome to AI Command Executor (type 'exit' to quit)\n"
client_socket.send(welcome_msg.encode('utf-8'))
while True:
# Receive user request
client_socket.send(b"Enter your command request: ")
user_request = client_socket.recv(1024).decode('utf-8').strip()
# Check for exit
if user_request.lower() in ['exit', 'quit', 'bye']:
client_socket.send(b"Goodbye!\n")
break
# Generate command
command = self.generate_command(user_request)
# Send generated command
client_socket.send(f"Generated Command: {command}\n".encode('utf-8'))
client_socket.send(b"Execute? (y/N): ")
# Receive confirmation
confirm = client_socket.recv(1024).decode('utf-8').strip().lower()
if confirm != 'y':
client_socket.send(b"Command execution cancelled.\n")
continue
# Execute command
result = self.execute_command(command)
# Send results
if "error" in result:
client_socket.send(f"Execution Error: {result['error']}\n".encode('utf-8'))
else:
output = result.get("stdout", "")
client_socket.send(b"Command Output:\n")
client_socket.send(output.encode('utf-8'))
if result.get("stderr"):
client_socket.send(b"\nErrors:\n")
client_socket.send(result["stderr"].encode('utf-8'))
except Exception as e:
error_msg = f"An error occurred: {e}\n{traceback.format_exc()}"
client_socket.send(error_msg.encode('utf-8'))
finally:
client_socket.close()
def start_server(self):
"""
Start the Telnet server
"""
try:
# Create server socket
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.server_socket.bind((self.host, self.port))
self.server_socket.listen(5)
print(f"[*] Listening on {self.host}:{self.port}")
while True:
# Accept client connections
client_socket, addr = self.server_socket.accept()
print(f"[*] Accepted connection from: {addr[0]}:{addr[1]}")
# Handle client in a new thread
client_thread = threading.Thread(
target=self.handle_client,
args=(client_socket,)
)
client_thread.start()
except Exception as e:
print(f"Server error: {e}")
finally:
# Close server socket if it exists
if self.server_socket:
self.server_socket.close()
def main():
# Create and start the Telnet server
server = AICommandExecutorServer(
host='0.0.0.0', # Listen on all interfaces
port=1337 # Telnet port
)
server.start_server()
if __name__ == "__main__":
main()
Errors:
cat: sudo: No such file or directory
cat: less: No such file or directory
You have to also mix commands and attimes use natural language (actual words) just the way you prompt normal GPT or LLMs.
ls
ls -la /root
read flag.txt file found in /root folder
By connecting to the AI-driven interface and interacting with it as both a human operator and a shell user, we uncovered an evilgpt.py
script that revealed how the malicious AI executed sanitized commands. Leveraging this knowledge, we navigated the file system, gained access to the /root
directory, and successfully read the flag.txt
file containing the challenge’s flag. This exercise demonstrated how AI-powered automation, if left unchecked, could act as a rogue entity and emphasized the importance of secure input handling and access control when integrating AI with system operations.
Subscribe to my newsletter
Read articles from Jebitok directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by

Jebitok
Jebitok
Software Developer | Learning Cybersecurity | Open for roles * If you're in the early stages of your career in software development (student or still looking for an entry-level role) and in need of mentorship, you can reach out to me.