Smali Patching for calling Secret Function on droids4 Android App
In this writeup, I will walk you through the steps I took to solve the droids4 challenge from PicoCTF 2019. This challenge similar with droids3 because it still involve modification on smali code , and rebuild and sign the APK.
Tools that I used:
Unlike the previous challenge attempt where I did the decompile and signing manually, this time I tried to use a VSCode extension that looks really interesting and can speed up my exploration called APKLab.
Let’s get started
Still same UI, but the hint is “you got this” When the button is pressed it says “NOPE”
let’s see what is inside the APK using JADX
okay this time there is some String manipulation or some might call it cryptography puzzles, I guess this might take a while to decode manually like checking the ASCII Table, calculating and pointing the value something like this:
ace.setCharAt(0, (char) (ace.charAt(0) + 4)): ASCII of ‘a’ is 97. 97 + 4 = 101, which is ‘e’ so the first character in variable ace is ‘e’
This is Interesting but… I think instead of spending time to manually decode the value for each variable, why not try to copy part of the code and run the code on java online compiler first? This time I’m using
https://www.programiz.com/java-programming/online-compiler/
See, I got the password almost instantly 🤣 by copying the puzzle logic and printing the password it shows that the password is
So back to the emulator, I tried to submit the password only to realize that even though I got the password right, it still returned “call it” not the flag
return input.equals(password) ? "call it" : "NOPE";
this part, so I guess I need to change the smali code again and rebuild the APK. but I need to re-check the code again to find what to change.
This time I found out that the native method “cardamon” is initialized but not called, so it starting to make sense with the hint “call it”.
So to change the smali code, Let’s try the new tools that I found on VSCode which is APKLab.
after finished installing the extension, I ran the APKLab command to load the APK
I chose to have 2 params which are only-main-classes and no-res because I don’t need the resources and only want to focus on smali code part.
After it’s successfully loaded the APK new VSCode window will be shown and it’s already loaded with a new directory of decompiled APK
Moving on to FlagStaffHill.smali file I found this big line of code. Focusing only on getFlag() method, I need to somehow change the return true condition from “call ” to cardamom().
At the end of the smali getFlag() method here is the checking condition and return value
if-eqz v5, :cond_0
const-string v5, "call it"
return-object v5
.line 37
:cond_0
const-string v5, "NOPE"
return-object v5
and from my understanding, this line of code means something like this:
- “v5 ”: refers to the password variable
- “const-string”: refers to Hardcoded String
- “return-object”: is for return
- “cond_0”: is for the if condition true and false
Because I don’t really understand smali code and need to somehow change the return to a static native method that already initialized. I try to decompile the previous challenge APK because they call the native method correctly and no need to change the smali to get the flag. In this case, I choose to decompile the droids1 APK to check the smali code but only with JADX to have a quick look.
on droids1 it uses fenugreek() native method and calls it on true condition, this is similar to what I want to change on droids4 the only difference is the method name. so I Copy this part from droids1 getFlag() smali
invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->fenugreek(Ljava/lang/String;)Ljava/lang/String;
move-result-object v1
and paste it to the droids4 getFlag() smali at the end of the method. so the new Code on that part looks like this
and now I just need to make some changes to the code like this:
//from
invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->fenugreek(Ljava/lang/String;)Ljava/lang/String;
//changed into
invoke-static {p0}, Lcom/hellocmu/picoctf/FlagstaffHill;->cardamom(Ljava/lang/String;)Ljava/lang/String;
change fenugreek into cardamon because the native method on droids4 is cardamon, p0 is not changed because it refers to params “input” which is still the same from droids1 and droids4
//from
move-result-object v1
//changed into
move-result-object v5
v1 to v5 because on that current block of code, it’s on register v5
//from
const-string v5, "call it"
//changed into
I removed the const-string because It’s not needed anymore
after finished changing the code, I tried to generate the APK using the APKLab by right-clicking the apktool.yml and rebuilding the APK
and use the default params.
And it’s success is like magic, not only does it generate the modified APK but also automatically signs it which saves me a lot of time. In my case the modified APK is stored in \dist\ folder.
so the moment of truth, let’s try the modified APK on the emulator
It’s successfully installed and Here comes the last flag
picoCTF{not.particularly.silly}
Reference:
OWASP Mobile - M7: Insufficient Binary Protection