Thursday, October 22, 2015

Hack.lu 2015 CTF Write Up: Dr. Bob (Forensic 150)

Hack.lu 2015 CTF was organised by fluxfingers during October 20-22. It's one of the coolest CTFs around, the only drawback is that it runs during week days (hey guys patch this for the next years). My team TheGoonies ranked #59th, which is not bad considering we only played part-time.

The task Dr. Bob was the one I found most interesting as it included disk forensics, memory forensics and basic crypto tasks.

Task: Dr. Bob (Forensic 150)

There are elections at the moment for the representative of the students and the winner will be announced tomorrow by the head of elections Dr. Bob. The local schoolyard gang is gambling on the winner and you could really use that extra cash. Luckily, you are able to hack into the mainframe of the school and get a copy of the virtual machine that is used by Dr. Bob to store the results. The desired information is in the file /home/bob/flag.txt, easy as that.


The file provided is a VirtualBox image in a saved state. According to the challenge instructions, we have to retrieve the flag from the user home folder. The VM starts on a login terminal of what seems to be a Linux distro.


The easiest route here is to convert the VDI image to raw, mount and extract the key from the home folder. VirtualBox has a builtin tool to convert VDI to raw and it's as simple as:

C:\Program Files\Oracle\VirtualBox\VBoxManage.exe internalcommands converttoraw c:\ctf\home\dr_bob\.VirtualBox\Safe\Safe.vdi c:\ctf\safe.dd


Let's identify the raw image and mount it externally:
sudo fdisk -lu safe.dd

sudo losetup -o 1048576 /dev/loop0 safe.dd
sudo lvmdiskscan


There are two interesting devices: /dev/vg/root and /dev/vg/home, let's 1 - mount the home folder, 2 - grab the flag and 3 - PROFIT!!!


Oh noes, the disk is encrypted... I couldn't find any useful data on the root device (/dev/vg/root). I tried to crack some local password hashes but I didn't get anything and logs/history files didn't reveal any secrets. Time to unleash some CSI skills and perform live memory forensics.


Memory Forensics: Rekall

Unlike VMWare virtual machines, VirtualBox does not offer an easy-to-use memory dump (as far as I know). What do we do now? It's time to perform VM introspection with Rekall.

Memory Analysis Inception
Rekall is the first memory framework to support transparent introspection of VMs with any host-guest OS combination and is independent of the virtualization software layer.


Building the Profile

Linux support in Rekall requires a tailoured profile to the running kernel as well as the System map file. The profile file contains all the debugging symbols extracted into a Rekall standard profile format. To generate this file, it is necessary to build a kernel module with debugging symbols enabled, and then parse the DWARF debugging symbols.

The operating system is a Debian 7.9 i686, with 3.2.0-4-486 Kernel.


The Linux Guide from rekall repository is pretty straightforward. I downloaded a Debian 7.9 i386 ISO, installed it on a clean system, installed the Kernel headers from the target VM and built the corresponding profiles. I mirrored them here:

Memory Analysis Inception

Now that we have the proper profile, we can run VirtualBox, start the VM and perform live forensics on the guest machine.

The vmscan plugin scans the physical memory attempting to find hypervisors and group them together logically as virtual machines.

It's possible to run plugins on any VM by using the --ept (Extended Page Tables) parameter on the command line. To run a rekall plugin on a VM that vmscan found, invoke rekall as you normally would, but add --ept EPT_VALUE as a parameter.

rekal -f \\.\pmem vmscan --live
rekal.exe -f \\.\pmem --profile Debian-3.2.0-4-486.zip --ept 0x1ECC0701E


I tried to use the base Plugins that supports Linux analysis, but none of them revealed the secrets necessary to decrypt the disk.


After some time I decided to take a different approach and dump the full memory from the Guest VM and carve for some secrets.

imagecopy output_image='memdump.raw'



Extracting AES Keys from the Memory Dump

You can use tools like bulk_extractor and findaes to extract AES keys from memory dumps. These programs work by carving the images and eliminating anything which is not a valid AES key schedule.

./findaes memdump.raw


The tools found an AES-128 key, and I now needed to recreate this behavior on a lab to make sure that it was the encryption master-key. I set up an encrypted volume on a Debian installation and dumped the master keys using cryptsetup:

cryptsetup luksDump --dump-master-key /dev/sda5


After that, I dumped the operating system memory and used bulk_extractor to search for AES Keys:

bulk_extractor memdump.raw


The AES256 key matches with the MK dump, what brings us to the final step.


Decrypting LUKS volume using the Master Key

Now that we have the AES Key, all we need to do is follow this guide - Cryptsetup and the master key - and decrypt '/dev/vg/home'. There's no command-line to decrypt the disk using the master-key, everything is kind of hackish (you need to corrupt the headers and create a new one using the key).

sudo losetup -o 1048576 /dev/loop1 safe.dd
cryptsetup -v luksDump /dev/vg/home


The Master Key (MK) has 128 bits, which is a good sign. The payload offset is 2048 and we need to do some basic math here to get the LUKS header size: 2048 * 512 / 1024 = 1024 (fdisk -l shows that the cluster size is 512 bytes).

We now proceed to write a new LUKS header on the device using the extracted MK, assigning a new passphrase:

dd if=/dev/vg/home of=test.img
hexdump -C -n 80 test.img
dd if=/dev/zero of=test.img conv=notrunc bs=1024 count=1
hexdump -C -v -n 80 test.img
echo 1fab015c1e3df9eac8728f65d3d16646 | xxd -r -p > key.bin


cryptsetup luksFormat --verify-passphrase --cipher=aes-ecb --hash=sha1 --key-size=128 --master-key-file=key.bin test.img


They tried to hide the flag from "/bin/cat" using the carriage return char (0x0D), but hexdump and Pluma had no problems displaying it:

               

             


Flag: flag{v0t3_f0r_p3dr0}


Update 1: @rbaranyi and David Berard pointed out that replacing '/etc/shadow', login with the known password and then use 'strings /dev/lvm' would be easier. That's true, but that wouldn't involve any kind of memory inception.

Update 2: David Berard pointed out that newer 'cryptsetup' offers an option to set a new passphrase using the master key: 'cryptsetup luksAddKey --master-key-file=<master-key-file> <luks device>'

Update 3: According to the writeup from CLGT, you can also dump  VirtualBox RAM using this administrative command: 'VBoxManage debugvm SafeClone dumpvmcore --filename=getthekey'

Update 4: Some teams used the dm_dump volatility plugin: it identifies disks on the target system which were mounted using the device-mapper framework. The output of this plugin gives you the arguments to pass to the dmsetup command to remount the original unencrypted file system on a different machine.

4 comments:

  1. Or : sed -i -e 's|OLD_ROOT_SHADOW|NEW_SHADOW|g' Safe.vdi; boot VM; login; dd if=home_crypt |string

    ReplyDelete
  2. Or easier for the last part: cryptsetup luksAddKey --master-key-file=keydumped

    (cf. https://gitlab.com/cryptsetup/cryptsetup/wikis/FrequentlyAskedQuestions#6-backup-and-data-recovery)

    ReplyDelete
    Replies
    1. Updated the post with that info, thanks =)

      Delete