x32x01
  • by x32x01 ||
Android reverse engineering (Part 2) refers to the process of decompiling the APK for the purpose of investigating the source code that is running in the background of an application. In part 1 (refer here) we saw how an attacker would be able to decompile, change the smali files and recompile and sign the APK to perform some kind of function, for example, changing root detection logic of the application. In this extension of reversing articles, we’ll see different scenarios in which an attacker is able to extract juicy information by decompiling an APK while understanding various default files present in android. It is wrong to say this article covers all of the aspects of reversing and extracting info, however, it will lay out a fundamental process as to how one can proceed to do so.

Let’s begin

Table of Content
  • Understanding default files
  • Understanding improper WebView implementation
  • Hardcoded secrets
  • Secrets in strings.xml file
  • Insecure classes implementation
  • Insecure decryption method for hardcoded values
  • Insecure cryptography in SQLite database
  • Hard coded AWS credentials
Understanding default files
AndroidManifest.xml –
Manifest literally means to show. This is the most literal file in the whole of the application as it does precisely what it’s name suggests. It begins with a <manifest> tag. It should also contain “xmlns: attribute” which declares several system attributes used within the file. It declares:
  • <permissions> – Permissions that APK requires to run
  • <activity> – Various activities in the APK
  • <intent-filter> – Intent filters
  • <data android:scheme=”string” /> – Data Schemes
  • <action android:name=”string” /> – Action that an intent performs
  • <uses-configuration> tag – specifies input mechanisms
  • <uses-sdk> tag – specifies android API to be used
Hence, Manifest file is the guide which is needed by the package to make particular components behave the way the developer intended them to.

Strings.xml – This XML file contains strings that can be referenced from the application or from other resource files (such as an XML layout). In other words, I can use a reference to strings’ object in my actual Java class so that I don’t have to type in the complete value then and there and also if there is a need to change that value in future, I won’t need to go to my java class every single time to change it, I can just change the value in the strings file. One example is supposed in Java file the code flows like this:
Code:
String string = getString(R.string.hello);

Here, R.string.<string object> sets the value of variable string. I can make its reference in the layout file like this:
<TextView
android:layout_width=”fill_parent”
android:layout_height=”wrap_content”
android:text=”@string/hello” />


This sets the type of view that the hello object would have while displaying in app. Here, @string/hello refers to strings.xml file’s hello object. So, finally in the strings.xml file code would be something like:
<?xml version=”1.0″ encoding=”utf-8″?>
<resources>
<string name=”hello”>Hello!</string>
</resources>


So, the variable string would indirectly get assigned a value “Hello!” Note that <resources> tag allocates a string value.

R.java file – It is an auto-generated file by aapt (Android Asset Packaging Tool) that contains resource IDs for all the resources of res/ directory. If you create any component in the activity_main.xml file, id for the corresponding component is automatically created in this file. This id can be used in the activity source file to perform any action on the component. If you delete this, it’ll get auto-generated again.

There are various other default files as well, we’ll talk about them later when we discover each.

Understanding improper WebView implementation
This will lay up your basics. Now, this article specifically talks about what code to look for in order to understand if webview implementation is insecure or not. Now, for the purpose of this article, I’ll be using InjuredAndroid.apk developed by Kyle Benac. You can find it here. It would look something like this
1.png
In the very first challenge of the application, we’ll see a poor webview implementation. First activity’s source code is:
2.png
Here, we can see that a string type variable post is receiving a value from an input field and supplying it to DisplayPostXSS.class using intent. We’ll understand what happens when it reaches the said class from the source code:
3.png
Here, we can easily see that the said input is getting parsed as an HTML and being displayed within a webview. Also, JavaScript is enabled. This means only one thing for us researchers. XSS!
4.png
After sending in the payload we can see that WebView is able to display the supplied input in an HTMl format like this
5.png
Hence, this taught us how we can look for XSS bugs by decompiling the application

HardCoded Secrets
Oftentimes, for ease of access developers would hard code various secret keys, decryption functions and other juicy things within the application and so by reversing the APK we can extract them. For example, if we see FlagOneLoginActivity developer has laid out a little hint at the bottom.
6.png
Now, let’s reverse the application using JADX and see what’s hidden under GUI. It can be easily inferred even after obfuscation that submitFlag() method is comparing a user supplied input with a given flag “F1ag_0n3”. Hence, the entire login mechanism is bypassed just by looking for the right class after reversing.
7.png
After we input the flag, we see that it was indeed correct.
8.png
Secrets in strings.xml file
Oftentimes, developers create a reference string and use that object in Java class whose actual value is stored in strings.xml file. For example, in FlagThreeActivity we can see the developer has laid out a little hint at the bottom.
9.png
Now, let’s look at this activity’s code in jadx first. We’ll observe that an object with a gibberish name is being used.
10.png
It is quite easily understood that user-supplied input is being compared with a resource that is stored in strings.xml file. Hence, what we’ll do is decompile the package using apktool and then traverse to the directory: /res/values/strings.xml
Code:
apktool d InjuredAndroid-1.0.10-release.apk
cd InjuredAndroid-1.0.10-release/res/values
cat strings.xml | grep cmVz
11.png
Hence, we have our third flag.

Insecure classes implementation
Just like an object can be referred from strings.xml file, similarly, other classes can also be implemented to perform a specific function with an object, and it’s return value be used. For example, in the FlagFourActivity we see something similar
12.png
Now, after observing the code underneath the class we see that return value from a certain g class’ a() method. Now, due to obfuscation the original classes and methods names have been changed.
13.png
Pondering over g.a() we’ll see that a base64 encoded value is being decoded and supplied as an input and typecasted in a byte array.
14.png
After encoding this, we’ll get this flag.
Code:
echo "NF9vdmVyZG9uZV9vbWVsZXRz" > to_decode
cat to_decode | base64 --decode
15.png
Insecure decryption method for hard coded values
Oftentimes, developers implement methods to generate keys and encrypt some information which is either received from a user or to encrypt a secret such as login credentials within the application. For example in FlagSixLoginActivity we can see that a certain k.a() return value is being compared with a user input.
16.png
This gibberish value is a base64 encoded byte array. Now, we are going to inspect k.a() method.
17.png
This certainly implies that a is receiving string str, which is getting base64 decoded first and then encrypted using a DES key generated. Reversing this function manually in very difficult, but it is certainly possible if we intercept the () method’s return value when it calculates and supplies the value to FlagSixLoginActivity. Kyle Benac has given a code in his repository to do this with javascript using Frida. Here is the code:
JavaScript:
console.log("Script loaded successfully ");
Java.perform(function x() {
console.log("Inside java perform function");
var my_class = Java.use("b3nac.injuredandroid.VGV4dEVuY3J5cHRpb25Ud28");
var string_class = Java.use("java.lang.String");
my_class.decrypt.overload("java.lang.String").implementation = function (x) { //hooking the new function
console.log("*************************************")
var my_string = string_class.$new("k3FElEG9lnoWbOateGhj5pX6QsXRNJKh///8Jxi8KXW7iDpk2xRxhQ==");
console.log("Original arg: " + x);
var ret = this.decrypt(my_string);
console.log("Return value: " + ret);
console.log("*************************************")
return ret;
};
Java.choose("b3nac.injuredandroid", {
onMatch: function (instance) {
console.log("Found instance: " + instance);
console.log("Result of secret func: " + instance.decrypt());
},
onComplete: function () { }
});
});
18.png
Insecure cryptography in SQLite database
Oftentimes, juicy information is obtained from an application’s SQLite database. This happens because the developer has stored some values like credentials, keys etc. within the sqlite itself. Let’s look at one such implementation in FlagSevenSqliteActivity
19.png
Now, each database has its own SQLite database associated with itself. We simply need to traverse to this database and dump values. Note that having root access is sometimes critical to do this, other times if your user has the permissions you’d be able to have a look at the database.
Code:
adb shell
cd /data/data/b3nac.injuredandroid/databases
ls
sqlite3 Thisisatest.db
select * from Thisisatest;
20.png
And just like that we have the flag’s hash which is in MD5 and password which is encrypted in some format as well (ROT47). One can decrypt it and is good to go. It is essential for developers not to use old encryption and hashing techniques.

Hardcoded AWS key and access ID
“World is moving to cloud” ~ Google

“But stupidity exists everywhere” ~ Pentesters

Oftentimes developers hard code or create a reference value of AWS bucket credentials. One such example could be seen in FlagEightLoginActivity. Here, the developer has given a little hint at the bottom too.
21.png
On exploring the activity’s code we see that this client authenticates with aws.
22.png
One of the most common places to look for AWS creds is in the strings.xml file. So we check it:
Code:
cd /InjuredAndroid-1.0.10-release/res/values
cat strings.xml | grep AWS

And it worked like a charm.

Now we’ll create a profile of aws and can easily use AWS cli to connect to it. To make profile:
Code:
cd ~ && mkdir .aws
cd .aws && nano credentials

Copy the obtained ID and access key in it.
23.png
Conclusion
Even after string obfuscation, various classes, objects and strings can be reversed and used to harm an organisation. It is very essential that developers follow strict practices for security given by OWASP MSTG. Thanks for reading.
 

Similar Threads

x32x01
Replies
0
Views
112
x32x01
x32x01
x32x01
Replies
0
Views
122
x32x01
x32x01
x32x01
Replies
0
Views
205
x32x01
x32x01
x32x01
  • x32x01
Replies
0
Views
249
x32x01
x32x01
x32x01
  • x32x01
Replies
0
Views
234
x32x01
x32x01
TAGs: Tags
android penetration testing apk reverse engineering reverse engineering

Register & Login Faster

Forgot your password?

Latest Resources

Forum Statistics

Threads
517
Messages
518
Members
45
Latest Member
Tacola
Back
Top