Make a good lab set up to start test the security of Android applications can be hard work sometimes. Many times, an application will present many steps before you can properly start to test it, that’s the most common case on real-life applications, we will call this barriers ‘pre tests’ for this text. Thinking about a mobile application as a piece of code that you deliver to the hands of your customer, we start to see why is so important to make the app with some hardening parts, so you can grant the code some kind of security.
A unique application can have many pretests steps. So what you will have to do will really vary from app to app. What’s the application’s target customer?? Does this app have a kind of financial transaction? What is the technology that this application was made of? Those are some questions that usually help to kind of predict which pre-tests you can find in one application. Today I will talk about some basic parts that are most common to find in many types of applications.
To make things more interesting, I decided to download some apps and look for what kind of hardening they already have implemented, in this post, I will show some pre-tests that I found looking on 30 of those apps, and those are the technologies that the apps that I was looking was made.
Talking a little bit about the apps, most of them are bank/financial related applications, some of them are e-commerce and all of them are available on the Brazilian play store.
Talking about android applications hardening, one that you will surely see on many applications is obfuscation. The type of obfuscation will vary from app to app, the variables and methods names can be changed to just letters, useless pieces of code can be implemented on the source code, just to make static analysis harder, and the APK can also try to identify when it is trying to be decompiled and crash at some point.
From the 21 native apps that I saw, 14 had some kind of obfuscation. Here I’m only talking about native because when the application is developed with a nom native implementation, other specific files become as interesting as the java files, adding other challenges to the reverse engineering part of the process.
Since most parts of the obfuscation process involve the compile process, and not the code written by the developer itself, we can’t do many things about it. The famous APK decompiler tool jadx provides us with an implementation that can help a little on the obfuscation that renames the variables and methods of the application.
Here we have a code without obfucation:
And this is a piece of code, after it is obfuscated.
Using the –deobf flag, we can set how many characters are the minimum on the app, so each time the jadx finds a name with fewer chars it will be renamed to a more trackable name, making the static analysis process a little easier.
Now looking for another hardening technique, we have anti-root. The relation of the apps that had this kind of hardening was:
As the name says, is basically when the application is aware that it is running on a rooted device and it takes a different behavior after that. What the application will do after that can vary, the app can simply close or move the user to a different activity and lock it there. The method that the application will use to identify when it is running on a rooted device or not will also vary, I will talk about 3 common techniques.
Looking for files
A common way to find when a device has root is looking for some specific files on de device file system, ‘/bin/su/’, ‘/su’ and variations. Here we have a common example from a famous anti root module.
As we can see on this part of the code, it just calls a ‘File.exists’ method on a given string. Anti root has many ways to be bypassed, the most famous is using Frida-based frameworks or a Frida script. Looking at Frida Codeshare, we can find this script. That’s one of the most famous Frida scripts for bypass anti-root detections, it basically looks for common techniques and implements a way that the method is hooked and changes the return (for example from true to false) to prevent the method to alert the application that this device has root privileges. If we take a closer look at this script we will find a part that he just uses an implementation on the same ‘File.exists’ methods that we saw the application using before.
Looking for packages
Another technique that is common to see on root detections is looking for packages, a package is an app that is installed on your device. The implementation is very similar to the previous, it basically uses the ‘getPackageManager’ method, if it fails, the device probably doesn’t have this package.
The same script that we used to prevent ‘File.exists’ also has an implementation for this method call, as we can see here.
Trying to run commands
The last anti root technique that we will see is to try to run a command. The implementation uses the ‘Runtime.getRuntime.exec’ method to try to execute a command that needs some super user privileges on the device, if the command fails, the device probably doesn’t have root privileges available for users.
The same script that we used to prevent the previous methods also has many overloaded implementations of the exec call, as we can see here.
These are some examples of what you can find, probably this script will not work every time, that’s when you need to stop and make some static analysis to try to identify what steps the particular application that you are looking for implements that you can’t bypass now. After that, you surely can make a unique frida script to bypass it.
SSL Pinning is a much more common app hardening technique, it will literally pin an SSL certificate on the application and just function properly on communications made with this certificate, if you just try to put a proxy on the way, since the certificate given to the app will now be the proxy certificate, the app will fail and stop the communications, as if you don’t have internet access. The SSL Pinning feature can also vary from technology to technology, many flutter applications use other methods to check certificates on the HTTPS communications.
The relation of the apps that had this kind of hardening was:
A famous way to implement SSL Pinning on apps is using the OKHTTP3 ‘CertificatePinner‘ class. This class has a method called ‘check’, and as you already guessed there are many ways to bypass this common implementation.
Here we have a famous Frida script that tries to bypass many SSL Pinning techniques. By overloading some check implementations it can easily bypass that OKHTTP3 implementation.
HTTP Body Encoding
A not-so-common feature is encoded all the body on the HTTPS communications, to bypass this you will surely need to take a closer look at the decompiled code, you can start to look at classes that import some classes from the ‘javax.crypto’ package. Sometimes, even a more common script will work on this part, we have some solutions on Brida (it uses a script made by FSecure) and other codeshare scripts.
Keep in mind that these are just some little examples that you can find in the wild. If you are looking for a bigger application, you will probably have to spend more time on the pre-test part. The important thing that we have in mind is that take a look at any kind of application is always a good idea, you never know when you will find a new and more sophisticated technique.
References and good reads
- Jadx tool for decompiling – https://github.com/skylot/jadx
- Frida script used for antiroot – https://codeshare.frida.re/@dzonerzy/fridantiroot/
- Frida script used for SSLPinning – https://codeshare.frida.re/@akabe1/frida-multiple-unpinning/
- Frida script used for look cipher – https://github.com/FSecureLABS/android-keystore-audit/blob/master/frida-scripts/tracer-cipher.js
- Good text about intercept traffic from flutter apps – https://blog.nviso.eu/2019/08/13/intercepting-traffic-from-android-flutter-applications/
- Good text about proxying nom-proxy-aware apps – http://blog.dornea.nu/2014/12/02/howto-proxy-non-proxy-aware-android-applications-through-burp/