I would like to build a library that is used for applications. The library is not free. I intend to code it by using C++, and compile into binary files which my clients can import to their Android applications (written by Java/Kotlin).
This is just my roughly idea, I haven't done any similar thing previously.
Could someone who used to do same thing before guide me the best practice for this kind of library?
At the end of the day, if you give someone binaries, they will be able to reverse engineer it to some extent no matter what you do. With that said, there are a few things you can do to make reverse engineering really hard.
First, you'll only want to provide C++ headers for your user (that don't expose implementation details). Then, you'll distribute the actual .dll or .so compiled binary, of which they can only access the assembly code. A great example of this strategy I've seen is Porcupine, who only distributes headers.
You can look into code obfuscation, but this probably isn't worth it for C++. If you have Java parts to the library though, this could help.
Set a restrictive license on your library, most well-intended developers would rather find an alternative library upon seeing your non-open source license rather than wasting time stealing it and reverse engineering it. Porcupine also has a licensing system (and the library will expire without a valid license). So you could look into that as well.
Does your library have to be local? Can some parts be hidden behind an API that your users could call instead?
Only distribute your library to paying customers (do not provide headers, binaries, or anything to non-subscribers).
Related
i am using ndk and android studio to secure my api-key and it works now.
also i am trying dirty code to harden disassembling... .
but i can still decompile and see native methods in java classes.
also pre-built .so(shared object) files are available in apk and wil be used again!
Questions:
After releasing the apk, all hackers can see .so file and they can use custom settings in .mk file and program specific native methods like my class for extracting the api-key only. they call my functions related to api-key without knowing the implementation. am i eliminating something here?
is proguard necessary for this way ?
That's right, there is no way to prevent .so reuse by malicious agent. Therefore, your native API should never reveal secret information to the Java side. You can perform some validation in your native methods to check if the calling Java actually belongs to the legitimate APK.
On the other hand, don't underestimate another vulnerability of native code: your .so can be disassembled with relevant tools, and any protection may be torn off. There exist means of obfuscation and resilience to reverse engineering for native code, but the earning curve for them is much steeper than with ProGuard.
Still, it's worthwhile to at least not keep the api-key in plain text in your C++ code. Try yourself to run
strings libnative.so
(here libnative.so is the .so file extracted from your APK) and you may discover important information that is waiting to be stolen from your library, no sophisticated reverse engineering necessary.
As far as ProGuard is concerned, it does not add protection to the native methods you use. You cannot even obfuscate the class name and method name for a native method. (Well, it is possible, but very tricky, and there are no tools that can help with such setup).
You increase the time hackers will need to decompile and understand the .so file. Estimate how hard it is, and change the way your api authentification works from time to time. Doing so makes previous hacking attempt obsolete, even if they have been successful.
To clarify : put the api-key and the authentification process in the native methods. For instance, for an HTTPS api, send the uri, json content, usertoken, to a native method. Then in the native code, use these and the api-key and some hash functions to create a hash. And output that hash to the Java code to be send in the HTTP request. By doing so, it will be hard to guess the authentification recipe by simply monitoring entries and output. Attackers will have to decompile the native code.
Activate Proguard, compile, decompile, and see for yourself. On my opinion it does raise a good level of complexity for a very easy set up.
We have created a gradle plugin to hide keys in the Android NDK, you can check all the implementation on github : https://github.com/klaxit/hidden-secrets-gradle-plugin
The goal is to make it as hard as possible to reverse engineer keys. We encourage to add a custom encrypt algorithm then keys are stored in the NDK as hexadecimal arrays.
We would love to have feedbacks on our solution !
I have given up trying to get Proguard to work on either Eclipse or Android Studio. The docs are arcane and whatever I try, the Proguard obfuscated apk blows. Also questions regarding Proguard don't get much attention on this forum.
Standard Android apk files are designed to almost invite reverse engineering and I'm looking for some ways to protect my code. Not all my code just some methods.
Before I started writing Android apps, I wrote apps in C and in C# and I'm familiar with both of those languages and actually prefer either of them to Java so I've recently been reading about the NDK.
Of course the NDK is about speed but I'm wondering if it also would help protect my code against reverse engineering and inspection from hackers. I understand that it is "compiled" code so I imagine that the source code would not be visible.
Am I barking up the right tree?
Thanks,
Dean
This depends on what kind of protection you are looking for. If that is a revolutionary algorithm that will allow you do some very popular task much much faster than it takes today, then your code will be reverse engineered, no matter how you obfuscate it; you need patent protection. If you want to hide some unfriendly behavior (like spying on your users), it will be discovered. So don't do it. If you want to protect some protocol of client-server communication, it may be subject to easy attack elsewhere.
But in some cases going C++ does really help; it may be easier to distribute a monolithic shared library "black box" than to deal with Java API. I don't think obfuscation can work on code that you sell as library.
When we were selling a huge communication SDK, we followed this approach, and all our Java code was simply open to customers (part was intended to be changed/customized, but some classes carried a warning in the header "Please don't modify this class, there is very high chance that the product will not work properly if you mess with it".
Native C code is harder to decompile but it can be decompiled easily using the right tools.
Especially if you only develop small parts in C and then communicate with it using JNI which is a clear interface, anybody who decompiles your app can also use it. Who needs to know how your code works if you can simply execute it?
Conclusion: native code can be harder to decompile. But usually the only difference is that you need different tools and you need more knowledge & practice to decompile. Also modifying something is usually more complex.
Just implementing some methods in NDK alone will not likely help a lot. However, the resistance to reverse engineering can be improved if you also apply obfuscation and even run-time protection techniques to your NDK code. A simply web search gives a list of free tools. You could also work with commercial solution providers like Arxan. In addition, the level of obfuscation can generally be improved if you put more logic of your app in native code.
Yes if you use the NDK you can make it very difficult to reverse engineer your code and it is unlikely anybody would try.
I have created an Android library and I would like to protect the library code from reverse engineering. To my understanding, I could either use obfuscation (i.e use proguard) or create an Android Library without the source code. Also I have read some posts that recommend to use both approaches. What is the best approach to use and potential limitations? Is there any other solution you recommend?
Thanks,
Lupe
You should use both, but I guess it won't be enough. Managed languages are very easy to decompile. Android code seems to be even easier to reverse enginner, because of use of built-in libraries. You cannot obfuscate system libraries, so with calls to system libraries your code becomes more and more obvious.
For me you have two ways of dealing with the problem:
rewrite your library in C. Compiled languages are much safer.
rely on the law. Nobody can use your library or its parts when it's officially protected by law as your intellectual property.
I am not sure if the terminology is correct what code practices can you use to make it difficult for someone to modify the binary/assembly to bypass a check:
eg in the source code.
bool verificationResult = verify();
if (verificationResult){
allow_Something();
}else{
prevent_Something();
}
If a person looking at the disassembly version of the above code can modify the 'jump opcodes(?)' to run allow_Something even when the verification result is false.
Something similar is covered here
http://www.codeproject.com/Articles/18961/Tamper-Aware-and-Self-Healing-Code#pre0
Note I am creating the binary in C++ for it to be used via NDK on Android.
As the general consensus is so far, its impossible to prevent anyone hell-bent upon "cracking" your APK from doing so. Obfuscation techniques will only increase the complexity required to "crack" the APK once. After it gets uploaded to the myriad of the sites that offer to host APKs for free, its just a google search away from even the "noob-est" of Android noobs.
Also security through obscurity will NOT get you far.
Regarding protecting your APK from being hacked, i would recommend the following article that discusses the current state of license validation of APKs on Android. The techniques described in it should give you an idea of the common attack-vectors that you need to safeguard against.
Proguard is a good place to start obfuscating your APK.
After you manage to obtain an obfuscated APK, DO run it through the following tools and observe the de-compiled source. All these are free and open-source tools that are very popular and will surely be the first thing that any decent "cracker" will try :
1. baksmali
2. apktool
3. Dex2Jar + JD-Gui
Keep adding layers of obfuscation to your code until you are satisfied that the output of the above tools is fairly complicated to make sense. (Again do NOT under-estimate what a college-grad armed with coke, pizza and the knowledge of DVM opcodes can accomplish over a weekend).
Regarding the techniques discussed in the link you shared, i fail to see how they can be implemented to protect the .dex on Android. And if you end up implementing the verification logic in a separate .so then all the "cracker" would need to do is patch the call in your java code to the verify() function inside the .so.
UPDATE:
Additional obfuscation steps to secure the .so.
1. Do NOT follow a more or less linear path.
Adding additional jumps all over the place works by flooding the "cracker" with so many potential targets which need to be individually modified and patched and verified if the protection has been bypassed.
2. Add timing checks
This is mainly to throw off the "cracker" by making the code follow different paths during debug and actual run-time. If the time spent between two points is a lot more than usual then its a clear indication that your program is being debugged. i.e time to jump into that part of junk code that calculates the number of pianos in the world.
3. Write self modifying code
Again this thwarts static analysis. For example if your jump into the verification function does not exist in the binary but is patched everywhere as part of some init() function in the .so.
All the above techniques(and more) are described with examples in the following article on anti-debugging techniques.
A more comprehensive guide is Ultimate Anti Debugging Reference by Peter Ferrie.
Avoid using too transparent checks. Try some basic workflow obfuscating (for example XOR-ing result), this can help to defend against simple opcode replacing. But I assure you, that if someone wants (very-very) to crack you, he can do it regardless of complexity of your protection.
Dexguard is made by the same people who did Proguard, but it allows for even finer-grained options. That said, Proguard is more or less the industry standard for Android obfuscation. Though, as said above, if someone with the know-how wants to crack your app, there's no protection to be had for love or money.
The simple truth: you can't.
You can purchase utilities to obfuscate your object code but they are all trivially bypassed by any slightly motivated attacker. If your user can write to the program image (on disk or in memory) no amount of obfuscation will defend against it.
If it is extremely important, I recommend moving the important component to a device you control and provide some form of challenge-response code to access it. It won't prevent people from cracking it, but it can put up a much more significant barrier against it.
Is there a way to somehow 'protect' a native shared library (.so) for the Android platform against binary changing?
E.g. someone could overwrite a JMP instruction with a NOP after reverse engineering the application, and distribute that library to rooted devices.
Is there anything someone can do?
What I'm looking for here is ideas about implementing a series of checks (e.g. encryption, checksumming etc).
Of course since the platform does not look like it offers support for this (correct me if I'm wrong) it would have to be all 'client-side'. Thus the whole thing is a bit futile, but at least will hinder reverse engineering some.
Yes there are things you can do, and they will make it very challenging for the Reverse Engineer, but I doubt you'd be able to do anything that would stop Chris Eagle.
The best way to protect from modification is to take a SHA-2 of the .so after you compile it, and rehash each time at runtime, matching it against the known value. This check will be enforced on the client side, so a skilled RE could just modify the binary to ignore the check. It does make it a bit harder though. If you put checks all throughout your code and use different checking techniques then it extends the amount of work the RE has to do. Do know however that Microsoft has poured millions of dollars into anti-RE techniques and there are still pirated copies of Office and Windows out there. You'll never stop them all. My personal philosophy (now that I've studied RE myself) is that it is ultimately too much of a pain to try and stop them. Just make a good app, make it cheap, and people will buy. The miscreants that steal your stuff wouldn't have bought it anyway.
If your app calls home you could also submit the hash to the server for verification. Of course and RE can still bypass this but it is one more thing to do.