Android Hacking - Part 6

Static Analysis - Hands-on, finally.....

Hands on basic static analysis


Target App: InjuredAndroid

Environment: Physical device / Android Studio Virtual Device

Grabbing the Android apk

  1. Start the Android virtual device.

  2. Grab the apk from releases page OR you can download it from the Play Store directly.

  3. Once downloaded, simply drag and drop onto your Virtual device to install the apk.

  4. 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


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)

Something I noticed: The dark editor themes on jadx-gui make the highlighting less visible so I will switch back to the light theme. eye burn time

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


$ 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 android.content.Intent;
import android.os.Bundle;

public class MainActivity extends AppCompatActivity {

    protected void onCreate(Bundle savedInstanceState) {

        Intent start = new Intent();
        start.setClassName("b3nac.injuredandroid", "b3nac.injuredandroid.b25lActivity");


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(;
        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);

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.


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!