Infected

NDH 2018 - Forensic (550 pts).

NDH 2018 - Infected

Event Challenge Category Points Solves
Nuit du hack 16 Infected Forensic 550 3 (first blood \o/)

Description

This forensic task was submitted at Nuit du hack 2018 in Paris. This challenge took me around 5 hours! In this write-up, we will deal with Linux memory dump, Windows 10 memory dump, Windows mechanics and a bit of steganography.

TL;DR

At the beginning of this task, I started with the file infected.exe (~600 Mo). A quick analysis later, it occurred to me the infected.exe file was a PNG file instead of PE.

With binwalk I’ve been able to carve 2 BMP pictures and 1 encrypted archive (Zip). The password is hidden in the second BMP file, with LSB method (extracted with stegsolve).

After decrypting the archive, I got 1 other encrypted archive and a Linux memory dump. To use volatility on this dump I had to create a new profile:

OS: Ubuntu 14.04.1

Kernel: 3.13.0-66-generic

The password to decrypt the second archive is in the bash history.

In the second encrypted archive, there is a Windows 10 memory dump. Windows can use 8-bits encoded data, but it uses 16-bits encoded data too. Then, I did a strings -e l on the memory dump and I found a SHA1 hash to crack, and flag :-)

State of the art

Well, I started this challenge at midnight approximately (the time is important). The first step, determine if the infected.exe file is really a PE file.

$ file infected.exe
infected.exe: PNG image data, 244 x 337, 8-bit/color RGBA, non-interlaced
$ ll infected.exe
-rw-r--r-- 1 maki users 599M  2 juil. 14:40 infected.exe

Well, a picture of 599 Mo… Let’s extract some data ;-)

$ binwalk -e infected.png
DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PNG image, 244 x 337, 8-bit/color RGBA, non-interlaced
12488         0x30C8          Zip archive data, at least v1.0 to extract, compressed size: 627739148, uncompressed size: 627739148, name: step1.zip
627751653     0x256ABAE5      End of Zip archive
628094451     0x256FF5F3      End of Zip archive

$ ll _infected_binwalk
-rw-r--r-- 1 maki users 599M  4 juin  15:59 step1.zip
-rw-r--r-- 1 maki users 1,2M  4 juin  14:45 билэ.bmp
-rw-r--r-- 1 maki users 901K  4 juin  15:51 ключ.bmp

The step1.zip is encrypted and contains 2 files:

$ zipinfo step1.zip
Archive:  step1.zip
Zip file size: 627739148 bytes, number of entries: 2
-rw-a--     6.3 fat 557933864 Bx lzma 18-Jun-04 09:50 1.elf
-rw-a--     6.3 fat 499247924 Bx stor 18-Jun-04 14:24 2.zip
2 files, 1057181788 bytes uncompressed, 627738858 bytes compressed:  40.6%

Step1 - Stegano

The password of the step1.zip is hidden in the ключ.bmp (renamed in img2.png). I used StegSolve to exract the password:

Fig 1 - Zip password in LSB

After many tries and revert the picture, I finally found the password:

I13eYu&!yd2lC@lne

$ 7za x step1.zip
[...]

Enter password (will not be echoed): I13eYu&!yd2lC@lne

$ ll step1
-rw-r--r-- 1 maki users 533M  4 juin  09:50 1.elf
-rw-r--r-- 1 maki users 477M  4 juin  14:24 2.zip

Right, at this time we are probably at 1 AM.

Step2 - Linux memory dump

Let’s start with real forensic stuff.

Determine OS and Kernel version

First, the 1.elf is a Linux memory dump:

$ strings 1.elf | grep "Linux version" | sort | uniq
[    0.000000] Linux version 3.13.0-66-generic (buildd@lgw01-26) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #108-Ubuntu SMP Wed Oct 7 15:20:27 UTC 2015 (Ubuntu 3.13.0-66.108-generic 3.13.11-ckt27)
Jun  4 09:44:32 caine kernel: [    0.000000] Linux version 3.13.0-66-generic (buildd@lgw01-26) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #108-Ubuntu SMP Wed Oct 7 15:20:27 UTC 2015 (Ubuntu 3.13.0-66.108-generic 3.13.11-ckt27)
Linux version 3.13.0-66-generic (buildd@lgw01-26) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #108-Ubuntu SMP Wed Oct 7 15:20:27 UTC 2015 (Ubuntu 3.13.0-66.108-generic 3.13.11-ckt27)

$ strings 1.elf | grep "Ubuntu 14.0" | sort | uniq
# deb cdrom:[Ubuntu 14.04.1 LTS _Trusty Tahr_ - Release amd64 (20140722.2)]/ trusty main restricted
Description: Ubuntu 14.04 Wallpapers
elcome to Ubuntu 14.04.3 LTS (GNU/Linux 3.13.0-66-generic x86_64)
"Ubuntu 14.04.3 LTS"
Ubuntu 14.04.3 LTS
 Wallpapers from the Ubuntu 14.04 community contest
Welcome to Ubuntu 14.04.3 LTS (GNU/Linux 3.13.0-66-generic x86_64)

Kernel: 3.13.0-66-generic

OS: Ubuntu 14.04.3

We know one thing: we have to do a new volatility profile. It’s not the regular kernel version for Ubuntu 14.04.


#### Profile creation

First of all, download the right Ubuntu version: http://old-releases.ubuntu.com/releases/14.04.1/ubuntu-14.04.1-desktop-amd64.iso

And install it in your favorite hypervisor. When the install is done, just install the new Linux Kernel:

```bash
$ sudo apt-get update && sudo apt-get install linux-image-3.13.0-66-generic linux-headers-3.13.0-66-generic volatility-tools

Well, the new kernel is installed, we have to reboot the machine. Now, let’s create the good profile.

$ uname -a
Linux ubuntu 3.13.0-66-generic #108-Ubuntu SMP Wed Oct 7 15:20:27 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux

$ cd /usr/src/volatility-tools
$ chmod -R 777 linux/ # I know, it's bad
$ cd linux && make
$ ll
-rwxrwxrwx 1 root root     378 Mar 25  2013 Makefile*
-rwxrwxrwx 1 root root   13831 Mar 30  2013 module.c*
-rw-rw-r-- 1 toto toto 1732757 Jul  2 06:17 module.dwarf
drwxrwxrwx 2 root root    4096 Jun 30 16:15 pmem/

$ zip ndh_infected.zip /usr/src/volatility-tools/linux/module.dwarf /boot/System.map-3.13.0-66-generic

Now, just place this new volatility profile in the right place (on the machine containing the memdump obviously).

$ sudo cp ~/Documents/CTF/ndh16/infected/ndh_infected.zip  /usr/lib/python2.7/site-packages/volatility/plugins/overlays/linux

$ volatility --info | grep infected
Volatility Foundation Volatility Framework 2.6
Linuxndh_infectedx64      - A Profile for Linux ndh_infected

$ volatility -f 1.elf  --profile=Linuxndh_infectedx64 linux_banner
Volatility Foundation Volatility Framework 2.6
Linux version 3.13.0-66-generic (buildd@lgw01-26) (gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) ) #108-Ubuntu SMP Wed Oct 7 15:20:27 UTC 2015 (Ubuntu 3.13.0-66.108-generic 3.13.11-ckt27)

Great, our volatility profile seems to work. But we have to stay focus on our goal: Find the password of the encrypted archive.

You can download my volatility profile here: ndh_infected.zip

Find the password

Let’s check the bash history:

$ volatility -f 1.elf  --profile=Linuxndh_infectedx64 linux_bash
Volatility Foundation Volatility Framework 2.6
Pid      Name                 Command Time                   Command
-------- -------------------- ------------------------------ -------
    5986 bash                 2018-06-04 07:46:54 UTC+0000   loadkeys fr
    5986 bash                 2018-06-04 07:47:01 UTC+0000   sudo loadkeys fr
    5986 bash                 2018-06-04 07:47:09 UTC+0000   cls
    5986 bash                 2018-06-04 07:47:16 UTC+0000   clear
    5986 bash                 2018-06-04 07:47:27 UTC+0000   loadkeys
    5986 bash                 2018-06-04 07:47:33 UTC+0000   loadkeys fr
    5986 bash                 2018-06-04 07:47:38 UTC+0000   sudo loadkeys fr
    5986 bash                 2018-06-04 07:47:47 UTC+0000   sudo bash
    5986 bash                 2018-06-04 07:48:28 UTC+0000   setxkbmap fr
    5986 bash                 2018-06-04 07:48:34 UTC+0000   cls
    5986 bash                 2018-06-04 07:48:37 UTC+0000   clear
    5986 bash                 2018-06-04 07:48:43 UTC+0000   reset
    5986 bash                 2018-06-04 07:49:14 UTC+0000   echo "ObP&CWfh2K18"

w00t! I found the second password:

ObP&CWfh2K18

It looks easy, but during the challenge I didn’t wait long enough, I just stopped the command because it was too long… And after that, I lost 1 big hour…

Well, no problem, we keep going.

Step3 - Windows stuff

No more encrypted zip archive, the final part! We’re close!

Let’s play with volatility…

Which OS?

$ strings 2.elf | grep 'Linux version'
# No output...

$ volatility -f 2.elf imageinfo
Volatility Foundation Volatility Framework 2.6
INFO    : volatility.debug    : Determining profile based on KDBG search...
          Suggested Profile(s) : Win10x64_10586, Win10x64_14393, Win10x64, Win2016x64_14393
                     AS Layer1 : Win10AMD64PagedMemory (Kernel AS)
                     AS Layer2 : VirtualBoxCoreDumpElf64 (Unnamed AS)
                     AS Layer3 : FileAddressSpace (/home/maki/Documents/CTF/ndh16/infected/temp/_infected.png.extracted/step1/step2/2.elf)
                      PAE type : No PAE
                           DTB : 0x1aa000L
             KUSER_SHARED_DATA : 0xfffff78000000000L
           Image date and time : 2048-12-31 20:59:32 UTC+0000
     Image local date and time : 2048-12-31 23:59:32 +0300

Windows 10, nice. Well, we have a memory dump from a sandbox, then there is some malware on the desktop:

  • NJRAT_REMAKE.EXE
  • DEFENDERCONTROL\DefenderControl\DefenderControl.exe
  • NJRAT_0_7D.EXE
  • XENOS64.EXE
  • WINMM_NET.DLL
  • CLASSLIBRARY1.DLL

My first hypothesis was: reverse the NJRAT_REMAKE.EXE and try to find the flag. After a while, I started to analyze XENOS64.EXE and DDLs but nothing too…

It’s around 5 AM now, and we’re tired and a bit angry.

…But don’t need it.

After chatting with @Big5, he released 1 hint per step. For the last step the hint was something like:

Volatility is so high level… lol

And I understood that I have to deal with strings and grep. But, Windows uses 16-bits encoded data, and by default strings is looking for 8-bits encoded data.

So let’s try something:

$ strings -a -e l 2.elf > memdump_strings_16bits
$ cat memdump_strings_16bits | grep "ndh"
ndh_crackedhash
[...]

Hmmm.. I tried to validate the task with that, obviously, it didn’t work.

Step 4 - Crack the hash

Well, after strings .. grep, let’s go for less:

$ less memdump_strings_16bits
[...]
ndh_crackedhash
FileVersion
InternalName
CALC
LegalCopyright
64ce3703bc4937a1b9edc6f15bfa1e9357807ce4
[...]

64ce3703bc4937a1b9edc6f15bfa1e9357807ce4

Go to hashkiller to break the SHA1, the clear text is:

NO2603

Flag

Finally the flag:

ndh_NO2603

And now it’s around 5h30AM! I spent a lot of time on this task (5 hours maybe more), but it was worth, we earned 650 points with the “First blood”.

@makhno and @shutdown spent a lot of time on this task too, they validate it with their team few minutes after, GG to all of us! :)

Feel free to contact me on twitter @AlanMarrec1 if you have any question or anything else.

Thanks for reading.

Maki