Writeup: INS'hAck 2018 - Take a look inside

Information

  • category: Forensics
  • points: 400

Description

I acquired some information about my PC because I think someone messed up with it…

You can find everything attached.

Please find out what’s wrong about these captures.

Have fun!

Source: takealookinside.zip

Writeup

This challenge was resolved as an exercise during a weekly meeting and after the end of the CTF.

Analysis

We have a memory dump and a pcap.

PCAP

Two endpoints:

192.168.56.1 and 192.168.56.101 doing TCP traffic (a lot).
Recreating the TCP Stream is a way too long task for wireshark but we can see that IP .101 is sending a lot of data to IP .1 (1 sends only ACKs); filtering only packets with useful data (data.len > 4) from 101 to 1 (data will be in HEX encoding) should be easy with tshark:

tshark -r taking-a-look-inside.pcap -T fields -e data -Y 'ip.src == 192.168.56.101 && data.len > 4' > taking-a-look-inside.out

Using xxd in possibile to convert the HEX data to ASCII.

xxd -r -p taking-a-look-inside.out > taking-a-look-inside.b64

-r reverse operation: convert (or patch) hexdump into binary. If not writing to stdout, xxd writes into its output file without truncating it. Use the combination -r -p to read plain hexadecimal dumps without line number information and without a particular column layout.

Now we have the complete payload and we can see a pattern:

  1. SCN|
  2. a base64 payload
  3. NCS|
  4. goto 1

cat taking-a-look-inside.b64 | sed "s/SCN|\||NCS/\n\n/g" > taking-a-look-inside.txt

In taking-a-look-inside.txt now there are only base64 payload separated with two new lines. Let’s take a look at the first payload:

cat taking-a-look-inside.txt| rg "^$" -A 1 -m 2 | base64 -d > first.data
file fist.data: first.data: data => GARBAGE!

rg is RipGrep (alternative written in Rust to grep): https://github.com/BurntSushi/ripgrep

Memory Dump

Fist we need to identify the memory dump profile to use with volatility.

volatility -f taking-a-look-inside.dmp imageinfo should return the correct profile…no results after some time.

Alternative method for unknown profiles (if is unknown is probably Linux):

strings taking-a-look-inside.dmp | rg -i boot_image

Response: /boot/vmlinuz-4.9.0-6-amd64; a quick Google search will lead us to identify the machine as a Debian with kernel 4.9.0 (64-bit).
But we need a volatility profile to work with, two ways:

  1. Install Debian 9.4 x64 in a VM and follow this steps: https://github.com/volatilityfoundation/volatility/wiki/Linux#creating-a-new-profile
  2. Find a profile: https://github.com/volatilityfoundation/profiles/pull/52

Now is possibile to use volatility:

volatility --plugins=../ -f taking-a-look-inside.dmp --profile=LinuxDebian94x64 linux_pstree

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
olatility Foundation Volatility Framework 2.6
Name Pid Uid
systemd 1
.systemd-journal 195
.systemd-udevd 205
.ModemManager 370
.irqbalance 371
.rsyslogd 372
.rtkit-daemon 373 105
.cron 374
.systemd-logind 375
.dbus-daemon 376 108
.avahi-daemon 405 113
..avahi-daemon 419 113
.accounts-daemon 407
.NetworkManager 409
..dhclient 475
.polkitd 421
.gdm3 498
..gdm-session-wor 506
...gdm-wayland-ses 528 116
....gnome-session-b 532 116
.....gnome-shell 540 116
......Xwayland 557 116
.....gnome-settings- 589 116
..gdm-session-wor 630
...gdm-x-session 686 1000
....Xorg 688 1000
....gnome-session-b 702 1000
.....ssh-agent 782 1000
.....gnome-shell 818 1000
.....gnome-settings- 921 1000
.....gnome-software 966 1000
.....tracker-miner-u 979 1000
.....tracker-miner-f 986 1000
.....tracker-extract 993 1000
.....tracker-miner-a 997 1000
.....evolution-alarm 1034 1000
.VBoxService 513
.systemd 523 116
..(sd-pam) 524 116
..dbus-daemon 530 116
..at-spi-bus-laun 563 116
...dbus-daemon 568 116
..at-spi2-registr 570 116
..pulseaudio 574 116
.upowerd 544
.wpa_supplicant 587
.packagekitd 588
.colord 604 114
.minissdpd 653
.systemd 676 1000
..(sd-pam) 677 1000
..dbus-daemon 699 1000
..at-spi-bus-laun 794 1000
...dbus-daemon 799 1000
..at-spi2-registr 802 1000
..gvfsd 823 1000
..gvfsd-fuse 828 1000
..evolution-sourc 858 1000
..gnome-shell-cal 854 1000
..mission-control 880 1000
..goa-daemon 868 1000
..goa-identity-se 881 1000
..gvfs-udisks2-vo 891 1000
..gvfs-mtp-volume 904 1000
..gvfs-afc-volume 908 1000
..gvfs-goa-volume 913 1000
..gvfs-gphoto2-vo 917 1000
..evolution-calen 944 1000
...evolution-calen 1050 1000
...evolution-calen 1074 1000
..tracker-store 981 1000
..evolution-addre 1075 1000
...evolution-addre 1100 1000
..dconf-service 1067 1000
..gnome-terminal- 1162 1000
...zsh 1168 1000
....su 1355 1000
.....zsh 1356
......python3 2530
......python3 4524
.......[python3] 4645
...zsh 1226 1000
....gimp 2079 1000
.....script-fu 2270 1000
...zsh 2283 1000
....su 2321 1000
.....zsh 2322
......insmod 4638
...zsh 3301 1000
....su 4168 1000
.....zsh 4169
......tshark 4505
.......dumpcap 4523
..dhclient 1605
..gvfsd-metadata 3122 1000
.gnome-keyring-d 683 1000
.VBoxClient 753 1000
..VBoxClient 755 1000
.VBoxClient 764 1000
..VBoxClient 766 1000
.VBoxClient 771 1000
..VBoxClient 772 1000
.VBoxClient 777 1000
..VBoxClient 779 1000
.pulseaudio 847 1000
.udisksd 894
.gsd-printer 985 1000
[kthreadd] 2
.[ksoftirqd/0] 3
.[kworker/0:0H] 5
.[rcu_sched] 7
.[rcu_bh] 8
.[migration/0] 9
.[lru-add-drain] 10
.[watchdog/0] 11
.[cpuhp/0] 12
.[cpuhp/1] 13
.[watchdog/1] 14
.[migration/1] 15
.[ksoftirqd/1] 16
.[kworker/1:0H] 18
.[kdevtmpfs] 19
.[netns] 20
.[khungtaskd] 21
.[oom_reaper] 22
.[writeback] 23
.[kcompactd0] 24
.[ksmd] 26
.[khugepaged] 27
.[crypto] 28
.[kintegrityd] 29
.[bioset] 30
.[kblockd] 31
.[devfreq_wq] 32
.[watchdogd] 33
.[kswapd0] 34
.[vmstat] 35
.[kthrotld] 47
.[ipv6_addrconf] 48
.[ata_sff] 84
.[kworker/u4:1] 92
.[scsi_eh_0] 112
.[scsi_tmf_0] 113
.[scsi_eh_1] 114
.[scsi_tmf_1] 115
.[scsi_eh_2] 117
.[scsi_tmf_2] 118
.[bioset] 120
.[bioset] 121
.[kworker/1:1H] 124
.[kworker/0:1H] 129
.[jbd2/sda1-8] 164
.[ext4-rsv-conver] 165
.[kauditd] 199
.[iprt-VBoxWQueue] 262
.[ttm_swap] 316
.[kworker/u4:0] 2640
.[kworker/1:1] 2941
.[kworker/0:1] 3087
.[kworker/0:0] 3137
.[kworker/1:0] 3357
.[kworker/1:2] 4500

The zsh processes took our attention: python3, gimp, insmod and tshark.

Using:

volatility --plugins=../ -f taking-a-look-inside.dmp --profile=LinuxDebian94x64 linux_enumerate_files | rg -i zsh_history`

and

volatility --plugins=../ -f taking-a-look-inside.dmp --profile=LinuxDebian94x64 linux_find_file -i 0xffff97e9c78883e8 -O zsh_history

we recovered the zsh history file and some interesting commands:

1
2
3
4
: 1522658873:0;./goggles --host=192.168.56.1
: 1522659187:0;python3
: 1522659978:0;clear
: 1522659980:0;./goggles --host=192.168.56.1

Since 192.168.56.1 is the target of our traffic we should focus on the script goggles and his log in /tmp/goggles.log.

1
2
3
4
volatility --plugins=../ -f taking-a-look-inside.dmp --profile=LinuxDebian94x64 linux_find_file -L | rg -i goggls
Volatility Foundation Volatility Framework 2.6
32635 0xffff97e9c7989818 /tmp/goggles.log
18 0xffff97e9fd74c000 /media/sf_vms-share/taking-a-look-inside/src/goggles

But exporting those files will lead us to a dead end.

./goggles script take a --host= as a paremeter so we can expect to find the same string in memory (if the script is in memory).

Also no strings matching INS{ (better safe than sorry!).

Findings

strings taking-a-look-inside.dmp| rg -i "\-\-host" -A 5

1
2
3
4
5
6
]2;./goggles --host=192.168.56.1
]1;./goggles
> sending size bytes: b'\x00\x03I\xe0'
> sending 215520 bytes
>> 86880 of 215520 bytes sent.
>> 215520 of 215520 bytes sent.

But no others clues…

Wait…goggles is a python script so we can search for a classic python string as import or print(.

For import (with space) and 3 lines after:

1
2
3
4
>>> import hashlib
>>> m = hashlib.md5()
>>> m.update(b"Nobody inspects")
>>> m.update(b" the spammish repetition")
1
2
3
4
5
6
from builtins import property as _property, tuple as _tuple
from operator import itemgetter as _itemgetter
from collections import OrderedDict
class TokenInfo(tuple):
'TokenInfo(type, string, start, end, line)'
__slots__ = ()
1
2
3
4
5
>>> from Crypto.Cipher import AES
>>> from Crypto import Random
>>>
>>> key = b'Sixteen byte key'
>>> iv = Random.new().read(AES.block_size)

Found something interesting!
Maybe the traffic in the pcap is generated with an AES cypher!

Let’s try to recover all the script and/or the key and/or the AES method used.

In zsh_history we saw pip install -r requirements.txt but other hints.

strings is our friend:

strings taking-a-look-inside.dmp | rg "AES" we found something:

[mAES_KEY = [25;5Hcipher = AES.new(AES_KEY, AES.MODE_ECB)

>>> cipher = AES.new(key, AES.MODE_CFB, iv)

maybe the script is using AES in ECB or CFB mode and, also, with a variable AES_KEY or key as encryption key.

strings is such a good friend!!!

strings taking-a-look-inside.dmp| rg "AES_KEY =" -A 3

1
2
3
4
[mAES_KEY = 
[0;1m
[32m'd3Adb3Efc4Feb4Be'
[18d

We found a key! d3Adb3Efc4Feb4Be and the first candidate is AES.MODE_ECB due to the function above; we need a script to decrypt the traffic in taking-a-look-inside.txt.

Good old deadbeef cafebabe!

Decryption

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import sys
import base64
try:
from Crypto.Cipher import AES
except ModuleNotFoundError:
print("install pycrypto!")
sys.exit(1)

AES_KEY = "d3Adb3Efc4Feb4Be"

with open("../sources/taking-a-look-inside/taking-a-look-inside.txt",
"r") as enc:
f = enc.read()
ciphers = f.split("\n\n")

for i, c in enumerate(ciphers):
if len(c) > 1:
with open("newfile_" + str(i) + ".png", "wb") as nf:
cipher = base64.b64decode(c)
aes = AES.new(AES_KEY, AES.MODE_ECB)
decrypted = aes.decrypt(cipher)
nf.write(decrypted)

Decrypting each row in the txt files and using file to detect the file type we got 36 PNGs; these images are screnshoots from the execution of goggles and a tmp.xcf opened in GIMP with the flag.

No way to dump the xcf file from volatility…

Flag

INSA{aa80467558a76019b99ecec7b4f6d0c7}