Init

How do I say it? I wasn’t expecting anything like this at all… it’s kinda hardware-jeopardy-ish.

Actually, a day after this event I have to present my fyp, so I’m literally traveling back and forth between Johor and Selangor like crazy.

People usually do this kind of thing for their gf, but I’m doing it for ctf 😭.

alt text

Format Overview

The format of the competition is really unique I would say, and it consists of an immense amount of hardware hacking knowledge, to be more specific the usage of proxmark.

Luckily my group mate, @TanSc was there and he literally cloned a couple of cards before using his own phone, so proxmark should not be a problem for him.

There are multiple stages btw, and if you didn’t manage to solve the previous stage you couldn’t proceed to solve the other one and it’s something like this:

  1. Stage 0 - Card Cracking
  2. Stage 1 - Open Sesame
  3. Stage 2 - Scada Hacking

Stage 0 - Card Cracking (Token)

So for us to access stage 1, we need to get the token available inside the card (solving stage 0 first).

alt text

Stage 0 is quite easy, all you need to do is crack the MIFARE keys of the card, and then dump the data contained inside it.

alt text

hf mf darkside command to recover the first key of the card

hf mf nested use first key to find other keys

hf mf dump extract all data once keys are owned

Here is the data that was dumped, it is in hex 746F6B656E3A65383734386534306336 0000000000000000000000000

1
2
3
4
// Convert the hex string to text
const hexString = "746F6B656E3A65383734386534306336";
const textResult = hexString.match(/.{1,2}/g).map(byte => String.fromCharCode(parseInt(byte, 16))).join('');
console.log("Decoded text:", textResult);

Change it to text from hex, and we got the token to access the web panel, and vpn file (will come in handy for stage 2 instances) for our team!

alt text

Stage 1 - Open Sesame (Watson)

Okay for this part right here it’s a little bit tricky.

They actually gave us the Raspberry Pi image a day before, and we need to find out where the challenges are located inside the image, so it is actually testing out our forensic knowledge here.

Challenges were found at /opt/janus and this is the one to solve watson

1
2
3
4
5
6
7
8
9
10
def watson(uid, blocks):
_, node, release, *_ = platform.uname()
codename = platform.freedesktop_os_release()['VERSION_CODENAME']
_, ver = platform.libc_ver()
checks = [uid, node.encode(), release.encode(), codename.encode(), ver.encode()]
for check, block in zip(checks, blocks):
if hashlib.md5(check).digest() != block:
send_error(f'watson: invalid block [{block.hex()}]')
return False
return True

So we need to use the card given, and fill it with the raspberry pi infos:

  1. the UID of our team’s card
  2. the node hostname
  3. the kernel release string
  4. the OS codename
  5. the C library version

Computes an MD5 of each piece and compares to one block each (data block)

  1. 3d955d7444c80970660bc3233ba398b6
  2. df256845c7212af8a6ef1a25d13ba7be
  3. b879b8d65ca0895296e64e3e87928d10
  4. e0bfa30ac77faf071cda9e9af49d9bcc
  5. 46ef89558baf4b56a4c29fe69c21ab10

All infos can be collected like so:

Mount the raspberry pi image and do the following to get:

  1. node hostname
1
cat /etc/hostname
  1. kernel release string
1
2
3
┌──(aan㉿aan)-[/mnt/pi]
└─$ ls /mnt/pi/lib/modules/
6.12.25+rpt-rpi-2712 6.12.25+rpt-rpi-v8

Tried both versions, turns out this one works 6.12.25+rpt-rpi-v8

  1. OS codename
1
2
3
4
5
6
7
8
9
10
11
┌──(aan㉿aan)-[/mnt/pi]
└─$ cat /mnt/pi/etc/os-release
PRETTY_NAME="Debian GNU/Linux 12 (bookworm)"
NAME="Debian GNU/Linux"
VERSION_ID="12"
VERSION="12 (bookworm)"
VERSION_CODENAME=bookworm
ID=debian
HOME_URL="https://www.debian.org/"
SUPPORT_URL="https://www.debian.org/support"
BUG_REPORT_URL="https://bugs.debian.org/"

It’s bookworm

  1. C Library Version
1
2
3
┌──(aan㉿aan)-[/mnt/pi/lib]
└─$ grep -A10 "Package: libc6$" /mnt/pi/var/lib/dpkg/status | grep Version
Version: 2.36-9+rpt2+deb12u10

It’s 2.36

Now we need to overwrite the data into the card’s data block, can use proxmark given

alt text

Scan it to the scada platform and cross your fingers, it will blink green if it works!

Stage 2 - Scada Hacking (Billboard)

alt text

This challenge I think had the most fun cuz it’s finally related to what I love which is web exploitation!

On the website, we can actually see a couple of billboards that we can control. Our main goal is actually to obtain the key to use it to forge a signature before transmitting emergency messages to electronic billboards.

alt text

We found a file upload functionality here, and retrieve its path by pressing a button or something I forgot what it was.

alt text

So we figured out how to upload a webshell by sending a file with the byte signature of a webp file, but the content after the signature is actually a php code xd

Request
alt text

Response
alt text

From here we enumerated the source code of the web application and found the value of the secret key obtained from EMERGENCY_SECRET_KEY which can be retrieved from phpinfo() function.

alt text

alt text

Here from this part Sc signed the message using the signature and we pwned the billboard.