How to avoid reverse engineering of an APK file
I am developing a payment processing app for Android, and I want to prevent a hacker from accessing any resources, assets or source code from the APK file.
If someone changes the .apk extension to .zip then they can unzip it and easily access all the app's resources and assets, and using dex2jar and a Java decompiler, they can also access the source code. It's very easy to reverse engineer an Android APK file - for more details see Stack Overflow question Reverse engineering from an APK file to a project.
I have used the Proguard tool provided with the Android SDK. When I reverse engineer an APK file generated using a signed keystore and Proguard, I get obfuscated code.
However, the names of Android components remain unchanged and some code, like key-values used in the app, remains unchanged. As per Proguard documentation the tool can't obfuscate components mentioned in the Manifest file.
Now my questions are:
- How can I completely prevent reverse engineering of an Android APK? Is this possible?
- 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?
- 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?
Solution 1:
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
Solution 2:
AFAIK, you cannot protect the files in the /res directory anymore than they are protected right now.
However, there are steps you can take to protect your source code, or at least what it does if not everything.
- Use tools like ProGuard. These will obfuscate your code, and make it harder to read when decompiled, if not impossible.
- Move the most critical parts of the service out of the app, and into a webservice, hidden behind a server side language like PHP. For example, if you have an algorithm that's taken you a million dollars to write. You obviously don't want people stealing it out of your app. Move the algorithm and have it process the data on a remote server, and use the app to simply provide it with the data. Or use the NDK to write them natively into .so files, which are much less likely to be decompiled than apks. I don't think a decompiler for .so files even exists as of now (and even if it did, it wouldn't be as good as the Java decompilers). Additionally, as @nikolay mentioned in the comments, you should use SSL when interacting between the server and device.
- When storing values on the device, don't store them in a raw format. For example, if you have a game, and you're storing the amount of in game currency the user has in SharedPreferences. Let's assume it's
10000
coins. Instead of saving10000
directly, save it using an algorithm like((currency*2)+1)/13
. So instead of10000
, you save1538.53846154
into the SharedPreferences. However, the above example isn't perfect, and you'll have to work to come up with an equation that won't lose currency to rounding errors etc. - You can do a similar thing for server side tasks. Now for an example, let's actually take your payment processing app. Let's say the user has to make a payment of
$200
. Instead of sending a raw$200
value to the server, send a series of smaller, predefined, values that add up to$200
. For example, have a file or table on your server that equates words with values. So let's say thatCharlie
corresponds to$47
, andJohn
to$3
. So instead of sending$200
, you can sendCharlie
four times andJohn
four times. On the server, interpret what they mean and add it up. This prevents a hacker from sending arbitrary values to your server, as they do not know what word corresponds to what value. As an added measure of security, you could have an equation similar to point 3 for this as well, and change the keywords everyn
number of days. - Finally, you can insert random useless source code into your app, so that the hacker is looking for a needle in a haystack. Insert random classes containing snippets from the internet, or just functions for calculating random things like the Fibonacci sequence. Make sure these classes compile, but aren't used by the actual functionality of the app. Add enough of these false classes, and the hacker would have a tough time finding your real code.
All in all, there's no way to protect your app 100%. You can make it harder, but not impossible. Your web server could be compromised, the hacker could figure out your keywords by monitoring multiple transaction amounts and the keywords you send for it, the hacker could painstakingly go through the source and figure out which code is a dummy.
You can only fight back, but never win.
Solution 3:
At no point in the history of computing has it ever been possible to prevent reverse-engineering of software when you give a working copy of it to your attacker. Also, in most likelihood, it never will be possible.
With that understood, there is an obvious solution: don't give your secrets to your attacker. While you can't protect the contents of your APK, what you can protect is anything you don't distribute. Typically this is server-side software used for things like activation, payments, rule-enforcement, and other juicy bits of code. You can protect valuable assets by not distributing them in your APK. Instead, set up a server that responds to requests from your app, "uses" the assets (whatever that might mean) and then sends the result back to the app. If this model doesn't work for the assets you have in mind, then you may want to re-think your strategy.
Also, if your primary goal is to prevent app piracy: don't even bother. You've already burned more time and money on this problem than any anti-piracy measure could possibly ever hope to save you. The return on investment for solving this problem is so low that it doesn't make sense to even think about it.