发觉已然没有值得我兴奋的教程,真正的大佬们把自己的技术藏的严严实实[滑稽]便从研究MOD改个方向研究安全。寻思着一法通则万法通,本意是想写一个so层的c++签名检验,往hook框架进发。所以最近研究了一些关于签名检验的东西,从java层面,以及对lgl菜单的一个兼容,写了一个java层次的签名检验代码
由于我们经常需要对游戏进行去签,一些检验方式可能不是很适合,可能把自己的也防了。所以就从md5值方向出发。
实现功能比较简单,检验md5值,正确就正确运行,错误就弹出对话框,对话框的构造函数是默认的安卓对话框方式,实现功能为可以跳转链接。。。如果你有一定开发基础,也可以根据这个方向进行一定美化以及,对检验强度进行一个加强,这是我在so层检验的一个小产物。。
主要部分都有注释,复制全文提取代码部分粘贴到你的菜单项目,文件路径为:
我的菜单/app/src/main/java/com/android/support/main.java
建议是在完成植入与编译后,通过dex2c将代码抽取,提高安全程度。。。
package com.android.support;import android.app.AlertDialog;import android.content.pm.PackageInfo;import android.content.pm.PackageManager;import android.content.pm.Signature;import java.security.NoSuchAlgorithmException;import android.content.Context;import android.content.Intent;import android.graphics.Canvas;import android.content.DialogInterface;import android.graphics.drawable.GradientDrawable;import android.net.ConnectivityManager;import android.net.NetworkInfo;import android.net.Uri;import android.os.Build;import android.os.Environment;import android.os.Looper;import android.os.Process;import android.provider.Settings;import android.view.Gravity;import android.view.SurfaceHolder;import android.view.View;import android.widget.Button;import android.widget.EditText;import android.widget.LinearLayout;import android.widget.LinearLayout.LayoutParams;import android.widget.TextView;import android.widget.Toast;import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.FileWriter;import java.io.IOException;import java.io.InputStreamReader;import java.io.OutputStream;import java.net.HttpURLConnection;import java.net.NetworkInterface;import java.net.URL;import java.security.MessageDigest;import java.text.SimpleDateFormat;import java.util.Collections;import java.util.GregorianCalendar;import java.util.List;import java.util.UUID;import org.json.JSONException;import org.json.JSONObject;import static android.graphics.Typeface.BOLD;import android.app.Activity;public class Main {private static native void CheckOverlayPermission(Context context);static {//你所用so库的名字System.loadLibrary("mylibname");}public static interface callbackSwitch {void newMenu(Context context);}//获取<a href="https://www.knrjk.com/tag/99" target="_blank">应用</a>签名 MD5 值private static String getAppSignatureMD5(Context context) {try {PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES);Signature[] signatures = packageInfo.signatures;byte[] signatureBytes = signatures[0].toByteArray();MessageDigest md = MessageDigest.getInstance("MD5");md.update(signatureBytes);byte[] digest = md.digest();StringBuilder sb = new StringBuilder();for (byte b : digest) {sb.append(String.format("%02<a href="https://www.knrjk.com/tag/1481" target="_blank">X</a>", b));}return sb.toString();} catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) {e.printStackTrace();return null;}}public static void Start(Context context) {CrashHandler.init(context, false);// 检查签名 MD5 值String appSignatureMD5 = getAppSignatureMD5(context);String expectedMD5 = "123456"; // 请将此处替换为您期望的 MD5 值if (appSignatureMD5 != null && appSignatureMD5.equals(expectedMD5)) {CheckOverlayPermission(context);} else {// 签名错误,退出程序showErrorDialog(context);}}private static void showErrorDialog(final Context context) {AlertDialog.Builder builder = new AlertDialog.Builder(context);builder.setTitle("错误");//对话框标题builder.setMessage("签名错误,退出程序");builder.setPositiveButton("打开链接", new DialogInterface.OnClickListener() {@Overridepublic void onClick(DialogInterface dialog, int which) {Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com"));context.startActivity(browserIntent);}});builder.setCancelable(false);builder.show();}}package com.android.support; import android.app.AlertDialog; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import java.security.NoSuchAlgorithmException; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; import android.content.DialogInterface; import android.graphics.drawable.GradientDrawable; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.Looper; import android.os.Process; import android.provider.Settings; import android.view.Gravity; import android.view.SurfaceHolder; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.NetworkInterface; import java.net.URL; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.GregorianCalendar; import java.util.List; import java.util.UUID; import org.json.JSONException; import org.json.JSONObject; import static android.graphics.Typeface.BOLD; import android.app.Activity; public class Main { private static native void CheckOverlayPermission(Context context); static { //你所用so库的名字 System.loadLibrary("mylibname"); } public static interface callbackSwitch { void newMenu(Context context); } //获取<a href="https://www.knrjk.com/tag/99" target="_blank">应用</a>签名 MD5 值 private static String getAppSignatureMD5(Context context) { try { PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); Signature[] signatures = packageInfo.signatures; byte[] signatureBytes = signatures[0].toByteArray(); MessageDigest md = MessageDigest.getInstance("MD5"); md.update(signatureBytes); byte[] digest = md.digest(); StringBuilder sb = new StringBuilder(); for (byte b : digest) { sb.append(String.format("%02<a href="https://www.knrjk.com/tag/1481" target="_blank">X</a>", b)); } return sb.toString(); } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } public static void Start(Context context) { CrashHandler.init(context, false); // 检查签名 MD5 值 String appSignatureMD5 = getAppSignatureMD5(context); String expectedMD5 = "123456"; // 请将此处替换为您期望的 MD5 值 if (appSignatureMD5 != null && appSignatureMD5.equals(expectedMD5)) { CheckOverlayPermission(context); } else { // 签名错误,退出程序 showErrorDialog(context); } } private static void showErrorDialog(final Context context) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("错误");//对话框标题 builder.setMessage("签名错误,退出程序"); builder.setPositiveButton("打开链接", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com")); context.startActivity(browserIntent); } }); builder.setCancelable(false); builder.show(); } }package com.android.support; import android.app.AlertDialog; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import java.security.NoSuchAlgorithmException; import android.content.Context; import android.content.Intent; import android.graphics.Canvas; import android.content.DialogInterface; import android.graphics.drawable.GradientDrawable; import android.net.ConnectivityManager; import android.net.NetworkInfo; import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.Looper; import android.os.Process; import android.provider.Settings; import android.view.Gravity; import android.view.SurfaceHolder; import android.view.View; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.TextView; import android.widget.Toast; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.NetworkInterface; import java.net.URL; import java.security.MessageDigest; import java.text.SimpleDateFormat; import java.util.Collections; import java.util.GregorianCalendar; import java.util.List; import java.util.UUID; import org.json.JSONException; import org.json.JSONObject; import static android.graphics.Typeface.BOLD; import android.app.Activity; public class Main { private static native void CheckOverlayPermission(Context context); static { //你所用so库的名字 System.loadLibrary("mylibname"); } public static interface callbackSwitch { void newMenu(Context context); } //获取应用签名 MD5 值 private static String getAppSignatureMD5(Context context) { try { PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), PackageManager.GET_SIGNATURES); Signature[] signatures = packageInfo.signatures; byte[] signatureBytes = signatures[0].toByteArray(); MessageDigest md = MessageDigest.getInstance("MD5"); md.update(signatureBytes); byte[] digest = md.digest(); StringBuilder sb = new StringBuilder(); for (byte b : digest) { sb.append(String.format("%02X", b)); } return sb.toString(); } catch (PackageManager.NameNotFoundException | NoSuchAlgorithmException e) { e.printStackTrace(); return null; } } public static void Start(Context context) { CrashHandler.init(context, false); // 检查签名 MD5 值 String appSignatureMD5 = getAppSignatureMD5(context); String expectedMD5 = "123456"; // 请将此处替换为您期望的 MD5 值 if (appSignatureMD5 != null && appSignatureMD5.equals(expectedMD5)) { CheckOverlayPermission(context); } else { // 签名错误,退出程序 showErrorDialog(context); } } private static void showErrorDialog(final Context context) { AlertDialog.Builder builder = new AlertDialog.Builder(context); builder.setTitle("错误");//对话框标题 builder.setMessage("签名错误,退出程序"); builder.setPositiveButton("打开链接", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("https://www.example.com")); context.startActivity(browserIntent); } }); builder.setCancelable(false); builder.show(); } }

THE END