Dec 9, 2017

ph0wn CTF 2017 Write-up: Misc/helpxman - Stage 2 and 3

After successfully getting the flag of Stage 1, the challenge told us to continue looking for something interesthing from the app. After playing around with the app's UI, we found nothing special and decided to look into the internal of the app.
By saying internal we meant: let's reverse the source code of the application!

Get the application's APK file from the glasses.

  1. Connect the glasses with the computer as described in Stage 1
  2. List all current application installed in the smart glasses:
> adb shell pm list packages
...
package:ph0wn.reconjet
...
=> We can easily identify the app we are looking for is package:ph0wn.reconjet
  1. With the package name found, we can find the actual filename and the location of the APK file:
> adb shell pm path ph0wn.reconjet
package:/data/app/ph0wn.reconjet-1/base.apk
(Author's note: When writing this write-up, I have to run the app again on my phone, so the path appear above might be different from the one actually found on smartglasses.)
  1. Pull the APK to our host computer for further analysis:
> adb pull /data/app/ph0wn.reconjet-1/base.apk ./ph0wn.reconjet-1.apk

Analyse the APK file

  1. We use [apktook] to decompile the APK file.
On the host computer:
$ apktool d ./ph0wn.reconjet-1.apk 
I: Using Apktool 2.2.3-dirty on ph0wn.reconjet-1.apk
I: Loading resource table...
I: Decoding AndroidManifest.xml with resources...
I: Loading resource table from file: /root/.local/share/apktool/framework/1.apk
I: Regular manifest package...
I: Decoding file-resources...
I: Decoding values */* XMLs...
I: Baksmaling classes.dex...
I: Copying assets and libs...
I: Copying unknown files...
I: Copying original files... 
All the source/resource files are decoded and saved at ph0wn.reconjet-1 directory.
  1. After some quick investigation, we found one suspecious file (and with suspecious name): ph0wn.reconjet-1/smali/ph0wn/reconjet/HiddenActivity.smali.
Look inside the file, we found one suspecious part of source code (at the end of file): from line 114 to line 1012.
    :array_0
    .array-data 4
        0x43
        0x6f
        0x6e
        0x67
        0x72
....
....
....
        0xa
        0x47
        0x6f
        0x6f
        0x64
        0x20
        0x6c
        0x75
        0x63
        0x6b
        0x2e
=> This is definitely suspecious and we have to find a way to decode this set of hexa codes, it may store our flag(s).
  1. By some simple tricks to copy and paste, we put all the hexa codes next to each other for better view, and save them to a file called hexacodes:
$ cat hexacodes
0x430x6f0x6e0x670x720x610x740x750x6c0x610x740x690x6f0x6e0x730x2c0x200x740x680x690x730x200x690x730x200x730x740x610x670x650x200x320x200x210xa0x540x6f0x200x660x6c0x610x670x200x740x680x690x730x200x730x740x610x670x650x2c0x200x660x6c0x610x670x200x690x730x3a0x200x500x680x300x770x6e0x7b0x4b0x4b0x4b0x500x690x630x6f0x490x730x450x760x650x720x790x770x680x650x720x650x7d0x200x770x680x650x720x650x200x790x6f0x750x200x6d0x750x730x740x200x720x650x700x6c0x610x630x650x200x4b0x4b0x4b0x200x770x690x740x680x200x740x680x650x200x6b0x650x790x200x790x6f0x750x200x660x6f0x750x6e0x640x200x640x750x720x690x6e0x670x200x730x740x610x670x650x200x310x2e0xa0x4b0x650x790x200x660x6f0x720x200x730x740x610x670x650x200x330x200x690x730x3a0x200x630x5f0x480x710x6f0x700x650x660x390x310xa0xa0x530x740x610x670x650x200x330x3a0xa0x530x650x610x720x630x680x200x690x6e0x200x740x680x650x200x720x6f0x6f0x6d0x2c0x200x640x690x720x650x630x740x690x6f0x6e0x200x4e0x570x2c0x200x660x6f0x720x200x610x200x680x690x640x640x650x6e0x200x740x720x650x610x730x750x720x650x200x3a0x290x200x420x650x200x710x750x690x650x740x200x730x6f0x200x740x680x610x740x200x6f0x740x680x650x720x200x740x650x610x6d0x730x200x640x6f0x200x6e0x6f0x740x200x750x6e0x640x650x720x730x740x610x6e0x640x200x770x680x610x740x200x790x6f0x750x200x610x720x650x200x640x6f0x690x6e0x670x2e0xa0x540x6f0x200x660x6c0x610x670x200x740x680x690x730x200x730x740x610x670x650x2c0x200x660x6c0x610x670x200x660x6f0x720x6d0x610x740x200x690x730x3a0x200x500x680x300x770x6e0x7b0x4b0x4b0x4b0x4b0x4b0x4b0x4b0x4b0x4b0x4b0x410x410x410x420x420x420x430x430x430x440x440x440x450x450x450x460x460x460x470x470x470x7d0x2e0xa0x570x680x650x720x650x200x4b0x4b0x4b0x4b0x4b0x4b0x4b0x4b0x4b0x4b0x200x690x730x200x740x680x650x200x6b0x650x790x200x790x6f0x750x200x660x6f0x750x6e0x640x200x640x750x720x690x6e0x670x200x730x740x610x670x650x200x310x2e0xa0x2d0x200x410x410x410x200x690x730x200x740x680x650x200x630x6f0x6f0x720x640x690x6e0x610x740x650x730x200x6f0x660x200x740x680x650x200x660x690x720x730x740x200x6c0x650x740x740x740x650x720x200x6f0x660x200x770x6f0x720x640x200x460x4f0x520x540x490x4e0x450x540x200x690x730x200x740x680x650x200x740x720x650x610x730x750x720x650x2e0x200x460x690x720x730x740x200x6c0x650x740x740x650x720x200x690x730x200x630x6f0x6c0x750x6d0x6e0x200x280x410x2c0x200x420x2c0x200x430x2e0x2e0x2e0x290x2e0x200x530x650x630x6f0x6e0x640x200x6c0x650x740x740x650x720x200x690x730x200x720x6f0x770x200x280x310x2c0x320x2c0x330x2e0x2e0x2e0x290x2e0x200x540x680x690x720x640x200x6c0x650x740x740x650x720x200x690x730x200x770x6f0x720x640x200x640x690x720x650x630x740x690x6f0x6e0x3a0x200x480x200x660x6f0x720x200x680x6f0x720x690x7a0x6f0x6e0x740x610x6c0x2c0x200x560x200x660x6f0x720x200x760x650x720x740x690x630x610x6c0x2e0x200x530x6f0x2c0x200x690x660x200x460x4f0x520x540x490x4e0x450x540x200x730x740x610x720x740x730x200x610x740x200x720x6f0x770x200x410x2c0x200x630x6f0x6c0x750x6d0x6e0x200x330x2c0x200x680x6f0x720x690x7a0x6f0x6e0x740x610x6c0x6c0x790x2c0x200x770x650x200x770x690x6c0x6c0x200x680x610x760x650x200x410x330x480x2e0xa0x2d0x200x420x420x420x200x690x730x200x740x680x650x200x630x6f0x6f0x720x640x690x6e0x610x740x650x730x200x660x6f0x720x200x540x450x4c0x450x430x4f0x4d0x2c0xa0x2d0x200x430x430x430x200x660x6f0x720x200x500x410x520x490x530x540x450x430x480x2c0xa0x2d0x200x440x440x440x200x660x6f0x720x200x500x4c0x410x540x450x460x4f0x520x4d0x450x2c0xa0x2d0x200x450x450x450x200x660x6f0x720x200x430x4f0x4e0x430x450x500x540x490x4f0x4e0x2c0xa0x2d0x200x460x460x460x200x660x6f0x720x200x450x550x520x450x430x4f0x4d0xa0x2d0x200x610x6e0x640x200x470x470x470x200x660x6f0x720x200x470x520x450x480x410x430x4b0x2e0xa0x470x6f0x6f0x640x200x6c0x750x630x6b0x2e
(Trick: merge all the lines and remove spaces in VIM
:%s/\n        //g
)
  1. One more thing, these hexa codes look pretty much a set of ASCII codes of a very long string, let's try to print them out by a simple python print function.
In []: print((open('hexacodes').read().replace('0x','')).decode('hex'))
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-36-ba53ed228ee2> in <module>()
----> 1 print((open('hexacodes').read().replace('0x','')).decode('hex'))

/usr/lib/python2.7/encodings/hex_codec.pyc in hex_decode(input, errors)
     40     """
     41     assert errors == 'strict'
---> 42     output = binascii.a2b_hex(input)
     43     return (output, len(input))
     44 

TypeError: Non-hexadecimal digit found
Oops! It should work, but why doesn't it?!
  • We tried to read only 30 first characters:
In []: print((open('hexacodes').read().replace('0x',''))[:30].decode('hex'))
Congratulations
=> It works with the first 30 characters. (And the word Congratulations makes us believe that we are on the right way). There must be some thing wroing in the middle of the string makes our process doesn't work.
  • Look at closely to the string, we found the problem: it is the code 0xa that made our print command failed. Isn't it supposed to be a newline character (0x0a)? Let's fix it and try again.
  • Secondly, we noticed that the final '\n' in our hexacodes also makes a problem, so that let's remove it as well.
  • The final command is as follows:
In [57]: print((open('hexacodes').read().replace('0xa','0x0a').replace('0x',''))[:-1].decode('he
    ...: x'))
Congratulations, this is stage 2 !
To flag this stage, flag is: Ph0wn{KKKPicoIsEverywhere} where you must replace KKK with the key you found during stage 1.
Key for stage 3 is: c_Hqopef91

Stage 3:
Search in the room, direction NW, for a hidden treasure :) Be quiet so that other teams do not understand what you are doing.
To flag this stage, flag format is: Ph0wn{KKKKKKKKKKAAABBBCCCDDDEEEFFFGGG}.
Where KKKKKKKKKK is the key you found during stage 1.
- AAA is the coordinates of the first lettter of word FORTINET is the treasure. First letter is column (A, B, C...). Second letter is row (1,2,3...). Third letter is word direction: H for horizontal, V for vertical. So, if FORTINET starts at row A, column 3, horizontally, we will have A3H.
- BBB is the coordinates for TELECOM,
- CCC for PARISTECH,
- DDD for PLATEFORME,
- EEE for CONCEPTION,
- FFF for EURECOM
- and GGG for GREHACK.
Good luck.
BINGO!! All the information of flags for Stage 2 and Stage 3 are revealed!
  1. The rest are simple (we hoped :) ), it actually require some physical exercises and playing with some word game (as described above), no computer skills needed. (But personally I think this kind of thing made this challenge a lot of fun and unlike any other CTF challenges before. Plus 1 for ph0wn organizers!)
  2. So,to conclude, the flags are as follows:
  • Stage 2: Ph0wn{X@MPicoIsEverywhere}
  • Stage 3: Ph0wn{c_Hqopef91M17HI10VO19VK1VL14VA8VC12V
BONUS Here is the hidden treasure we found (with some beautiful original handwriting):

ph0wn CTF 2017 Write-up: Misc/helpxman - Stage 1

When wearing the smart glasses, we can see there is an application called Ph0wn Glasses. Go to that application (by using controller on the glasses, we can see one QR code appears on the screen.
The QR code is much likely have information about the flag. Let's try to read it!
  1. Connect the smart glasses with the (ADB already installed) computer.
  2. From the command prompt of the computer (Ctrl+R --> Type cmd --> Press Enter). Type:
> adb devices
List of devices attached
* daemon not running. starting it now at tcp:5037 *
* daemon started successfully *
IDOFTHEDEVICE      device
=> Make sure the ID of the device appear as above. Otherwise, we have to:
  • Turn on Developer options in the Settings of the glasses. (The glasses is running Android, so it's the same as any other Android devices).
  • Restart ADB service on host computer: > adb kill-server
  • Try to connect with the device (glasses) again: > adb devices
  1. On the smart glasses, browse to the application, so that the QR code image appears on the screen. The idea is we try to take a screenshot of the glasses, pull it to our host computer and read it by QR code reader.
  2. Take a screen shot by adb command:
> adb shell screencap -p /sdcard/screencap.png
The screenshot will be saved in the glasses' SDcard.
  1. Pull the file to host computer (current working folder):
> adb pull /sdcard/screencap.png .
  1. View the image:
> screencap.png
We will see it on our computer's screen:
  1. Now, let's read the QR code. No need to make things complecated, let's choose a very simple way: show the image on computer's creen, read it with the Barcode scanner app on our normal phone.
It's quickly be recognized as follows:
So, the flag is: Ph0wn{ScottWishesHeHadOurSmartGlasses}
And, we note the key X@M for the next stage.

ph0wn CTF 2017 Write-up: Misc/helpxman - Stage 2 and 3

After successfully getting the flag of  Stage 1 , the challenge told us to continue looking for something interesthing from the app. After ...