We can use lots of tools like apktool, baksmali, dex2jar to convert a android app to java source code easily. So now most of our developers will put the core-function in the native level(with C/C++ code) because the arm-assembly language or C pseudo code are more difficult to read than java.
But others can still read the native code if they really want, they can use IDA to read .so files and debug our apps dynamicly. In order to make our apps difficultly to debug dynamicly, we may will need to add some methods that can provide antidebug functions for us.
This aritcle will provide a simple example about how to antidebug and the sinature-verify.
PS: Recently I am helping my teacher to prepare a Android-Security Course, so I feel it is time to record something, and Sorry for my poor English. (: but I think write article in English is the fast way to help me to improve my English.
When we publish our apps to the app-store, we will sign apps with our private key, and put the public key into our apps, if others modify our apps, he will re-sign the apps and the public key will be changed, so we can add some code into our apps to check the sinature, if it is not same with ourselves public keys, we can let the apps to exit to prevent the modified apps do something that is harmful to users.
Below is the code in java level:
The java code above will do the sinature verify in java level. As what we have metioned, it is easy to be pathed by modify the smali file. So the more safy way is to do it in a .so file, which is so-called “native level”.
To do it, we should add some code in our java code, and be careful, what this example do is simple add a native funciton that will only do the sign-check, this can be patched easily by modify the smali, too. So in the real env we should merge the code to our core-function, that means if we patched the native method call in java level, the app won’t work.
Below code will return the signature, you can do the verify after you get the sinature easily:
The code above will call the java function via relfcetion, and the second arguement is a Context object that can be passed by declare a java method like
Simplly, we can start a new process via the fork(), the new process will check the parent’s /proc/[PID]/status file to see whether the TracerPid is 0, if not, kill the parent and then exit. Also, we should prevent others to debug the child process via dynamic debuging, we can let the child process ptrace itself.
The code below will provide antidebug function:
To do something more, you can also create a marco which will do
and put it in a lot of places in your c source code, to add the difficulty of reversing apps.
In this article we provide a simple example about antidebug and signCheck, it can not prevent others to reverse our apps completely, but it can add the difficulty in reversing. Hope this article can help someone. :)