Software Security and Reverse Analysis in Android [2]-apk anti-cracking technology and security protection mechanism
In Android Application Development, after we develop the software, we do not want others to decompile and crack our applications, and cannot modify our code logic. In fact, in consideration of the security mechanism of applications, we hope that our applications will be highly secure and increase the anti-compilation and cracking costs of competitors through various encryption operations. Imagine that it would take 10 days for a competitor to develop the same application, and 100 days for the competitor to crack our software program. This will inevitably eliminate the idea of hackers cracking our applications. How to increase the opponent's cracking costs requires testing how secure our applications are and how powerful encryption technologies are. An excellent application not only brings benefits to users, but also protects its core technologies.
This article briefly introduces the protection mechanism of Android applications from the following aspects.
1. Do not allow the program to be installed on the simulator
In the previous article, Android software security and reverse analysis [1]-apk decompilation cracking and the majority of operations described in java assembly code reading and writing are static decompilation cracking apk files in Android. Some applications are confused. From SDK2.3, we can see that a proguard folder is added under android-sdk-windows ools, and proguard is a java code obfuscation tool, for details, refer to this blog post to make the code logic more complex. If we need static decompilation and cracking, We need to insert some smali code to dynamically debug and observe the apk logic. So how can we protect our applications from decompilation and cracking? We need to prevent other programmers from decompiling and dynamically debugging my applications. In other words, it is necessary to prevent hacker programmers from installing my application on the simulator.
One way is to prevent your application from running on the simulator. When the application finds itself installed on the simulator, it will commit suicide.
package com.example.cracktest;
import android.app.Activity;
import android.os.Build;
import android.os.Bundle;
public class MainActivity1 extends Activity {
protected void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
if (isEmulator ()) {
// Suicide immediately, find yourself running on the simulator, and quickly commit suicide
android.os.Process.killProcess (android.os.Process.myPid ());
}
setContentView (R.layout.activity_main);
}
/ **
* Determine whether the application is running on the emulator
*
* @return
* /
public boolean isEmulator () {
// model: Android SDK built for x86
// As long as it is in the simulator, no matter what version of the simulator, it will carry the keyword parameter sdk in its MODEL information
if (Build.MODEL.contains (sdk) || Build.MODEL.contains (SDK)) {
return true;
} else {
return false;
}
}
}
The above application can be run on the real machine, but it cannot be opened on the simulator, which prevents hackers from dynamically debugging our application.
Second, check the integrity of the application
The second security mechanism to protect the application is to check the integrity of the application. We can use the jni technology to verify the integrity of the application, or we can use the digital signature to detect the integrity of the application. We know that when an apk file is decompiled and cracked, and the code logic is modified, the jarsigner tool must be used to re-sign the apk before the modified apk file can be run. An application's signature is the only identification that identifies a developer. If an application is decompiled by someone else, then the application's signature will definitely change. When it is found that the signature of the program changes, we can commit suicide to avoid the loss caused by the program. Let's introduce the way of digital signature to check the integrity of the application.
package com.example.cracktest;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
public class MainActivity2 extends Activity {
protected void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
System.out.println (getSignature ());
}
/ **
* Obtain the digital signature of the application
*
* @return
* /
public String getSignature () {
PackageManager pm = getPackageManager ();
try {
// Get the signature of the current application
PackageInfo info = pm.getPackageInfo (getPackageName (),
PackageManager.GET_SIGNATURES);
return info.signatures [0] .toCharsString ();
} catch (NameNotFoundException e) {
e.printStackTrace ();
return;
}
}
}
The digital signature of the application obtained by the above simple example code is,
Any operation on the original apk will modify the digital signature of the original apk. In order to facilitate the judgment in the program, we take the MD5 hash value of the digital signature to judge.
package com.example.cracktest;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
public class MD5 {
/ **
* MD5 encryption of the string
* @param content
* @return
* /
public static String getMD5 (String content) {
try {
MessageDigest digest = MessageDigest.getInstance (MD5);
digest.update (content.getBytes ());
return getHashString (digest);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace ();
}
return null;
}
private static String getHashString (MessageDigest digest) {
StringBuilder builder = new StringBuilder ();
for (byte b: digest.digest ()) {
builder.append (Integer.toHexString ((b >> 4) & 0xf));
builder.append (Integer.toHexString (b & 0xf));
}
return builder.toString ();
}
}
When the application is running, we judge whether the MD5 hash value of the current digital signature is equal to the hash value in the above picture. If it is equal, it runs legally. If it is not equal, we can prove that the apk file has been decompiled and cracked. We committed suicide after 1.5s.
package com.example.cracktest;
import android.app.Activity;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.os.Bundle;
import android.widget.Toast;
public class MainActivity2 extends Activity {
protected void onCreate (Bundle savedInstanceState) {
super.onCreate (savedInstanceState);
setContentView (R.layout.activity_main);
System.out.println (getSignature ());
// The correct signature information is 77e980cae813e5dacc11fdb4c67988fd
if (77e980cae813e5dacc11fdb4c67988fd.equals (getSignature ())) {
Toast.makeText (this, self-verification is completed, legal and normal operation., 0) .show ();
} else {
Toast.makeText (this, you dare to crack my code !, 0) .show ();
new Thread () {
public void run () {
try {
Thread.sleep (1500);
} catch (InterruptedException e) {
e.printStackTrace ();
}
android.os.Process.killProcess (android.os.Process.myPid ());
};
} .start ();
}
}
/ **
* Obtain the digital signature of the application
*
* @return
* /
public String getSignature () {
PackageManager pm = getPackageManager ();
try {
// Get the signature of the current application
PackageInfo info = pm.getPackageInfo (getPackageName (),
PackageManager.GET_SIGNATURES);
return MD5.getMD5 (info.signatures [0] .toCharsString ());
} catch (NameNotFoundException e) {
e.printStackTrace ();
return;
}
}
}
The specific decompilation process can be found in the previous article Software Security and Reverse Analysis in Android [1]-apk decompilation cracking and java assembly code reading and writing, when decompiling apk, modifying smali code, re-signing apk, deploy Go to the simulator to run and find that the program commits suicide after 1.5s.
Check the package name, version name and version number, and then make a judgment, which is similar to the method of detecting digital signatures. If you are interested, you can do your own research.
3. Dynamic bytecode technology
The running bytecode of the application is not local, but on the network side , That is to say, the key core code of our application should not be placed locally, but should be placed on the network server. How to get the bytecode on the network? We download the bytecode from the server to the local via URLClassLoader, and then compile and run. This technique of dynamically obtaining bytecodes from the network can prevent hackers programmers from statically decompiling our applications.
4. Encryption of zip package 5. Packing technology of flower instructions
Developer programmers first make a so shell, as the application's running environment, the shell runs our program code, which is equivalent to adding a code monitor on the upper layer of the java virtual machine. It can also be said that running our application in an encrypted virtual machine increases security.
6. References Use jni technology to check Android application signature information and protect sensitive information Android's decompilation prevention techniques Technical analysis to prevent android apk decompilation How to prevent apk from being decompiled proguard