Create your own Android security tool, because you are a Hacker: Intercepting Android application network (day 98)
Because the tools you usually used are not enough and you think you can do it better
Thus, in this post, I will show you some of the thought processes that you can apply when designing your own hacking tools. We will take a look at how to automate the process of intercepting an Android application.
If you want to see the source code directly you can check the following Github link
Some Background Knowledge:
Let's start with a simple question?"why do we want to automate the process of intercepting an Android application?"
First, you need to download the proxy certificate. In Burpsuite, all you need to do is go to http://localhost:8080 and you need to change the cert extension into .crt. Copy the cert to the device folder, make sure you put this to a directory that you can easy to find, in this context I put the cert at "Downloads" folder.
To copy the file, you can do this by ADB tools:
~# adb push cacert.crt /storage/emulated/0/Download/
Go to settings and search for "Install certificates from SD card" this will take you to encryption & credential settings in the device.
Click "Install from SD card" and choose the proxy certification that you have installed earlier.
"Easy peasy lemon squeezy"
But! in Android Nougat, this approach will not work anymore.
"why?"According to Android-developer official website, Google has changed how the Android device will handle trusted Certificate Authorities(CA) to provide more security. These changes include:
- Safe and easy APIs to trust custom CA's.
- Apps that target API Level 24 and above no longer trust user or admin-added CA's for secure connections, by default.
- All devices running Android Nougat offer the same standardized set of system CA's—no device-specific customizations.
We are interested in the second and third points. It shows that if we want to intercept application traffic, we need to make the app explicitly state it by customizing it.
You can follow these steps to customize the application:
- Decompile the application using Apktool. Apktool helps us to get the original file of the apk file.
- ~# apktool d <apk file> -d <directory result>
- Edit the configuration in the AndroidManifest.xml file. In layman's term, The Manifest file is a file containing a summary of permission, components, and configuration that the application needs to have to run in the device. Put the following string to "application tag" in the XML file:<application android:networkSecurityConfig="@xml/network_security_config"...>the added string will told the application to use network security configuration inside "network_security_config.xml" file located in the XML directory.
- Create a new file named "network_security_config.xml" inside the res/xml directory with the following content that instructs the application to trust any preinstalled system and user-added CAs.
<network-security-config> <base-config> <trust-anchors> <!-- Trust preinstalled CAs --> <certificates src="system" /> <!-- Additionally trust user added CAs --> <certificates src="user" /> </trust-anchors> </base-config> </network-security-config>
The "res" directory contains all the pretty things that we see in the android app such as image, font, color, style, and dimension. - Rebuild the application, after customizing the application configuration it's time to rebuild the directory into the apk file again.
- ~# apktool b <app folder> -o <new apk>
- Sign the application, we got our new application but it's not ready yet to be installed. We need to sign the application, you can use "uber-sign" tools to do this task.
- ~# java -jar uber-apk-signer.jar --apks /path/to/apks (make sure java is installed in your host)
Finally, you can install the new customized app and start sniffing the application's traffic.
But as you probably realized there are a lot of steps that we need to take before doing any analysis of a single application. Thus, it is a good idea to automate the following steps using the programming language of our choice.
The Good Stuff:
Now we are ready to create our own tools, from this point I will use python version 3 as the programming language of choice. It's up to you if you want to use Ruby, Golang or Java, etc whatever that makes you comfortable
Setting up global variables:
First, we want to make global variables that hold the path to Apktool, Uber signer, and Java so we don't have to repeatedly type the path in every function.
Checking the file:
We want to make sure that the file that is submitted to our scripts is an apk file, we can utilize the python-magic library to identify the file type. First, you need to install the library using the python-pip utility~# pip3 install python3-magic
Next, create a function named "check_file_apk" to hold the logic of our file check. To detect the file type you can use the "from_file" function from the magic library that we have installed earlier, the result of the function will be check if it's "application/zip" or not.
you should already know that android apk file is a zip file this is why we compared it with the string "application/zip"
Decompiling the apk file:
As we were sure that the user submits the correct file, we will straight to decompile the apk file using the Apktool.Unfortunately, I haven't found any python library that integrated with the Apktool, so we will use os python library to execute OS command on the machine that invokes Apktool command for us.
- First, we referenced the path of the Apktool from the global variable that we have initialized earlier.
- Put some logging message so we know that it reaches the function(optional).
- We construct the output directory name and make sure the result is in the same directory of our tools. I'm using "os.path.basename" to retrieve the name of the file from the path(if user submit "/home/user/test.apk", it will result "test.apk") and append it with "_smali"
- We construct the OS command using a python format string.
- Show the constructed os command using logging function so we know that the tool correctly places the string together(optional).
- Execute the OS command using os.system() function and we compare the return value. If it returns 0 it means that our command successfully executed and finally we return the output directory for further reference.
Edit the manifest file:
We have decompiled the apk file, the next logical step is to edit the manifest file.- To edit an XML file we can use the ElementTree library. However, before we move any further I should warn you when the python ElementTree read the AndroidManifest.xml file you will soon notice that the prefix "android:" is replaced with "{http://schemas.android.com/apk/res/android}" and it will screw the entire file if we try to update it.
- Thus, we told the library so that it knows to treat "http://schemas.android.com/apk/res/android" as "android" using ET.register_namespace() function.
- We show the directory that is passed into the function(optional).
- We join the path of output directory with the AndroidManifext.xml string to get the real path using os.path.join() function.
- We need to make sure that the path we produce is correct so we check if the produced path leads to a file or not using os.path.isfile() function.
- We show the path of the AndroidManifest.xml file(optional).
- We load the XML file using parse() function and get the root of the XML using getroot(), we need to obtain the root first so we can navigate around the XML content. More details about python and XML files can be read in this link.
- Inside the XML file, our main interest is the "application" tag we can get this tag directly by using find() function and we want to retrieve the content or attribute by appending the find() function with attrib.
- Next, we want to append the new configuration in this tag which is "android:networkSecurityConfig" with the content "@xml/network_security_config" this means that the app will look for the configuration file named "network_security_config" in XML folder. Doing this is pretty easy, we can just add a new entry by creating a new key along with the content like a dictionary in python.
- Finally, We update XML file so the new entry is saved using write() function
Copied the configuration file:
Now that we have customized the AndroidManifest.xml to use the new network configuration, we need to create a "network_security_config.xml" in /res/xml folder of the application directory.
- We joined the output directory with "res/xml" string to get the destination path.
- I just create a new file named "network_security_config.xml" located in the tool directory and fill it with this configuration:
<network-security-config> <base-config> <trust-anchors> <!-- Trust preinstalled CAs --> <certificates src="system" /> <!-- Additionally trust user added CAs --> <certificates src="user" /> </trust-anchors> </base-config> </network-security-config>
- Next, we check if the source file and destination folder are present using isfile() and isdir() function respectively.
- Put some logging message so we know that it reaches the function(optional).
- Finally, copy the source file into the destination folder using shutil.copy() function. More details on how to use python to automate copy can be check in this link.
Rebuild the application directory into a new apk file:
Creating a function to rebuild the application is not much of a difference when doing the decompilation process, the only thing that is different is the OS command that we need to pass to the os.system() function. Using "b" as the parameter dictates the Apktool to build the application directory to an APK file.
Finally, at the end of the function, we return the file path inside the variable file_output as a reference.
Once we are done with all of the heavy liftings we will create one last function to sign a newly build apk file. This is a crucial step because the Android device will not accept unsigned applications.
The process is pretty similar to decompiling and rebuilds APK function, however, in this function, we joined two tools into one command strings(Uber-signer and Java)
Put it together into the main function:
We have created several functions with each own programming task, we use this approach to make it easy to trace a bug and easier to read rather than bulked all of the functionality into one main function that could be a whole lot of mess. Now, it is time to put it into one main function, like this:Printing the banner is optional, it is up to you whether you want to print a cool logo every time you want to run the program.
The sequence of the logic follows the order of function that we make earlier. First, we check if the file that submits to the program is APK file or not, if its yes it will decompile the program using Apktool then we saved the output directory so it can be referenced for edit_manifest_xml and copied_configuration_file function that will set up all the necessary configuration to prepare the application for proxy.
Finally, the program will rebuild the application directory into an APK file and saved the path of the file to be a reference for signing_new_apk function that will sign the new apk file.
The final result will be like this:
Once the script finishes the execution it will generate two folders consist of the smali folder which is the result of the Apktool and apk signed folder that contain the newly signed APK file that you will install in your Android device, whereas, one new apk file that is not yet signed.
For a test drive, I download the reddit(v.2.25.0) link application and turns out it works well enough for me :).
That's all for this blog I hope you enjoy creating your own tools, it is difficult but feels so rewarding at the end. I will try to run the tools into more testing cases to see if there is anything that I could improve in future development.
Comments
Post a Comment