Over the last few weeks and in part thanks to my new fascination with Android app security, I have recently found myself heavily invested in cyber security content online. Youtuber’s such as John Hammond and LiveOverflow provide hundreds of hours of free content, teaching the average person (as well as developers such as myself) the core concepts around cyber security, ethical hacking and reverse engineering.
Part of this content introduced me to cyber security’s capture-the-flag (‘CTF’) events, in which teams or individuals compete on challenges in numerous cyber security disciplines in order to gain points, win prizes and ultimately hold the bragging rights over their peers. The challenges usually range in difficulty and in style, from reverse engineering code to completely taking over a machine and gaining root (admin) access.
However, for the complete novice, picoCTF is a free for all annual event aimed at middle school + high school pupils to introduce them into cyber security through a number of hand crafted challenges. Once the event is over these challenges are released and made accessible for non-event attendees to try them for themselves. Despite the intended audience, the difficulty level of some of the harder challenges makes picoCTF a popular event for many seasoned experts as well as beginners. The aim of each challenge is to find a hidden ‘flag’ in the format “picoCTF{xxxxxxxxxxx}” using cyber security tools, your own knowledge and very often some expert google-fu.
What interested me immediately with picoCTF was 5 of their challenges all revolving around Android applications. These challenges, named droid0
to droid4
respectively, provided me with an exciting chance to test my Android knowledge and further my understanding of the platform I have worked with for close to 10 years. I thought being an experienced developer would mean they’d all be easy, but how wrong I was!
Below are my solutions to these problems.
⚠️ Spoilers Ahead
I highly recommend you try all the droid challenges before continuing this post to avoid spoilers. They range in difficulty, but with good research technique should be easy enough to solve without too much trouble.
However, should you wish to see the solutions, please continue at your discretion!
Challenge 1: droids0
The first challenge provided the following description
Where do droid logs go. Check out this file.
The very first step was to download the provided file to check what it was, so using wget
I downloaded it to my working directory.
It’s an APK file! Great, looks like we are checking out somebody’s compiled app.
Assuming it’s a debuggable build, it is possible to install this APK on a device or emulator via the Android Debug Bridge ‘adb’ tool.
Running the app showed an extremely basic app consisting of a title, input text field, button and another text view.
Playing with the app, inputting text and clicking the button caused the “I’m a flag text” to change to a “Not Today…” message.
With the app’s title text and the problem’s description, I immediately knew that I needed to check the application’s logs.
To do this, I made use of pidcat and grep
‘d the output to check for flags.
Sure enough, there’s the flag: picoCTF{a.moose.once.bit.my.sister}
Challenge 2: droids1
The second challenge starts with the following description
Find the pass, get the flag. Check out this file.
Following the previous challenge, I first downloaded the APK file and installed it to my emulator.
The app that installs is a mirror of the previous challenges app, but with the title stating ‘brute force not required’. Entering any text and hitting the button provides a helpful ‘NOPE’. It looks like a password is first required to gain access to the flag.
Based on the title hint, it suggests that reverse-engineering is the way to go. To reverse engineer the APK we can make use of apktool to decompile the app, check the resources and even inspect the decompiled Android byte-code written in a smali format.
To decompile the app using apktool
is ultra straightforward. The tool creates a directory one
with directories for all the decompiled files.
Whilst not being a smali expert, opening the smali file I located a getFlag
method that seemed like a great point to start. Inspecting the method, it was possible to work out what was going on through adding my own annotations.
The annotated file is below:
The 0x7f0b002f
in the code referenced a string resource. So to find out which one, I ran a simple grep
.
Having found out the relevant string resource is password
, then we can search the XML files for the relevant password using find
and grep
.
Bingo. Entering “opossum” into the app reveals the flag picoCTF{pining.for.the.fjords}
Challenge 3: droids2
Find the pass, get the flag. Check out this file.
With the same hint as the last challenge, it was time to follow the same steps as previous.
Installing the app resulted in the title of the app changing to ‘smali sounds like an Ikea bookcase’. In fairness, it totally does. Again, it looked like we’d need to find the password to unlock the flag.
Based on this title, it was a fair assumption we’d be diving head first into the decompiled smali code again.
This time the smali code was far more complex than the previous challenge. I decided that to investigate further, I would make use of the popular jadx decompiler to take the smali and attempt to convert it into something more readable, i.e. Java code.
After downloading jadx
, I launched the GUI using the jadx-gui
command and opened FlagstaffHill.smali
. Thankfully, jadx
did an excellent job of reversing the smali back into Java.
To obfuscate the password, it seems the app was doing some array and string manipulation. Based on a quick look at the code, it looked like the array of words would be placed in a specific order, separated by periods.
However, to avoid the potentially time consuming task of reverse engineering the code and then validating it, I created a new Java file and copied the decompiled code over. From there, I modified the code so it would print out the flag to ensure there was no chance for error and I would get the password immediately.
Once modified, compiling and running the code should provide the expected password.
Boom. There’s the password. With that in hand, I entered it into the app and successfully unlocked the flag picoCTF{what.is.your.favourite.colour}
Challenge 4: droids3
Find the pass, get the flag. Check out this file.
Knowing the drill at this point, I followed the same steps as the previous challenges.
The hint this time was a little more cryptic
Make this app your own
Ok? Make it my own? How can I do that.
To see what was going on this time, I again made use of jadx-gui
and opened the smali file.
So it looks like the class only has 4 methods, the cilantro
native method to get the flag from a compiled library, the getFlag
method that calls the nope
method and a seemingly unused yep
method that gets the flag via cilantro
.
Huh. Ok, I think we some how need to modify the app’s code to make getFlag
call yep
instead of nope
.
Thankfully, I had just come across the excellent ‘Hacktricks’ website that documents numerous reverse engineering techniques. The section on Android pointed out that apktool
could be used to recompile an app with modified smali.
So, I checked the smali for the getFlag
method
Could it be as simple as changing nope(Ljava/lang/String;)Ljava/lang/String;
to use yep
?
I modified the file and followed the steps to recompile the build with my modified code
Nervously I try clicking the button in the app and to my surprise it reveals the flag picoCTF{tis.but.a.scratch}
Final Challenge 5: droids4
Reverse the pass, patch the file, get the flag. Check out this file.
Having done this a few times by this point, I follow the steps from the previous challenges. It seems like that this time it will be a combination of figuring out the password and then modifying smali before recompiling.
Opening the the smali file in jadx
shows the following Java code that again makes use of obfuscation techniques to hide the password.
Following the previous challenge. I again made a modified version of the code to print out the password
Compiling and running this gave me the password as expected
However, having seen the getFlag
method was hard-coded to always return "call it"
, I also knew that we’d need to modify the smali code and recompile as per the previous challenge.
I located the smali code that returned the hardcoded string and observed the following
I needed to modify this code to instead invoke the cardamom
method, and return it.
Thankfully, the previous challenge actually provided the smali code to do this, so it was a simple case of copying it over and replacing the smali for the return method with the following
With these changes made, it was time to try it out!
Entering the previously discovered password and clicking the button reveals the final flag picoCTF{not.particularly.silly}
We’ve done it! ✨
Wrapping Up
picoCTF’s droid challenges proved to be a fun learning experience with the difficulty starting fairly easy but ramping up and requiring some background research.
In all these took me a couple of evenings to complete.
I would highly recommend giving this a go yourself as well as looking into the other challenges picoCTF has to offer!
Thanks 🌟
Thanks as always for reading! I hope you found this post interesting, please feel free to tweet me with any feedback at @Sp4ghettiCode and don’t forget to clap, like, tweet, share, star etc