How to Make APK Secure. Protecting from Decompile

How to make my code secure and prevent from decompiling?

YOUR PROBLEM

I created android app and it is working fine. The issue is that when we decompile the app we can see all the code, so hacker can see our API URL and API Classes so they can clone the app.

Not matter what tool you use to obfuscate or even encrypt code, your API url will need to be in clear text at some point, aka when you do the API request, therefore it's up for grabs by an attacker. So if an attacker is not able to extract it with static binary analyses, it will extract at runtime with an instrumentation framework, like Frida:

Inject your own scripts into black box processes. Hook any function, spy on crypto APIs or trace private application code, no source code needed. Edit, hit save, and instantly see the results. All without compilation steps or program restarts.

So basically the attacker will need to find the place in the code where you do the API request, hook Frida on it, and extract the URL or any secret passed along with it to identify/authorize your mobile app in the API server.

Another approach the attacker can take is to perform a MitM attack in a mobile device he controls, and intercept the request being made to the API server:

MitM attack example
Image sourced from article: Steal that API key with a Man in the Middle Attack

As you can see in the above example the intercepted API request, reveals the API server url and the API key being used.

POSSIBLE SOLUTIONS

So my question is that how can I secure my android app so I can protect it from hackers.

When adding security, no matter if for software or for a material thing, is always about layers, see the medieval castles for example, they don't have only one defense, they have several layers of it. So you should apply the same principle to your mobile app.

I will listed some of the minimal things you should do, but not an exhaustive list of them.

JNI/NDK

The JNI/NDK:

The Native Development Kit (NDK) is a set of tools that allows you to use C and C++ code with Android, and provides platform libraries you can use to manage native activities and access physical device components, such as sensors and touch input.

In this demo app I show how native C code is being used to hide the API key from being easily reverse engineered by static binary analyses, but as you already have seen you grab it with a MitM attack at runtime.


#include <jni.h>
#include <string>
#include "api_key.h"

extern "C" JNIEXPORT jstring JNICALL
Java_com_criticalblue_currencyconverterdemo_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {

// To add the API_KEY to the mobile app when is compiled you need to:
// * copy `api_key.h.example` to `api_key.h`
// * edit the file and replace this text `place-the-api-key-here` with your desired API_KEY
std::string JNI_API_KEY = API_KEY_H;

return env->NewStringUTF(JNI_API_KEY.c_str());
}

Visit the Github repo if you want to see in detail how to implement it in your mobile app.

Obfuscation

You should always obfuscate your code. If you cannot afford a state of the art solution, then at least use the built in ProGuard solution. This increases the time and skills necessary to poke around your code.

Encryption

You can use encryption to hide sensitive code and data, and a quick Google search will yield a lot of resources and techniques.

For user data encryption you can start to understand more about it in the Android docs:

Encryption is the process of encoding all user data on an Android device using symmetric encryption keys. Once a device is encrypted, all user-created data is automatically encrypted before committing it to disk and all reads automatically decrypt data before returning it to the calling process. Encryption ensures that even if an unauthorized party tries to access the data, they won’t be able to read it.

And you can read in the Android docs some examples of doing it:

This document describes the proper way to use Android's cryptographic facilities and includes some examples of its use. If your app requires greater key security, use the Android Keystore system.

But remember, that using Frida will allow for an attacker to hook into the code that returns the data unencrypted, and extract it, but also requires more skill and time to achieve this.

Mobile App Attestation

This concept introduces a new way of dealing with securing your mobile app.

Traditional approaches focus to much on the client side, but in first place the data you want to protect is in the API server, and it's here that you want to have a mechanism that let's you know that what is making the request is really your genuine mobile app, the same you uploaded to the Google Play Store.

Before I dive into the role of the Mobile App Attestation, I would like to first clarify a misconception around what vs who is doing the API request, and I will quote this article I wrote:

The what is the thing making the request to the API server. Is it really a genuine instance of your mobile app, or is it a bot, an automated script or an attacker manually poking around your API server with a tool like Postman?

The who is the user of the mobile app that we can authenticate, authorize and identify in several ways, like using OpenID Connect or OAUTH2 flows.

The Mobile App Attestation role is described in this section of another article I wrote, from where I quote the following text:

The role of a Mobile App Attestation service is to authenticate what is sending the requests, thus only responding to requests coming from genuine mobile app instances and rejecting all other requests from unauthorized sources.

In order to know what is sending the requests to the API server, a Mobile App Attestation service, at run-time, will identify with high confidence that your mobile app is present, has not been tampered/repackaged, is not running in a rooted device, has not been hooked into by an instrumentation framework (Frida, xPosed, Cydia, etc.) and is not the object of a Man in the Middle Attack (MitM). This is achieved by running an SDK in the background that will communicate with a service running in the cloud to attest the integrity of the mobile app and device it is running on.

On a successful attestation of the mobile app integrity, a short time lived JWT token is issued and signed with a secret that only the API server and the Mobile App Attestation service in the cloud know. In the case that attestation fails the JWT token is signed with an incorrect secret. Since the secret used by the Mobile App Attestation service is not known by the mobile app, it is not possible to reverse engineer it at run-time even when the app has been tampered with, is running in a rooted device or communicating over a connection that is the target of a MitM attack.

The mobile app must send the JWT token in the header of every API request. This allows the API server to only serve requests when it can verify that the JWT token was signed with the shared secret and that it has not expired. All other requests will be refused. In other words a valid JWT token tells the API server that what is making the request is the genuine mobile app uploaded to the Google or Apple store, while an invalid or missing JWT token means that what is making the request is not authorized to do so, because it may be a bot, a repackaged app or an attacker making a MitM attack.

So this approach will let your API server to trust with a very high degree of confidence that the request is coming indeed from the same exact mobile app you uploaded to the Google Play store, provided the JWT token has a valid signature and expire time, and discard all other requests as untrustworthy ones.

GOING THE EXTRA MILE

I cannot resist to recommend you the excellent work of the OWASP foundation, because no security solution for mobile is complete without going through The Mobile Security Testing Guide:

The Mobile Security Testing Guide (MSTG) is a comprehensive manual for mobile app security development, testing and reverse engineering.

How to avoid reverse engineering of an APK file

 1. How can I completely avoid reverse engineering of an Android APK? Is this possible?

AFAIK, there is not any trick for complete avoidance of reverse engineering.

And also very well said by @inazaruk: Whatever you do to your code, a potential attacker is able to change it in any way she or he finds it feasible. You basically can't protect your application from being modified. And any protection you put in there can be disabled/removed.

 2. How can I protect all the app's resources, assets and source code so that hackers can't hack the APK file in any way?

You can do different tricks to make hacking harder though. For example, use obfuscation (if it's Java code). This usually slows down reverse engineering significantly.

 3. Is there a way to make hacking more tough or even impossible? What more can I do to protect the source code in my APK file?

As everyone says, and as you probably know, there's no 100% security. But the place to start for Android, that Google has built in, is ProGuard. If you have the option of including shared libraries, you can include the needed code in C++ to verify file sizes, integration,
etc. If you need to add an external native library to your APK's library folder on every build,
then you can use it by the below suggestion.

Put the library in the native library path which defaults to "libs" in
your project folder. If you built the native code for the 'armeabi' target then put it
under libs/armeabi. If it was built with armeabi-v7a then put it under
libs/armeabi-v7a.

<project>/libs/armeabi/libstuff.so

Prevent decompiling android apk

[UPDATE]

**

When you build your application using Android gradle plugin version > 3.4.0, the plugin chooses R8 to optimize and obfuscate the code. The rules can now be configured on proguard-rules.pro or proguard-app.conf files. the rules to indicate what to exclude from the obfuscation are similar to the ones in proguard.cfg used earlier.

You can import your proguard files in your build.gradle like

buildTypes{
...
release{
proguardFiles getDefaultProguardFile(
'proguard-android-optimize.txt'),
'proguard-rules.pro'
}
}

R8 picks up all the existing proguard rules files as long as they're included in the build.gradle. You can also configure what pieces to obfuscate for different product flavors that you may have.

**

[OLD BUT RELEVANT INFO]

Proguard is a tool that will help you obfusate your code. This comes as part of your android tools and you just need to activate it. This link and this will help further.

Proguard's default configuration (in proguard.cfg) will be enough to sufficiently obfuscate your code. However you might want to tweak your proguard configuration when you have methods/classes that are being dynamically accessed.

  1. For instance, accessing classes/methods with Reflection will need you to have the code to be intact. You might sometimes experience ClassNotFoundException if proguard obfuscates it.

  2. If you have classes that are being accessed in the AndroidManifest/ Layout Files, you should prevent proguard from obfuscating them.

This can be done by adding

-keep public class <MyPackage.MyClass> 

to your proguard.cfg.

**

While Proguard makes static analysis harder, DexGuard protects from both static and dynamic analysis. DexGuard is specifially for android applications and is only commercially available while Proguard is open source and is for any java bytecode obfuscation / optimization.

How to make a Phonegap/Cordova apk Secure. Protecting from Decompile

You cannot prevent someone from decompiling your app, but you can make it more difficult for someone to understand the decompiled code. If you run your app through an obfuscator like ProGuard or DexGuard, it will scramble type/member names and strings. Some obfuscators will even rewrite the control flow such that it's very difficult to reason about. That's pretty much the best you can do.

How to use ProGuard to protect apk from decompilation?

If you're using Eclipse with the latest SDK release, just open the project.properties file in your project directory, read the instructions, and uncomment the appropriate line. ProGuard will run when you export your signed application. (It won't run for debug builds, so you can easily debug and also read stack traces.)

Read the developer docs for ProGuard in Android for more information.

How to prevent reverse engineering of an Android APK file to secure code?

Now I want to prevent this APK file from being reverse engineered.

That is impossible, sorry.

If it is possible to secure my app from reverse engineering, what are the steps to follow in my coding or any library is used for that?

ProGuard, properly configured, will obfuscate your code. DexGuard, a commercial extended version of ProGuard, may help a bit more. However, your code can still be converted into smali, and developers with reverse-engineering experience will be able to learn what you do from that smali code.

If you do not want others seeing your code, do not store that code on their device.

How to avoid reverse engineering of an APK file

 1. How can I completely avoid reverse engineering of an Android APK? Is this possible?

AFAIK, there is not any trick for complete avoidance of reverse engineering.

And also very well said by @inazaruk: Whatever you do to your code, a potential attacker is able to change it in any way she or he finds it feasible. You basically can't protect your application from being modified. And any protection you put in there can be disabled/removed.

 2. How can I protect all the app's resources, assets and source code so that hackers can't hack the APK file in any way?

You can do different tricks to make hacking harder though. For example, use obfuscation (if it's Java code). This usually slows down reverse engineering significantly.

 3. Is there a way to make hacking more tough or even impossible? What more can I do to protect the source code in my APK file?

As everyone says, and as you probably know, there's no 100% security. But the place to start for Android, that Google has built in, is ProGuard. If you have the option of including shared libraries, you can include the needed code in C++ to verify file sizes, integration,
etc. If you need to add an external native library to your APK's library folder on every build,
then you can use it by the below suggestion.

Put the library in the native library path which defaults to "libs" in
your project folder. If you built the native code for the 'armeabi' target then put it
under libs/armeabi. If it was built with armeabi-v7a then put it under
libs/armeabi-v7a.

<project>/libs/armeabi/libstuff.so


Related Topics



Leave a reply



Submit