I was working on Friday evening when my friend sent me a Twitter link to the Winja CTF quiz. I’m quite new to the CTF stuff but when I see the mobile challenge I go for it because it always looks interesting to me.
Although those methods may look primitive and I believe there are many experienced people who would laugh at these techniques still they work and it’s just a hobby, so bear with my writeup 😃
Back to the main story. This quiz asks us to find the hardcoded string in the application. Usually, if it’s hardcoded and especially if it’s native Android challenge is easy, I followed the download link to Github where I found APKs.
Anyone who worked with the Android apps will understand that if we see several APKs(if not bundled together) for different types of CPU-s it means we have to deal with native (c/c++) code. And that makes sense, otherwise, the task would be easy. (At this point I still didn’t know any details, I was just speculating, native code guess was right but there is more).
I didn’t run the app, directly opened the terminal and decompiled via
apktool. And guess what? It’s the Flutter app 🤘The final merged
AndroidManifest.xml clearly states that the default application name
libs/ folder contains
I don’t have much experience developing and REing Flutter apps so I guess this would give me a little bit of push in that direction. Let’s dive.
Of course, we need to start with libapp.so file because libflutter is Flutter framework itself compiled for specific CPU type. At this point, my thought was that
JADX was useless because it would be highly unlikely if that app had any bridge to native Android for platform-specific code. (Ok, if I couldn’t find anything in libapp then I was going to fire up the application in the emulator and look it up in JADX).
To someone who doesn’t know any
.so file is a compiled library file and it’s almost the same as
.dll on windows, therefore we can split our investigation into several ways.
- we can run
stringscommand on it and analyze the complete mess of strings
- Fire up Ghidra or IDA.
Let’s discuss both. Disclaimer: I’m totally n00b in disassembling native code I just like the process of RE-ing.
- Run the app in the emulator. We see the only input and it requires a correct password.
- Then I looked into
AndoridManifestand discovered activity which is basically a web view but which is not exported 😢 From this guess I expect to find anything related to URLs as well.
- Save the output and scavenge anything related to
passwordbecause the validator in the app displayed “Incorrect Password Detected”. Start from this.
After searching the string we end up seeing stuff like this. They are grouped together because they appear in the same code snippet and compiled next to each other and voila we have a flag 🎉
At this point, I was not sure if it was the correct one and I had to check. Looks like the password is correct but it confuses why the webpage not working.
https://winja.xyz-company.site/ “Am I missing something?” <- that was my guess. To open Burp-suite and monitor headers(Maybe there is something in request headers?) had no use because the address was unresolved. And back to the original tweet, it just required a secret which as it looks like I found.
Another way but it looks similar. Run the Ghidra.
And again I started to search strings like a password but I know it should not be at the beginning of the stack because it’s usually flooded by Flutter stuff. As in the previous method and obviously in Ghidra it looks clearly in the program stack those strings are close to each other and I followed execution flow. Found the address
005298e0 “Incorrect Password Detected: “ and after scrolling down a bit we could clearly see:
And that’s how I won this quiz:
Overall it didn’t take more than 10 minutes and was fun. I gained a little bit more experience with the Ghidra search and it was interesting. Mobile challenges are quite rare in CTFs and kudos for that 🤘