Crimediggers is a promotional escape game brought out by the Dutch police. It’s a very high-quality, realistic challenge and generally aimed at recruiting digital specialists for the police’s cybercrime teams. Completing Crimediggers requires previous knowledge in the computer security domain.
In this post, I share my path of progressing through the challenges. Solutions to the individual objectives will not be included, where possible, to avoid taking the fun away from other participants. DM me if you need help with any of these, and I’ll be happy to assist. Let’s get started!
Briefing
Upon entering the challenge, we’re met with a short briefing:
/ BRIEFINGUlrieke Doosjé, a politician at Nederland Rechtdoor, suddenly disappeared during a press conference. A targeted cyber attack disrupted the conference, and Doosjé has been untraceable ever since. We need to find her as soon as possible. Our team on site has secured several pieces of evidence for you. Your team leader will bring you up to speed./ TEAM CRIMEDIGGERSOf course, you are not alone in this research. A team of specialists is ready to help you. You will soon get to know them better. If they have something to say, you will see it in the team menu./ MY NOTESIf you want to take notes during the research, it is possible. You can also view and supplement your notes with new information at any time. Sometimes you will need information from previous levels, so keep the traces/evidence well./ UNIQUE LINKYour progress is saved as long as you are on the same computer. Do you want to ensure you don't lose your session? Then save this unique link.
Sounds good! Virgil, the team leader, and Frederike, the data scientist, meet us.
Virgil: Ah, there we have our new digital detective! We just got the surveillance footage from the conference center. Do you want to look at it with Frederieke? I will also make sure that you quickly get to know the other team members.
Frederike: Hey, Igor, right? Nice to meet you! My name is Frederieke, and I am a data scientist. Do you have a moment to watch the surveillance footage? Samira just forwarded them. The tactical team is combing the entire conference center for leads. They would like to know exactly where Doosjé has been so that they can search more precisely.
Objective 1: CCTV cameras
Here we need to review the CCTV feed of 16 cameras in an attempt to spot the movements of Ulrieke.
After a careful review, we can see her appearing on feeds of five cameras:
- TRH03
- GNG03
- and three more!
Objective 2: License plate
Virgil: Okay, the press is watching. That was to be expected, so don’t let it distract you. We just received the ANPR data from the parking garage. Could you find out if Ulrieke got into a car there? A license plate would be great.
We’re working off a hypothesis that Ulrieke got into a car in the parking garage. The task is to find out in what car Ulrieke left the parking garage on September 20 at 19:07.
We receive a file called logs.csv
. After scanning the document, we see that the date formats differ. I searched for “September 20” and was lucky enough to find a row with a time value of 19:07. Checking for other entries on September 20 confirms that only one car left the garage at 19:07 – a grey Tesla 🚙
Let’s see what we can do to get the license plate Virgil was asking for.
Looking at the format used to store license plates,
17#grijs#Tesla#Ry00OTtUF=#Sep …
we can see that it’s likely base64-encoded. Therefore it’s easy to decode using a shell command.
Let’s make Virgil and the team happy by submitting the license plate number to the system.
Cyberchef
By the way, in case we couldn’t determine the encoding right away, we could use a tool like Cyberchef:
CyberChef is a web application developed by GCHQ that’s been called the “Cyber Swiss Army Knife”. From theCyberChef Githubpage:
CyberChef is a simple, intuitive web app for carrying out all manner of “cyber” operations within a web browser.
These operations include simple encodings like XOR or Base64, more complex encryption like AES, DES, and Blowfish, creating binary and hex dumps, compression and decompression of data, calculating hashes and checksums, IPv6 and X.509 parsing, changing character encodings, and much more.
What is CyberChef used for?
CyberChef can be used to Encode, Decode, Format data, Parse data, Encrypt, Decrypt, Compress data, Extract data, perform arithmetic functions against data, defang data, and many other functions.
This tool can be downloaded from Github and run on your local machine, or it can be run inside the browser at this link:https://gchq.github.io/CyberChef/
Objective 3: IP address
Next, we have Arno wondering whether somebody hacked Ulrieke’s phone.
Agent: Orlando performed a “chip-off” on Ulrieke’s phone. Now this raw data is available for examination.
Forensics professionals generally use disk image files to verify captured data and to check for any manipulations and alterations in the data. In digital forensics, many forensic examiners depend on .dd files since it sometimes reveals the essential clues for their investigation.
Alright, let’s mount the image so that we can inspect it. For this objective and all that follow, I used the Kali Linux distribution: a Linux operating system pre-loaded with all kinds of practical tools so that you can focus on the task instead of having to install everything first.
┌──(igor㉿kali)-[~/Downloads]
└─$ mkdir phone
┌──(igor㉿kali)-[~/Downloads]
└─$ sudo mount -o loop phone_final.dd phone
After a quick browse through the directories, it becomes clear that we’re looking at an Android phone.
In the /app
directory, we see another one with an interesting name: com.confengine.android_chat_app
This is not one of the apps supplied with Android by default. Let’s decompile the base.apk
APK file using apktool
:
Let’s inspect the contents of the decompiled APK:
┌──(igor㉿kali)-[~/…/smali/com/agilefaqs/chatapp]
;
└─$ cd base/smali/com/agilefaqs/chatapp
ls
BackDoor.smali 'MainActivity$2$1.smali' 'MainActivity$ViewHolder.smali'
Crypter.smali 'MainActivity$2.smali' MainActivity.smali
DividerItemDecoration.smali 'MainActivity$3.smali'
'MainActivity$1.smali' 'MainActivity$4.smali'
Great, at least two Interesting files. Let’s start by inspecting BackDoor.smali
, which clearly suggests a “hacking attempt”, as mentioned in the task.
In the file, we can see the IPv4 address of the Command and Control server starting with 136.144
A command-and-control (C2) server is the primary tool cyber threat actors use to launch and control cyber-attacks. Threat actors use C2s to send commands to their malware and to distribute malicious programs, malicious scripts, and more.
They also use them to receive stolen data that they exfiltrated from target servers, devices, websites, and forms. In short, C2s are the technical brain behind a threat actor’s malicious operations.
This page has more detail on how C2 (or C&C) servers workhttps://www.malwarepatrol.net/command-control-servers-c2-servers-fundamentals/
Objective 4: Hacker’s name
Virgil is happy with our findings of the C2 server and wants to get more information about the hacker – presumably, the one running the C&C server.
Accessing the server using the IP address we found previously, the server suggests that there are two websites hosted there:
- https://welingelichtebronnen.nl/– a news website
- https://huur-een-hacker.nl– a “rent a hacker” service
Clicking through the pages of the news site gives us little: it’s a static website exposing no opportunities to dig deeper. The same thing applies to the hacker renting service – static pages, no suggestion of a client/admin area.
Since we don’t know what we’re looking for and where, let’s try searching for hidden gems and enumerate some directories. Using Dirbuster, a directory bruteforce/enumeration tool, we’ll map out the website’s directory structure. It makes sense to use a VPN connection for such kinds of tasks.
I tried several configuration setups (remember, we don’t know what we’re looking for)
After taking a somewhat embarrassingly long time tweaking Dirbuster, there’s a light of hope: a hidden .git
directory on the server.
To better understand why this may be valuable, check here to read that among many other service files, there’s usually one called config
, and it may contain the name of the repository maintainer, and likely even their email address.
The config gives us an email address. Great progress! 🕺
After a quick googling session, we see a YouTube channel of the person.
They have two videos uploaded with seemingly no interesting information. Still, I fast-forward through both videos.
In one of them, I see agent R.A.T. helping uncover the address label on a used-to-be delivery box. The video doesn’t have a high-resolution option, but after applying several passes of sharpening, we can finally read the person’s name.
Objective 5: GPS coordinates
Things are getting serious! Agent: You got him! We’re going to find out the address, and the tactical team will prepare a raid on this Niko van der S. Nice work!
In the meantime, Ulrieke got out of the car somewhere between Eindhoven and Amstelveen.
Virgil: Orlando read the car’s onboard computer. Can you find out where she got out?
We receive two files with the E01 extension. Let’s take a pause here and first check what these are.
What is EWF?
Herehttps://www.loc.gov/preservation/digital/formats/fdd/fdd000406.shtmlwe read that EWF is short for “Expert Witness Disk Image Format”.
EWF files are disk image files that contain the contents and structure of an entire data storage device, a disk volume, or (in some cases) a computer’s physical memory (RAM).
EWF files may take one of two forms. The first is referred to as a bitstream or forensic image: it is a sector-by-sector copy of the source, thereby replicating the structure and contents of the storage device independent of the file system. Bitstream images include static data like the files and fragments that reside in unallocated space, including deleted files that have not yet been overwritten.
The second form is called a logical evidence file. It preserves the original files as they existed on the media and documents the assigned file name and extension, DateTime created, modified, and last accessed, etc. Logical evidence files are typically created after an analysis locates some files of interest, and for forensic reasons, they are kept in an “evidence grade” container. Thus, in some situations, a user may have both a bitstream image and a logical evidence file.
Understanding EnCase image naming
Great! We now know a lot (a bit too much?) about EWF files. Let’s try to understand what to do with them.
Based on thispage:
If the media provided contains a series of files, which all have thesame namebutdifferent extensions, and the first one has the E01 extension, then you have been provided with an EnCase Image.
After the “E01 file”, each file has the same name but a different extension, increasing linearly: E02, E03, etc. Example: if the first file is called ExhibitA.E01
, the second one will be ExhibitA.E02
, and the third one will be ExhibtA.E03
.
Regardless of how many files there are starting with “ExhibitA”, if there is only one E01 file, there is only one image. Multiple files are used because Encase can chunk up the image for ease of movement/storage.
Let’s look at another example. Imagine we have the following files:
Disk1.E01
,Disk1.E02
,Disk1.E03
Disk2.E01
,Disk2.E02
this means that there are two different images: Disk1
and Disk2
.
Good stuff! We now know that carimage1.E01 and carimage2.E01 are images of different disks. Let’s try to mount them.
┌──(igor㉿kali)-[~/Downloads/carimage]
└─$ mkdir carimage1 carimage2
┌──(igor㉿kali)-[~/Downloads/carimage]
└─$ sudo ewfmount carimage1.E01 carimage1/
ewfmount 20140813
┌──(igor㉿kali)-[~/Downloads/carimage]
└─$ sudo ewfmount carimage2.E01 carimage2
ewfmount 20140813
All good and mounted, but there’s just one problem: we can’t access any of the files! Something must be wrong – or these images are not typical hard disk images.
After mounting those images as loop devices as follows, I was able to get helpful insight using the file
command:
┌──(igor㉿kali)-[~/Downloads/carimage]└─$ sudo losetup /dev/loop10 carimage1/ewf1┌──(igor㉿kali)-[~/Downloads/carimage]└─$ sudo losetup /dev/loop11 carimage2/ewf1
The output of the file
command:
Since the disks were installed in a car, this suggests that they were used as a RAID array in either RAID-0 or RAID-1 configuration. Another mode, JBOD, is also possible, but that would be unusual in a car. Anyway, let’s try assembling these disks into one accessible volume:
┌──(igor㉿kali)-[~/Downloads/carimage]
└─$ sudo mdadm --assemble /dev/md0 /dev/loop10 /dev/loop11
mdadm: /dev/md0 has been started with 2 drives.
We can see two disks appear in the file management system window. Optionally, you can mount the resulting /dev/md0
using a mount point of preference.
After exploring the filesystem for a while, looking into /var/logs
shows some interesting files. In particular, Car_gps.log
shows Ulrieke’s car coordinates, suggesting that we will likely figure out where she got out of the car using the file.
After editing it to only contain coordinates (regular expressions help speed up the filtering), I uploaded them to the GPS visualizer website.
Since we know to look at points between Amstelveen and Eindhoven, I traced the whole path between the two locations. Mcdonald’s in Breukelen stands out since it has two GPS locations recorded. After trying both, one is accepted by the Crimediggers website (it helps that they don’t subtract points for wrong submissions anymore!).
And just like that, we make Virgil happy again: Ulrieke did indeed get out there. CCTV footage shows her walking along the road to the Van der Valk motel. The tactical team will get there as soon as possible. And meanwhile, another team is ready to raid our hacker!
Objective 6: Bitcoin Wallet address
Agent: How fast was that! (referring to the video of the arrest) But we did it! We got the hacker’s computer up and running! Can you search for the payment? Unless he had his motive for the harassment, we must find the client.
We get a forensic image of the laptop, in which we’re supposed to find a Bitcoin wallet address.
Let’s start with the usuals: mounting the image.
┌──(igor㉿kali)-[~/Downloads/laptop6]
└─$ sudo ewfmount laptop.e0* lap3
ewfmount 20140813
┌──(igor㉿kali)-[~/Downloads/laptop6]
└─$ sudo losetup /dev/loop14 lap3/ewf1
Let’s learn more about the layout of the partitions with mmls
:
Good, we can see some partitions. Let’s mount the Linux partition for examination. To calculate the offset, we use sector size (512) and the desired start position (0000002048): 2048 * 512 = 1048576
┌──(igor㉿kali)-[~/Downloads/laptop6]
└─$ sudo mkdir /mnt/laptop6
┌──(igor㉿kali)-[~/Downloads/laptop6]
└─$ sudo mount -t ext4 -o ro,loop,offset=1048576 /dev/loop14 /mnt/laptop6
Now we can see the good stuff! Documents, downloads, projects, and other files of the suspected person.
After some time browsing through the files while paying particular attention to the files/folders related to communication software like browsers, mail clients, and IM, – I found a hidden directory of the Thunderbird email client in the user’s home directory.
After copying it for examination, an unencrypted .mbox
file can be seen. It contains many email conversations, most of them spam.
Searching for “Bitcoin” doesn’t bring much (would have been too easy?):
Tracing the conversation with <[emailprotected]>
, where payment agreements are being made, gives us the transaction ID.
Using this ID, we can check theblockchain.comwebsite for transaction details and get the wallet ID of the client.
Objective 7: Password of Ulrieke’s laptop
Agent: “Top job! Now we can request all data about the transaction from Bitonic. Hopefully, that will bring us closer to the client. Hey, by the way, turn up the volume. We’re in the news!”
Agent: “We’re here at the motel, but Ulrieke is not here. I have her laptop here – do you have any idea what the password could be? I’ll send you a picture of the login screen.”
We are given a photo of the login screen on the laptop and a photo of some Post-it notes found near the computer. The login screen suggests that the password has something to do with cats. The post-its don’t give any valuable pointers (except for one leading to this conspiracy theoryhttps://en.wikipedia.org/wiki/Free_energy_suppression_conspiracy_theory)
I spent quite some time on this one, slowly reviewing earlier evidence.
After getting back to surfing through files and directories of Ulrieke’s phone (the one containing the chat app with the C&C server address), a file called crypt.db
can be found:
┌──(igor㉿kali)-[~/…/data/com.confengine.android_chat_app/databases]
└─$ ls
crypt.db
While viewing it with “DB Browser for SQLite”, we can see a table called messages
, containing records that look base64-encoded. Decoding them doesn’t reveal plain text and confirms the assumption that these are also encrypted.
Let’s analyze the APK source files we decompiled earlier.
The file called Crypter quickly hints that an XOR cipher (also known as Repeating Key Encryption) is applied before encoding with base64.
Now we have to make a little detour to gather all the messages in one file. Below is how I did it, but there are many different ways to achieve the same (and probably faster):
- Export the “messages” table to a CSV, a file called
messages.csv
- Read the file and filter out everything that is not a base64-encoded message, record the results:
$ column -s, -t < messages.csv | grep -Pio "(?<=[0-9]{3}[\ ]{2})[a-zA-Z=0-9+/]{3,}" > messages_encrypted.txt
- Assuming we’re dealing with a standard XOR, use the following Ruby function to decode the message:
def decrypt(phrase, key)
phrase.bytes.map.with_index do |char, index|
char ^ key.bytes[index % key.length]
end.map(&:chr).join
end - Run all messages through the function above:
File.foreach("messages_encrypted.txt") { |line| p dec(Base64.decode64(line), 'ULRIEKE') }
Most of the messages are decrypted with no issues.
Reading through conversations takes time, and making sense of them takes even longer. We need to keep in mind that more than two people are conversing (see the contacts table in the DB).
Looking for anything related to cats, we can fish out the name of Ulrieke’s pet – likely the one pictured on the login screen.
Objective 8: Name of the whistleblower
Agent: I researched the Bitcoin transaction. One Lisanne Slienk paid with iDEAL, and I was able to trace the payment back to Furciver. You know, that energy company!
They must have a link with the whistleblower. Can you search Ulrieke’s files for a motive? What did Ulrieke want to announce? Who is the whistleblower?
After downloading and unpacking the file named bureaublad-ulrieke.zip
with Ulrieke’s computer’s desktop contents, we see several files, the most interesting one being the PDF – because it’s password-protected.
Nothing useful in the contents of the zip to move this forward.
At some point long into the process, I remembered seeing several out-of-place-looking messages from the previous step while decoding the chat messages. After scrolling through them a few times, I spotted the password that the PDF accepted. It begins with f>k3(298R
…
Since we’re after a name with the initials “YY”, finding the full name doesn’t take long.
Objective 9: “Exit plan” location
Agent: “I’m here at Furciver HQ, but we’re just a tad too late! The cupboards have all been emptied, and the director Jan-Jaap Bleijenberg-Witteman has just left here in great haste, according to the porter. He was calling, yelling into the phone, “I’m coming, 20 minutes! Get the Agusta ready for departure!”
What does that mean? Where did he go? We need answers ASAP, or we’ll lose him!”
Ok, it’s obvious that “Agusta” can “depart”. Let’s assume it’s a special car, a ship, or a plane.
Out of the two files provided by Samira, one is a mailbox of the lawyer, and another contains a few photos of the office. We’re given 20 minutes to finish the task, and the clock is ticking! ⏱️
A quick scroll through the mailbox gives little. Thinking I missed something, I do a first pass through the pictures, but that also brings nothing. Re-reading the task, remembering that Augusta can drive/sail/fly, and looking at the photos again, the logo with a propeller catches my attention. I tried Googling “EHVV” in a few different ways, didn’t help.
And the timer is still going!
Only after noticing my typo I corrected the search to “EHHV”, which quickly showed an airport in Hilversum. Its address turns out to be the destination the director is headed to.
Bonus knowledge point: “Agusta” is definitely a plane!
Agent: Yes! We found Jan-Jaap Bleijenberg-Witteman’s car in the airport parking lot. Witnesses saw him and a woman get out! A woman, you hear!But… There are a hundred planes and helicopters here. Which aircraft should we ground? Time is ticking away! 🚨
Objective 10: Heli’s Call Sign
Ok, it’s not a plane; it’s a helicopter. Doesn’t change much for us!
Agent: I have been given a list of all aircraft that are now grounded. Air traffic control cooperates and can ground all flights. Though I don’t think that will stop our fugitive. We need to find out which aircraft belongs to him.
And just like that, we get a .xlsx
list with call signs. Too many entries to make sense of it. After searching for JJ
(initials of the person in question), I found a row starting with PH-JJ
. The complete sign is PH-JJBW
, where BW corresponds to his last name. Nice touch!
Next, we see a TV broadcast reporting that Ulrieke is safe and can be seen petting her cat, presumably at home. Well done!
It’s been a unique, refreshing experience requiring the activation of all possible thinking powers while offering a priceless chance to learn many new things. Huge thanks to everyone involved in the creation of this five-star experience! Thank you for reading!