injuredandroid

Abdulrhman
11 min readSep 4, 2024

--

This is my first time to test on Android applications and in this walkthrough I will discuss how I was able to solve most of the challenges and also to introduce my methodology.

What is injuredandroid?

A vulnerable Android application with CTF examples based on bug bounty findings, exploitation concepts, and pure creativity.

Basic Recon

In the beginning, I liked to install the app and use it as a usual user to identify its functions and features, but this one is a type of challenge that gave me an idea about what challenges and its activities I would face.

Static Analysis

There are many tools that can perform this task for us, but I prefer the manual approach.

Let’s decompile the apk using jadx-gui.

After decompiling the apk, I like to check two interesting files AndroidManifest.xml and strings.xml.

The Android Manifest is an XML file which contains important metadata about the Android app. This includes the package name, activity names, main activity (the entry point to the app), Android version support, hardware features support, permissions, and other configurations.

Strings file contains all the strings which can be used frequently in the application.

Starting with AndroidManifest.xml file, I search for exported components that may reveal sensitive information, bypass any restrictions or do any interesting action.

In strings.xml file, I search for API keys, hardcoded credentials and firebase information.

Google API keys
Firebase Database URL

Dynamic Analysis

In this phase, I focus on the components that took my attention in static analysis phase, I also focus on Root detection mechanisms and SSL pinning checks.

I also run adb logcat while analyzing all the components and its related vulnerabilities.

In static analysis phase, I got three interesting exported activities.

First Finding

First Finding

Let’s use adb to see what it is hiding.

adb shell am start-activity -n b3nac.injuredandroid/.b25lActivity
Result of the first finding

Second Finding

Second Finding

Using adb command again.

am start -n b3nac.injuredandroid/.QXV0aA

All what I got is empty page with login button.

Result of the second finding

Click on Login button, I just got Authentication succeededin a Toast message.

Third Finding

Third Finding

By doing further investigation, I found this activity uses intents.

Let’s enter this activity using adb command.

am start -n b3nac.injuredandroid/.TestBroadcastReciever -a com.b3nac.injuredandroid.intent.action.CUSTOM_INTENT --es "url" "Hi"
Result of the third finding

After I finished testing of the interesting activities, I decided to start testing the application’s functionality and features (Challenges).

XSSText

Before analyzing the challenge code, I like first to open it to have a clue about the challenge.

As I expected, I just found a user input. So let’s analyze the code.

Search for b3nac.injuredandroid.XSSTextActivity in AndroidManifest.xml file.

b3nac.injuredandroid.XSSTextActivity

This activity has a simple code that takes user input as Intent to com.b3nac.injuredandroid.DisplayPostXSS then it starts the DisplayPostXSS activity.

com.b3nac.injuredandroid.DisplayPostXSS

The passed user input is loaded in a webView. The problem is with settings.setJavascriptEnabled(true); which allows the attackers to execute JavaScript code.

Let’s inject XSS payload as there’s no any restrictions of the passed user input.

I’ve injected a basic XSS payload: <img src=1 onerror=alert("Hacked")>

Login

let’s do the same as we did in the last challenge.

It’s just a flag input field. Let’s review the source code.

It just checks if the entered flag is equal to F1ag_0n3.

Resources

From the challenge name, It reveals that it’s related to res directory or resources.arsc directory.

Searching in strings.xml, we got flag.

Login2

Just flag input as the last one.

It takes the user input and compare it with the decoded value from g().a()

Let’s review g() class.

Here we got the base64 encoded flag, so let’s decode it.

Let’s submit the flag 4_overdone_omelets.

Login3

Just flag input as other login challenges.

It take the user input and compare with k.a(strangeValue), I thought it’s base64 encoded but it’s not.

Reviewing the method’s code, the strange value is DES encryption of the flag.

Here, I decided to use frida to get flag.

I used frida as the comparing function do, by decrypting the strange value.

Java.perform(function () {
let k = Java.use("b3nac.injuredandroid.k");
let decryptedValue = k.a("k3FElEG9lnoWbOateGhj5pX6QsXRNJKh///8Jxi8KXW7iDpk2xRxhQ==");
console.log("Flag: " + decryptedValue);
});

SQLite

Let’s open the code after we had an overview.

It takes the entered flag and compare it with encrypted flag and compared the entered password with encrypted password.

When decoding the first subtitle value, we got a hash.

Let’s break the hash.

So the password is hunter2. Let’s move forward to the other subtitle value which is a return value of function h.c().

We got another strange value, but it seems that it’s roted.

Trying multiple roting amounts, we got that it’s using ROT47.

Open the link, we got the flag S3V3N_11.

AWS

As most of the challenges, just flag submit.

From the challenge name, It’s related to AWS and cloud. So I decided to search again for any keys and tokens in strings.xml file.

It has no values and reviewing the does not give us much information.

After searching for a while, I got that the used bucket is open because there’s no provided values in AWS tags in strings.xml file.

Here, I used cloud_enum tool to enumerate the public cloud resources.

By using the keyword of the application name to reveal any cloud resources related to it.

python3 cloud_enum.py -k injuredandroid

As expected, there’s open S3 bucket revealing two files, The flag exists in C10ud_S3cur1ty_lol file.

Firebase

Let’s review the source code.

The app first decodes the user input before comparing it with the flag.

The source code reveals a lot of information.

Let’s start with the encoded value.

The decoded value seems to be an endpoint. We got another hint related to using .json with firebase url found in strings.xml file.

So we will append the .json to flags/.

https://injuredandroid.firebaseio.com/flags/.json

When browsing the link, we got the flag. But we should first base64 encode it.

Unicode

Just flag submition input.

Like the last challenge, the source code reveals a lot of information.

Let’s start with the encoded value.

It seems to be also an endpoint, but we got another hints like Find an email address and unicode collision.

I google unicode collision and I got this article.

Using the other hint about finding an email address, I used the article’s example John@Gıthub.com as an input. But I got Not Authenticated!.

After some time, I remmebered our Second Finding that we can use to get authenticated.

When I got authenticated and submit the email address again, I got the flag.

Deep Links

When I click on the challenge, I just got hints like Eploit The Schema, Check The Manifest.

Deep links are specific URLs that, when triggered, can launch a particular activity within an app.

Let’s review AndroidManifest.xml file.

Using flag11 as schema caught my attention as the first hint is Eploit The Schema.

Let’s do further investigations of the source code.

It seems it’s waiting for schema flag11 and action android.intent.action.VIEW to start the activity.

Let’s exploit the schema using adb command.

am start -a android.intent.action.VIEW -d "flag11://"

I was able to bypass the restrictions and start the activity. But we didn’t get the flag.

Let’s get back to the code.

We got another hints, we should look for binary file in the app. We need first to decompile the app.

apktool -d injuredandroid.apk

Then look for the binary in assets or lib directories.

In assets directory, we can find me'nu file and It’s binary executable file.

When executing the file, We got the flag HIIMASTRING.

Protected Components

When I click to open the challenge, I got Use an exported activity as Toast message.

The activity look for totally_secure intent and its value shoud be a URL with https schema.

When I tried to start the activity using adb command, I found the activity is not exported.

So let’s follow the hint and look for an exported activity to start it.

At the beginning, I thought any exported activity can start it, but after spending some time I realized that is not true and there’s only one activity that exists in AndroidManifest.xml file can do this.

After some searching, I found an exported activity that is able to start other activities b3nac.injuredandroid.ExportedProtectedIntent.

Let’s reveal its code.

It uses access_protected_component as an intent that accepts the package name of the wanted protected activity as a value and It only starts packages within the app by checking the package name.

I tried to use adb to perform this task, but it was a little bit complicated so let’s build an app the help us perform this task and get the flag.

package com.hacking.injuredandroidaccess

import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
import androidx.core.view.WindowInsetsCompat

class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
enableEdgeToEdge()
setContentView(R.layout.activity_main)
ViewCompat.setOnApplyWindowInsetsListener(findViewById(R.id.main)) { v, insets ->
val systemBars = insets.getInsets(WindowInsetsCompat.Type.systemBars())
v.setPadding(systemBars.left, systemBars.top, systemBars.right, systemBars.bottom)
insets
}

val intentToProtectedActivity = Intent().apply {
setClassName("b3nac.injuredandroid", "b3nac.injuredandroid.FlagTwelveProtectedActivity")
putExtra("totally_secure", "https://example.com/")
}

val triggeringIntent = Intent().apply {
setClassName("b3nac.injuredandroid", "b3nac.injuredandroid.ExportedProtectedIntent")
putExtra("access_protected_component", intentToProtectedActivity)
}

startActivity(triggeringIntent)
}
}

When I run this build app, I got redirected to protected activity.

Assembly

I got flag input and byte array [58,40,42] when I open challenge.

When I decoded it, I just got :(*

Let’s review the code.

The app is using an exported function from a library and the value of this.z are the byte array that are viewed in the challenge.

So let’s dig deep in the code to get from where this.z get those value.

The exported function is from libnative-lib.so library and the value of this.z are the return values of the exported function.

Let’s reverse the function to have an overview of its workflow.

I got win string and I guess it’s the flag.

In this walkthrough, we successfully exploited the vulnerabilities within the InjuredAndroid application.

Some of the challenges did not work with me.

If there’s any mistakes, please DM me. I’m waiting for your feedbacks.

--

--