After a recent attack, we found this encrypted file. Luckily, we made a
memory dump, can you decrypt the file?

Archive password: lcoXse3oa3Uicioc
http://ebctf.nl/files/883f6fdf1a87b7651b7216e1354a7e1f/flag
http://194.171.96.106/ebctf/memory.7z

We took this exercise as an opportunity to learn to use volatility, so this writeup will be a little overcomplicated, we could have just done it with strings/grep, but it was a great way to learn more about how to search and exploit memory dump.

To begin with, we have a memory dump of a VirtualBox VM :

$ file memory.dump
memory.dump: ELF 64-bit LSB  core file x86-64, version 1 (SYSV)
$ readelf -n memory.dump

Notes at offset 0x000002a8 with length 0x00000480:
  Owner                 Data size       Description
  VBCORE               0x00000018       Unknown note type: (0x00000b00)
  VBCPU                0x00000440       Unknown note type: (0x00000b01)

A little examination of the raw data indicates that it should be a linux, as we see the grub code in memory, and some indication of a kernel version :

BOOT_IMAGE=/boot/vmlinuz-3.5.0-23-generic root=UUID=d45d9170-0f93-4ff4-b5a5-be89760c0d77 ro

A little more search indicates that it is an Ubuntu 12.04 x86_64 image.

In order to use volatility on linux dumps, we must build or find a profile of the kernel. Instructions for building a profile for a kernel can be found here.

With this profile in place we can now start to tinker with our dump. Let’s start with the process list :

$ vol.py --profile=LinuxUbuntu1204x64 -f memory.dump linux_pslist
Volatile Systems Volatility Framework 2.3_beta
Offset             Name                 Pid             Uid             Gid    DTB                Start Time
------------------ -------------------- --------------- --------------- ------ ------------------ ----------
0xffff88000f9b0000 init                 1               0               0      0x000000000aff1000 2013-07-21 19:19:32 UTC+0000
0xffff88000f9b1700 kthreadd             2               0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000f9b2e00 ksoftirqd/0          3               0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa48000 migration/0          6               0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa49700 watchdog/0           7               0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa4ae00 cpuset               8               0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa4c500 khelper              9               0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa4dc00 kdevtmpfs            10              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa68000 netns                11              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa69700 sync_supers          12              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa6ae00 bdi-default          13              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa6c500 kintegrityd          14              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fa6dc00 kblockd              15              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fb00000 ata_sff              16              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fb01700 khubd                17              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000fb02e00 md                   18              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000db90000 khungtaskd           21              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000db91700 kswapd0              22              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000db92e00 ksmd                 23              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000db94500 fsnotify_mark        24              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000db95c00 ecryptfs-kthrea      25              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000d5f0000 crypto               26              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000d7a5c00 kthrotld             35              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000d7a2e00 scsi_eh_0            36              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000d7a1700 kworker/u:2          37              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000d7a0000 scsi_eh_1            38              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000d5f5c00 scsi_eh_2            39              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000d5f4500 kworker/u:3          40              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000d5f1700 binder               42              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000f011700 deferwq              62              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000f012e00 charger_manager      63              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000f014500 devfreq_wq           64              0               0      ------------------ 2013-07-21 19:19:32 UTC+0000
0xffff88000ee35c00 jbd2/sda1-8          201             0               0      ------------------ 2013-07-21 19:19:33 UTC+0000
0xffff88000ee30000 ext4-dio-unwrit      202             0               0      ------------------ 2013-07-21 19:19:33 UTC+0000
0xffff88000ec7dc00 kworker/0:3          220             0               0      ------------------ 2013-07-21 19:19:35 UTC+0000
0xffff88000ec78000 upstart-udev-br      288             0               0      0x000000000ada3000 2013-07-21 19:19:37 UTC+0000
0xffff88000f2ddc00 udevd                332             0               0      0x000000000ef46000 2013-07-21 19:19:37 UTC+0000
0xffff88000c291700 udevd                496             0               0      0x000000000c2a6000 2013-07-21 19:19:37 UTC+0000
0xffff88000c292e00 udevd                497             0               0      0x000000000c2c1000 2013-07-21 19:19:37 UTC+0000
0xffff88000c838000 kpsmoused            546             0               0      ------------------ 2013-07-21 19:19:37 UTC+0000
0xffff88000c4c9700 upstart-socket-      638             0               0      0x000000000d939000 2013-07-21 19:19:38 UTC+0000
0xffff88000ee31700 dhclient3            706             0               0      0x000000000f0fb000 2013-07-21 19:19:38 UTC+0000
0xffff88000c4cc500 rsyslogd             720             101             103    0x000000000c600000 2013-07-21 19:19:38 UTC+0000
0xffff88000c83ae00 sshd                 729             0               0      0x000000000bbce000 2013-07-21 19:19:38 UTC+0000
0xffff88000c4cdc00 dbus-daemon          759             102             105    0x000000000c538000 2013-07-21 19:19:38 UTC+0000
0xffff88000d1aae00 getty                822             0               0      0x000000000c641000 2013-07-21 19:19:38 UTC+0000
0xffff88000c62c500 getty                827             0               0      0x000000000d98c000 2013-07-21 19:19:38 UTC+0000
0xffff88000c839700 login                831             0               1000   0x000000000f28d000 2013-07-21 19:19:38 UTC+0000
0xffff88000c83dc00 getty                832             0               0      0x000000000d9c1000 2013-07-21 19:19:38 UTC+0000
0xffff88000c4cae00 getty                834             0               0      0x000000000c684000 2013-07-21 19:19:38 UTC+0000
0xffff88000d0a4500 acpid                837             0               0      0x000000000c315000 2013-07-21 19:19:39 UTC+0000
0xffff88000c83c500 cron                 839             0               0      0x000000000d9da000 2013-07-21 19:19:39 UTC+0000
0xffff88000d1a9700 atd                  840             0               0      0x000000000c327000 2013-07-21 19:19:39 UTC+0000
0xffff88000da11700 login                896             0               1000   0x000000000ae44000 2013-07-21 19:19:39 UTC+0000
0xffff88000c514500 whoopsie             901             103             106    0x000000000dae3000 2013-07-21 19:19:39 UTC+0000
0xffff88000bb15c00 bash                 1064            1000            1000   0x000000000c6f0000 2013-07-21 19:19:46 UTC+0000
0xffff88000af90000 kworker/0:0          1313            0               0      ------------------ 2013-07-21 19:24:35 UTC+0000
0xffff88000af94500 kworker/0:2          1314            0               0      ------------------ 2013-07-21 19:29:36 UTC+0000
0xffff88000af91700 kworker/0:1          1315            0               0      ------------------ 2013-07-21 19:34:37 UTC+0000
0xffff88000af95c00 kworker/0:4          1316            0               0      ------------------ 2013-07-21 19:35:46 UTC+0000
0xffff88000af92e00 python2              1317            1000            1000   0x000000000c6fb000 2013-07-21 19:36:09 UTC+0000
0xffff88000d0a5c00 bash                 1454            1000            1000   0x000000000d8c8000 2013-07-21 19:36:23 UTC+0000
0xffff88000f9b4500 flush-8:0            1552            0               0      ------------------ 2013-07-21 19:36:28 UTC+0000

As we can see here, we have a python2 instance launched (pid 1317). Let’s examine the bash history, in order to see exactly what and how it has been launched. It is a quite long process, but with it we should be able to see exactly what was launched.

$ vol.py --profile=LinuxUbuntu1204x64 -f memory.dump linux_bash
Volatile Systems Volatility Framework 2.3_beta
Pid      Name                 Command Time                   Command
-------- -------------------- ------------------------------ -------
    1064 bash                 2013-07-21 19:19:47 UTC+0000   ps aux | grep ssh
    1064 bash                 2013-07-21 19:19:47 UTC+0000   sudo poweroff
    1064 bash                 2013-07-21 19:19:47 UTC+0000   ip addr
    1064 bash                 2013-07-21 19:20:53 UTC+0000   ls
    1064 bash                 2013-07-21 19:21:05 UTC+0000   python2 ctf.py
    1064 bash                 2013-07-21 19:21:29 UTC+0000   python2 ctf.py ' i hide my '
    1454 bash                 2013-07-21 19:36:23 UTC+0000   ps aux | grep ssh
    1454 bash                 2013-07-21 19:36:23 UTC+0000   sudo poweroff
    1454 bash                 2013-07-21 19:36:23 UTC+0000   ip addr
    1454 bash                 2013-07-21 19:36:29 UTC+0000   ps aux | grep python
    1454 bash                 2013-07-21 19:37:04 UTC+0000   kill -s SIGUSR1 1317

Ok, so we have a python2 script ctf.py launched and after that, killed by a SIGUSR1 signal.

If the code should still be in memory, but sadly, not in python memory, as was compiled before and the second launched should only load the pyc file.

But if we search in memory, we can simply grep for SIGUSR1 there should not be a lot of instance of it. And with that we get :

import sys
import time
import random
import signal
from Crypto.Cipher import AES
key1 = "is this where"
key2 = sys.argv[1]
key3 = raw_input("Password: ")
iv = 'a very random iv'
secret = './flag'
mode = AES.MODE_CBC
def encrypt(signum, frame):
        key = key1 + key2 + key3
        enc = AES.new(key, mode, iv)
        inp = raw_input("Enter secret: ")
        diff = len(inp) % 16
        if diff != 0:
                inp += ' ' * (16 - diff)
        with open(secret, 'wb') as outfile:
                outfile.write(enc.encrypt(inp))
        del key, enc
def decrypt(signum, frame):
        key = key1 + key2 + key3
        enc = AES.new(key, mode, iv)
        with open(secret, 'rb') as infile:
                print(enc.decrypt(infile.read(48)))
        del key, enc
signal.signal(signal.SIGUSR1, encrypt)
signal.signal(signal.SIGUSR2, decrypt)
while True:
        time.sleep(1)

Now we have the code. There is a decrypt function that should give us the flag. we have found key2 in the bash history, it was ' i hide my '. What we still miss is the key3 string. So let’s look at the python process memory.

$ vol.py --profile=LinuxUbuntu1204x64 -f memory.dump linux_proc_maps -p 131
Volatile Systems Volatility Framework 2.3_beta
Pid      Start              End                Flags               Pgoff Major  Minor  Inode      File Path
-------- ------------------ ------------------ ------ ------------------ ------ ------ ---------- --------------------------------------------------------------------------------
$ vol.py --profile=LinuxUbuntu1204x64 -f memory.dump linux_proc_maps -p 1317
Volatile Systems Volatility Framework 2.3_beta
Pid      Start              End                Flags               Pgoff Major  Minor  Inode      File Path
-------- ------------------ ------------------ ------ ------------------ ------ ------ ---------- --------------------------------------------------------------------------------
    1317 0x0000000000400000 0x0000000000671000 r-x                   0x0      8      1       1273 /usr/bin/python2.7
    1317 0x0000000000870000 0x0000000000871000 r--              0x270000      8      1       1273 /usr/bin/python2.7
    1317 0x0000000000871000 0x00000000008da000 rw-              0x271000      8      1       1273 /usr/bin/python2.7
    1317 0x00000000008da000 0x00000000008ec000 rw-                   0x0      0      0          0
    1317 0x0000000002109000 0x0000000002200000 rw-                   0x0      0      0          0 [heap]
    1317 0x00007f7e9a000000 0x00007f7e9a001000 rw-                   0x0      0      0          0
    1317 0x00007f7e9a001000 0x00007f7e9a009000 r-x                   0x0      8      1     146852 /usr/lib/python2.7/dist-packages/Crypto/Cipher/AES.so
    1317 0x00007f7e9a009000 0x00007f7e9a208000 ---                0x8000      8      1     146852 /usr/lib/python2.7/dist-packages/Crypto/Cipher/AES.so
    1317 0x00007f7e9a208000 0x00007f7e9a209000 r--                0x7000      8      1     146852 /usr/lib/python2.7/dist-packages/Crypto/Cipher/AES.so
    1317 0x00007f7e9a209000 0x00007f7e9a20a000 rw-                0x8000      8      1     146852 /usr/lib/python2.7/dist-packages/Crypto/Cipher/AES.so
    1317 0x00007f7e9a20a000 0x00007f7e9a4d3000 r--                   0x0      8      1       8358 /usr/lib/locale/locale-archive
    1317 0x00007f7e9a4d3000 0x00007f7e9a4e8000 r-x                   0x0      8      1        713 /lib/x86_64-linux-gnu/libgcc_s.so.1
    1317 0x00007f7e9a4e8000 0x00007f7e9a6e7000 ---               0x15000      8      1        713 /lib/x86_64-linux-gnu/libgcc_s.so.1
    1317 0x00007f7e9a6e7000 0x00007f7e9a6e8000 r--               0x14000      8      1        713 /lib/x86_64-linux-gnu/libgcc_s.so.1
    1317 0x00007f7e9a6e8000 0x00007f7e9a6e9000 rw-               0x15000      8      1        713 /lib/x86_64-linux-gnu/libgcc_s.so.1
    1317 0x00007f7e9a6e9000 0x00007f7e9a89e000 r-x                   0x0      8      1        968 /lib/x86_64-linux-gnu/libc-2.15.so
    1317 0x00007f7e9a89e000 0x00007f7e9aa9d000 ---              0x1b5000      8      1        968 /lib/x86_64-linux-gnu/libc-2.15.so
    1317 0x00007f7e9aa9d000 0x00007f7e9aaa1000 r--              0x1b4000      8      1        968 /lib/x86_64-linux-gnu/libc-2.15.so
    1317 0x00007f7e9aaa1000 0x00007f7e9aaa3000 rw-              0x1b8000      8      1        968 /lib/x86_64-linux-gnu/libc-2.15.so
    1317 0x00007f7e9aaa3000 0x00007f7e9aaa8000 rw-                   0x0      0      0          0
    1317 0x00007f7e9aaa8000 0x00007f7e9aba3000 r-x                   0x0      8      1        978 /lib/x86_64-linux-gnu/libm-2.15.so
    1317 0x00007f7e9aba3000 0x00007f7e9ada2000 ---               0xfb000      8      1        978 /lib/x86_64-linux-gnu/libm-2.15.so
    1317 0x00007f7e9ada2000 0x00007f7e9ada3000 r--               0xfa000      8      1        978 /lib/x86_64-linux-gnu/libm-2.15.so
    1317 0x00007f7e9ada3000 0x00007f7e9ada4000 rw-               0xfb000      8      1        978 /lib/x86_64-linux-gnu/libm-2.15.so
    1317 0x00007f7e9ada4000 0x00007f7e9adba000 r-x                   0x0      8      1       4874 /lib/x86_64-linux-gnu/libz.so.1.2.3.4
    1317 0x00007f7e9adba000 0x00007f7e9afb9000 ---               0x16000      8      1       4874 /lib/x86_64-linux-gnu/libz.so.1.2.3.4
    1317 0x00007f7e9afb9000 0x00007f7e9afba000 r--               0x15000      8      1       4874 /lib/x86_64-linux-gnu/libz.so.1.2.3.4
    1317 0x00007f7e9afba000 0x00007f7e9afbb000 rw-               0x16000      8      1       4874 /lib/x86_64-linux-gnu/libz.so.1.2.3.4
    1317 0x00007f7e9afbb000 0x00007f7e9b15a000 r-x                   0x0      8      1       1604 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
    1317 0x00007f7e9b15a000 0x00007f7e9b359000 ---              0x19f000      8      1       1604 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
    1317 0x00007f7e9b359000 0x00007f7e9b374000 r--              0x19e000      8      1       1604 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
    1317 0x00007f7e9b374000 0x00007f7e9b37f000 rw-              0x1b9000      8      1       1604 /lib/x86_64-linux-gnu/libcrypto.so.1.0.0
    1317 0x00007f7e9b37f000 0x00007f7e9b383000 rw-                   0x0      0      0          0
    1317 0x00007f7e9b383000 0x00007f7e9b3d5000 r-x                   0x0      8      1       1603 /lib/x86_64-linux-gnu/libssl.so.1.0.0
    1317 0x00007f7e9b3d5000 0x00007f7e9b5d5000 ---               0x52000      8      1       1603 /lib/x86_64-linux-gnu/libssl.so.1.0.0
    1317 0x00007f7e9b5d5000 0x00007f7e9b5d8000 r--               0x52000      8      1       1603 /lib/x86_64-linux-gnu/libssl.so.1.0.0
    1317 0x00007f7e9b5d8000 0x00007f7e9b5de000 rw-               0x55000      8      1       1603 /lib/x86_64-linux-gnu/libssl.so.1.0.0
    1317 0x00007f7e9b5de000 0x00007f7e9b5df000 rw-                   0x0      0      0          0
    1317 0x00007f7e9b5df000 0x00007f7e9b5e1000 r-x                   0x0      8      1        986 /lib/x86_64-linux-gnu/libutil-2.15.so
    1317 0x00007f7e9b5e1000 0x00007f7e9b7e0000 ---                0x2000      8      1        986 /lib/x86_64-linux-gnu/libutil-2.15.so
    1317 0x00007f7e9b7e0000 0x00007f7e9b7e1000 r--                0x1000      8      1        986 /lib/x86_64-linux-gnu/libutil-2.15.so
    1317 0x00007f7e9b7e1000 0x00007f7e9b7e2000 rw-                0x2000      8      1        986 /lib/x86_64-linux-gnu/libutil-2.15.so
    1317 0x00007f7e9b7e2000 0x00007f7e9b7e4000 r-x                   0x0      8      1        967 /lib/x86_64-linux-gnu/libdl-2.15.so
    1317 0x00007f7e9b7e4000 0x00007f7e9b9e4000 ---                0x2000      8      1        967 /lib/x86_64-linux-gnu/libdl-2.15.so
    1317 0x00007f7e9b9e4000 0x00007f7e9b9e5000 r--                0x2000      8      1        967 /lib/x86_64-linux-gnu/libdl-2.15.so
    1317 0x00007f7e9b9e5000 0x00007f7e9b9e6000 rw-                0x3000      8      1        967 /lib/x86_64-linux-gnu/libdl-2.15.so
    1317 0x00007f7e9b9e6000 0x00007f7e9b9fe000 r-x                   0x0      8      1        972 /lib/x86_64-linux-gnu/libpthread-2.15.so
    1317 0x00007f7e9b9fe000 0x00007f7e9bbfd000 ---               0x18000      8      1        972 /lib/x86_64-linux-gnu/libpthread-2.15.so
    1317 0x00007f7e9bbfd000 0x00007f7e9bbfe000 r--               0x17000      8      1        972 /lib/x86_64-linux-gnu/libpthread-2.15.so
    1317 0x00007f7e9bbfe000 0x00007f7e9bbff000 rw-               0x18000      8      1        972 /lib/x86_64-linux-gnu/libpthread-2.15.so
    1317 0x00007f7e9bbff000 0x00007f7e9bc03000 rw-                   0x0      0      0          0
    1317 0x00007f7e9bc03000 0x00007f7e9bc25000 r-x                   0x0      8      1        985 /lib/x86_64-linux-gnu/ld-2.15.so
    1317 0x00007f7e9bca2000 0x00007f7e9bd96000 rw-                   0x0      0      0          0
    1317 0x00007f7e9bd97000 0x00007f7e9be1f000 rw-                   0x0      0      0          0
    1317 0x00007f7e9be23000 0x00007f7e9be25000 rw-                   0x0      0      0          0
    1317 0x00007f7e9be25000 0x00007f7e9be26000 r--               0x22000      8      1        985 /lib/x86_64-linux-gnu/ld-2.15.so
    1317 0x00007f7e9be26000 0x00007f7e9be28000 rw-               0x23000      8      1        985 /lib/x86_64-linux-gnu/ld-2.15.so
    1317 0x00007fff39317000 0x00007fff39339000 rw-                   0x0      0      0          0 [stack]
    1317 0x00007fff393ff000 0x00007fff39400000 r-x                   0x0      0      0          0

The python2 heap are on high addresses, and we should have some of the strings in it. So let’s dump all the address space and search in it.

$ vol.py --profile=LinuxUbuntu1204x64 -f memory.dump linux_dump_map -p 1317 -D output/
$ grep -r 'i hide my' output/
Binary file output/task.1317.0x7f7e9bca2000.vma matches
Binary file output/task.1317.0x7fff39317000.vma matches
$ strings output/task.1317.0x7f7e9bca2000.vma | grep 'i hide my'
 i hide my
is this where i hide my secrets?
$ strings output/task.1317.0x7fff39317000.vma | grep 'i hide my'
 i hide my

As we can see that it should be 'secrets?'. So we have the final modified python script :

import sys
import time
import random
import signal
from Crypto.Cipher import AES
key1 = "is this where"
key2 = ' i hide my '
key3 = 'secrets?'
iv = 'a very random iv'
secret = './flag'
mode = AES.MODE_CBC
def encrypt(signum, frame):
        key = key1 + key2 + key3
        enc = AES.new(key, mode, iv)
        inp = raw_input("Enter secret: ")
        diff = len(inp) % 16
        if diff != 0:
                inp += ' ' * (16 - diff)
        with open(secret, 'wb') as outfile:
                outfile.write(enc.encrypt(inp))
        del key, enc
def decrypt(signum, frame):
        key = key1 + key2 + key3
        enc = AES.new(key, mode, iv)
        with open(secret, 'rb') as infile:
                print(enc.decrypt(infile.read(48)))
        del key, enc

print(decrypt(0, 0))

and the flag is :

$ python2 ctf.py
ebctf{55169c1c241aa20412da94b3fcbf8506}

This challenge was interesting, thank you Eindbazen and NFI for these Forensics Challenges. We did not had the time to finish any other, but we will do them later. We hope to see more forensics challenges like that in future CTFs.