Android Hacking - Part 6
Hands on basic static analysis
Preparation
Target App: InjuredAndroid
Environment: Physical device / Android Studio Virtual Device
Grabbing the Android apk
Start the Android virtual device.
Grab the apk from https://github.com/B3nac/InjuredAndroid releases page OR you can download it from the Play Store directly.
Once downloaded, simply drag and drop onto your Virtual device to install the apk.
Process for applications that are only available on the Play store, use the instructions on our previous post here - Preparation
What is InjuredAndroid?
It is an intentionally vulnerable Android application created to learn mobile app vulnerabilities and exploitation.
As per the creator B3nac
, "A vulnerable Android application with ctf examples based on bug bounty findings, exploitation concepts, and pure creativity."
Let's begin hacking
Once you have the apk installed on your Android device (virtual or physical) and opened it up you should see the following page.
Scrolling down we can see there are a total of 18 flags. rolls up sleeves
Initial Recon
Let's decompile our application using apktool
or jadx-gui
if you'd like to keep things organized (my preferred method). Here we are just discussing the usual files to look at when starting off assessing a mobile app.
Let's navigate to 'Resources' -> AndroidManifest.xml
and give it a read. If you're lost please refer to an older post talking about AndroidManifest.xml
As part of the initial recon, I like to visit the strings.xml
file and search for hardcoded secrets like API keys, passwords, codes, DB URLs and more. They could be exposed in the activity source code as well.
Navigate to Resources -> 'resources.arsc' -> values -> strings.xml
Typically, I'd scroll through this to gather hardcoded data if any. We can use the Find feature and use terms like
password
API_Key
API
secret
AWS_Secret
http
https
SQL
ClientSecret
It is always good practice to go through the values folder files for any additional information we can gather. The best part about using a tool like jadx-gui is that we can do a find across the entire app to look for hardcoded credentials, URLs and more.
Note: It is still a good idea to peruse through the individual xml files and then do a general app wide search to increase scope.
You get the idea, right? Let's move on to the flags.
Flags 1 - 4
Flag 1 - Login
Let's take a look at the source code in jadx-gui
for this activity.
We can see from the code and the UI that clicking the red caution button on the app shows us a snackbar message saying "The flag is right under your nose" and another click on the same element shows "The flag is also under the GUI". It seems like they are hinting to the fact that the input might be getting compared to a static value in the source code. Scrolling further down we find the SubmitFlag function and see the value our input is being compared to.
Congratulations, we've solved the first flag!
Flag 2 - Exported Activity
Head on over to the main menu and click on the Flag two.
If you remember our AndroidManifest.xml post, this should be easy to locate. Let's head on there and see what we can find. Clicking the hint button says that exported and activity are the keywords as well as the fact that they can be accessed via adb
or drozer
(we haven't discussed this yet)
On the AndroidManifest.xml we can search for exported="true"
and we see a few pop up.
Now as<activity android:name="b3nac.injuredandroid.b25lActivity" android:exported="true"/>
is an exported activity we can use adb shell to invoke this activity. Let's go ahead and do that
$ adb shell
$ am start b3nac.injuredandroid/ .b25lActivity
Alternatively,
$ adb shell am start -n b3nac.injuredandroid/.b25lActivity
This should launch the intent and you should see the following
There is also a way to create a PoC app which when launched would result in the same outcome and could be useful when we get into more complex exploits.
package b3nac.injuredandroid.poc;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Intent start = new Intent();
start.setClassName("b3nac.injuredandroid", "b3nac.injuredandroid.b25lActivity");
startActivity(next);
}
}
Congratulations, second flag completed!
Flag 3 - Resources
Let's go click on it and then check out the source code
Looks awfully similar to the first flag and the hints say "Check xml files" and "R stands for resources"
The code we are interested in is the following, we can see that it is requesting text with the getText function and comparing it to a specific string.
public final void submitFlag(View view) {
EditText editText = (EditText) findViewById(R.id.editText2);
d.s.d.g.d(editText, "editText2");
if (d.s.d.g.a(editText.getText().toString(), getString(R.string.cmVzb3VyY2VzX3lv))) {
Intent intent = new Intent(this, FlagOneSuccess.class);
new FlagsOverview().L(true);
new j().b(this, "flagThreeButtonColor", true);
startActivity(intent);
}
}
I've copied this value and let's do a search on this value to look up the corresponding resource and looks like we have the answer!
Congratulations! Flag three found.
Flag 4 - Login 2
This one shows the Hints as "Where is bob" and "Classes and imports". Note: You don't need the hints but they are helpful at this stage to guide us through.
Let's navigate to the source code and see what we can find.
Similar to the last challenge but with a twist, Let's try to understand what it means. Searching for the Looks like it will show the FlagOneSuccess.class once it has the right submission.
We see this g() class, this is just an obfuscated name, it could have been anything. Let's double click to explore
There we see the base64 value which when decoded would give us out flag. Let's paste that into a base64 decoder and submit the flag.
4_overdone_omelets
Congratulations, we have found the flag. Developers try to be sneaky by thinking about the whole security through obscurity route and as we can see it's not super helpful because we were able to access the class it was using to import the string.
See you in the next post!
Subscribe to my newsletter
Read articles from Sukrit Dua directly inside your inbox. Subscribe to the newsletter, and don't miss out.
Written by