Ph0wn CTF 2019 - Smart Devices CTF

Another week another CTF, this time it was the Ph0wn at Sophia Antipolis (France). I teamed up with members from @Maki, @iansus, @MansourCyril and @0hax. We reached the second place of this IoT/Hardware CTF.

Banner

Writeups’ challenges

Rookie - Sunny day

The weather is always nice on the French Riveria. Yet, it is great to monitor this (sunny) weather with a weather station. There is a weather station in Biot, and there is an Android app for it. But somebody told me that there could be a hidden treasure in its main layout

First we ran the new MobSF application and drag’n dropped the APK file into it : docker run -it --name mobsf -p 8000:8000 opensecurity/mobile-security-framework-mobsf:latest. After inspecting the source code we stumbled upon the following Java/Android at http://localhost:8000/ViewSource/?file=tux/android/biotmeteo/MainActivity.java&md5=1b6d26562ca11c2d0c13fae063c93cd9&type=apk indicating the flag was around.

this.j = (Button) findViewById(R.id.badWeatherBtn);
this.j.setText("Flag is not far :)");

We extracted the biotmeteo.apk as a zip file and started looking for the flag pattern ph0wn{ recursively. We will find inside biotmeteo\res\layout\main.xml.

$ grep ph0 -r . --text
curvesButtonInfoTemp((tux.android.biotmeteo.AutoResizeTextViewRainWind
ph0wn{IsTheWeatherNiceT0night?}
BaHutLdityULIOLpL

Flag : ph0wn{IsTheWeatherNiceT0night?}

Hardware - Ant-Maker

To receive the signal, you have to fabricate a RHCP antenna at 868MHz. Use the 3D_ant file as a model to mount the antenna. Collect your PCBs and use some tools and a soldering iron. Once your are ready, register on list to test if your prototype can receive the signal. 3 teams will make the test each 30mn. The Master of the Chamber, Fabien, will guide you to the anechoic room.

We were given two PCB and an antenna, in order to get the flag we had to solder them the right way. To help us the organizers provided each team with this file : Ph0wn-3D_ant.step.

It’s a step file containing a 3D vizualization of the final PCB. From there we knew what to solder and where, we loaded it into https://3d-viewers.com/step-viewer.html.

Ph0wn3Dant.png

The challenge wasn’t hard but takes a lot of time and thorough effort to create a “working” antenna.

Flag : ph{LoRa_From_Space}

Misc - Compromised Sensor

I swear I saw a masked attacker come with a big syringe and a huge needle infect those glucose sensors for diabetics. What did he inject in those NFC sensors?!

  • Come and get a sensor at the organizer desk (see the attached image to recognize the device you need to get)
  • Nota. Due to a server crash, if you see an IP address, modify with 35.241.137.50 (no DoS)

Since the NFC is used by the sensor, let’s check it with our proxmark3. With these data in mind we can find more informations about the sensor, it seems to be a FreeStyle Libre sensors.

[usb] pm3 --> hf search
          
 UID  : E0 07 A0 00 02 A6 99 C0          
 TYPE : Texas Instrument France          
      
[+] Valid ISO15693 tag  found

On a StackOverflow post we find this goldmine :

Instead, you will have to find out what commands the blood sugar meter actually supports (probably it will support the ISO/IEC 15693 READ SINGLE BLOCK command

Now we know there is dump equivalent for NFC-V (ISO 15693), let’s try it with the proxmark.

[usb] pm3 --> hf 15 dump f mydump           
Reading memory from tag UID E0 07 A0 00 02 A6 99 C0           
...................................................
 45/0x2D | C2 43 08 08  | 0 | .C..          
 46/0x2E | 08 08 D2 42  | 0 | ...B          
 47/0x2F | D2 42 A3 F9  | 0 | .B..          
 48/0x30 | 4D 65 64 69  | 0 | Medi          
 49/0x31 | 4C 61 62 3A  | 0 | Lab:          
 50/0x32 | 70 3A 2F 2F  | 0 | p://                                                             
 51/0x33 | 31 30 2E 31  | 0 | 10.1                                                             
 52/0x34 | 3A 32 31 33  | 0 | :213          
 53/0x35 | 64 3A 70 69  | 0 | d:pi          
 54/0x36 | 77 64 3A 31  | 0 | wd:1          
 55/0x37 | 34 30 31 20  | 0 | 401           
 56/0x38 | E2 B3 C3 1C  | 0 | ....     

Some data are cropped, we tried several applications on our Android device. NFC TagInfo by NXP was the right one, it allows us to scan the entire memory.

Ph0wnNXP.jpg

We get the following credential for the IP 10.210.17.66

id: pico
pwd: 19990401

Ph0wnMedical.png

From there we can download a PDF file containing a mention to Examen réalisé par marquage de type “Ange Albertini” CCC’2014 ou PoC||GTFO. Ange Albertini gave a talk Funky File Formats on NoLimitSecu, we guess there is another file hidden in the PDF, running binwalk in extract mode will gave us thezip/FLAG containing the flag.

$ binwalk lab-results.pdf  -e

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             PDF document, version: "1.4"
71            0x47            Zlib compressed data, default compression
1852          0x73C           JPEG image data, JFIF standard 1.01
7162          0x1BFA          Zlib compressed data, default compression
7419          0x1CFB          Zlib compressed data, default compression
13863         0x3627          Zlib compressed data, default compression
14457         0x3879          Zlib compressed data, default compression
29155         0x71E3          Zlib compressed data, default compression
30196         0x75F4          Zlib compressed data, default compression
39508         0x9A54          Zlib compressed data, default compression
41694         0xA2DE          Zip archive data, at least v2.0 to extract, compressed size: 437, uncompressed size: 1244, name: thezip/blah
42200         0xA4D8          Zip archive data, at least v2.0 to extract, compressed size: 584, uncompressed size: 1487, name: thezip/FLAG

$ cat _lab-results.pdf.extracted/thezip/FLAG| grep -i Ph0
ph0wn{BeS@feAndTakeCare}

Flag : ph0wn{BeS@feAndTakeCare}

Misc - Domotics

Pico le Croco would like to control the power consumption of equipment in his wine cellar and in his pool. For that, he has bought a nice power meter, EcoCompteur from Legrand.

Configuration:

  • In Setup / Hardware, a Ph0wn EcoCompteur hardware is already partly configured for you (along with weather sensors), but you need to fix the IP address to: http://10.210.17.34:20000.

  • Unfortunately, you may encounter a bug where you are unable to modify the existing hardware. In that case, delete it and create a new one. Also, the port 20000 must be specified in both the remote address and the port (other bug).

  • Then, among Devices, you might like to tag “Conso 1” and “Conso 2”: Conso 1 is the wine cellar, Conso 2 is the pool.

A new docker instance is deployed for each team when they click on the challenge, this instance is binded to a random port of the server 10.210.17.34. Since there is no authentication to access the EcoCompteur we guessed we could access other contestants panel.

...
10040/tcp open  unknown        syn-ack
10050/tcp open  zabbix-agent   syn-ack
10060/tcp open  unknown        syn-ack
10070/tcp open  unknown        syn-ack
10081/tcp open  famdc          syn-ack
10100/tcp open  itap-ddtp      syn-ack
10130/tcp open  unknown        syn-ack
10151/tcp open  unknown        syn-ack
10160/tcp open  qb-db-server   syn-ack
10170/tcp open  unknown        syn-ack
10181/tcp open  unknown        syn-ack
10191/tcp open  unknown        syn-ack
10201/tcp open  rsms           syn-ack
10220/tcp open  unknown        syn-ack
10260/tcp open  axis-wimp-port syn-ack
10281/tcp open  unknown        syn-ack
10310/tcp open  unknown        syn-ack
10340/tcp open  unknown        syn-ack
10360/tcp open  unknown        syn-ack
...

We downloaded the usage for both Conso 1 and Conso 2.

╭─user@crashmanjaro ~/CTF/Ph0wn/Domotics 
╰─$ cat usage-last-24-hoursA.csv | cut -d "," -f3 | tr  "\n" ","
"Power Usage",,103,47,54,99,32,32,97,48,48,32,46,103,49,110,99,48,110,46,49,50,49,47,49,58,102,119,47,32,48,48,50,104,58,102,47,110,99,116,48,102,48,99,99,99,99,99,99,99,99,99,99,116,48,32,

╭─user@crashmanjaro ~/CTF/Ph0wn/Domotics 
╰─$ cat usage-last-24-hours.csv | cut -d "," -f3 | tr  "\n" "," 
"Power Usage",,119,110,32,102,108,97,103,32,97,116,32,104,116,116,112,58,47,47,49,48,46,50,49,48,46,49,55,46,54,54,58,50,48,48,48,48,47,110,49,99,101,102,102,102,102,102,102,102,102,102,102,112,104,48,% 

We can clearly identify some ASCII char, let’s display them using Javascript.

> console.log(String.fromCharCode(119,110,32,102,108,97,103,32,97,116,32,104,116,116,112,58,47,47,49,48,46,50,49,48,46,49,55,46,54,54,58,50,48,48,48,48,47,110,49,99,101,102,102,102,102,102,102,102,102,102,102,112,104,48));
> "wn flag at http://10.210.17.66:20000/n1ceffffffffffph0"

The URL was a little buggy, we grabbed the flag at http://10.210.17.34:20000/n1ceflag

Flag: ph0wn{h0w_about_using_a_candle_instead}

Crypto - Shamir Quest

Ph0wn is so coooool. We’ve implemented a Dragon Ball game for your Android smartphone, so you can play and relax. Oh?! Looks like there’s a flag in there!

The Android application is running Cordova, basically all the code is in some Javascript file. Every Dragon ball of the game is mapped like this int(1-7) - long(…). Based on the challenge name we know we have a Shamir Shared Secret. We can recover it with the following python script.

#!/usr/bin/python2
from secretsharing import points_to_secret_int

shares = [(7, 86280222218758143060577039723423036819702949921689517334729056400620503262863),      
(6, 64853486060730513615551322784573665580194031012367687584714706161521361565423),                
(5, 33814200739788654257795508969553514400370233867365839951719667470054751133890),                
(4, 31566639759828849253104354287777292258537243784043419234402145787553977170879),                
(3, 54008062481679211386368408327065859783198766778147014402616411673289639152699),                
(2, 84515091397950443810021067510975505753043639566495880186943378404018469002849),                
(1, 16977966888023650463948528650004025823243132426593812430821649423473014227191)]

print(hex(points_to_secret_int(shares))[2:-1].decode('hex'))

Flag : ph0wn{Sh4m1r_4nd_G0ku_P4rtyt1me}

Written on December 14, 2019