<strong><span style="font-size:24px;">众所周知安卓很容易被反编译,即使做了防止反编译处理许多代码也可以看的到,目前用的比较多的手段是jni,即:把核心代码放到c++中,然后做出so库,这样的话安全性提高不少,但如果不对so库进行特殊处理的话,通过查看反编译后的java代码就会推测出你定义的调用so库的接口,别人就可以仿造你的接口,然后调用你的so库。 其实我们可以再每次调用so库时都在so库中的函数中判断一下安卓的公钥是不是你的,从而阻止他们使用你的so库,具体代码及工程如下</span></strong>
#include"com_example_singjni_MainActivity.h" #include <stdio.h> #include <stdlib.h> // //获取公钥的java代码 //public void getSingInfo() { // try { // String pn=getPackageName(); // // PackageInfo packageInfo = getPackageManager().getPackageInfo( // pn, PackageManager.GET_SIGNATURES); // Signature[] signs = packageInfo.signatures; // Signature sign = signs[0]; // parseSignature(sign.toByteArray()); // } catch (Exception e) { // e.printStackTrace(); // } // } // // public void parseSignature(byte[] signature) { // ByteArrayInputStream bi=new ByteArrayInputStream(signature); // try { // CertificateFactory certFactory = CertificateFactory // .getInstance("X.509"); // X509Certificate cert = (X509Certificate) certFactory // .generateCertificate(new ByteArrayInputStream(signature)); // String pubKey = cert.getPublicKey().toString(); // String signNumber = cert.getSerialNumber().toString(); // // // System.out.println("signName:" + cert.getSigAlgName()); // System.out.println("pubKey:" + pubKey); // System.out.println("signNumber:" + signNumber); // System.out.println("subjectDN:"+cert.getSubjectDN().toString()); // } catch ( Exception e) { // e.printStackTrace(); // } // } //核心代码如下 ,其他可以忽略 JNIEXPORT jstring JNICALL Java_com_example_singjni_MainActivity_sing__Landroid_content_Context_2 (JNIEnv * env, jobject ob1, jobject thiz){ jclass thisClass=env->GetObjectClass(thiz); jmethodID getPNId=env->GetMethodID(thisClass,"getPackageName","()Ljava/lang/String;"); jstring packName=(jstring)env->CallObjectMethod(thiz,getPNId); jmethodID getPMId=env->GetMethodID(thisClass,"getPackageManager","()Landroid/content/pm/PackageManager;"); jobject packManger=env->CallObjectMethod(thiz,getPMId); jmethodID getPIId=env->GetMethodID(env->GetObjectClass(packManger),"getPackageInfo","(Ljava/lang/String;I)Landroid/content/pm/PackageInfo;"); jobject packageInfo=env->CallObjectMethod(packManger,getPIId,packName,0x00000040); jfieldID signaturesId=env->GetFieldID(env->GetObjectClass(packageInfo),"signatures","[Landroid/content/pm/Signature;"); jobject signatures=env->GetObjectField(packageInfo,signaturesId); jobjectArray signaturesArray=(jobjectArray)signatures; //signature=signs[0] jobject signature=env->GetObjectArrayElement(signaturesArray,0); jmethodID signatureBytesMId=env->GetMethodID(env->GetObjectClass(signature),"toByteArray","()[B"); //sign.toByteArray() jobject signatureBytes=env->CallObjectMethod(signature,signatureBytesMId); ///////////////// public void parseSignature(byte[] signature) {}///////////////////////////////////////////////////////////////// jclass certificateFactoryClass=env->FindClass("java/security/cert/CertificateFactory"); jmethodID getInstanceMId=env->GetStaticMethodID(certificateFactoryClass,"getInstance","(Ljava/lang/String;)Ljava/security/cert/CertificateFactory;"); jobject certFactory=env->CallStaticObjectMethod(certificateFactoryClass,getInstanceMId,env->NewStringUTF("X.509")); /////////////////////////////////// jclass byteInStreamClass=env->FindClass("java/io/ByteArrayInputStream"); jmethodID byteArrayInStreamConMId= env->GetMethodID(byteInStreamClass,"<init>","([B)V"); jobject byteArrayInStream=env->NewObject(byteInStreamClass,byteArrayInStreamConMId,signatureBytes); jmethodID generateCertificateMId=env->GetMethodID(certificateFactoryClass,"generateCertificate","(Ljava/io/InputStream;)Ljava/security/cert/Certificate;"); jobject certificate=env->CallObjectMethod(certFactory,generateCertificateMId,byteArrayInStream); jmethodID getPKMId=env->GetMethodID(env->GetObjectClass(certificate),"getPublicKey","()Ljava/security/PublicKey;"); jobject publicKey=env->CallObjectMethod(certificate,getPKMId); jmethodID toStringMId=env->GetMethodID(env->GetObjectClass(publicKey),"toString","()Ljava/lang/String;"); jstring publickeyStr=(jstring)env->CallObjectMethod(publicKey,toStringMId); /////////////////////// jmethodID equalsMId=env->GetMethodID(env->GetObjectClass(publickeyStr),"equals","(Ljava/lang/Object;)Z"); jboolean isCorrect=env->CallBooleanMethod(publickeyStr,equalsMId,env->NewStringUTF("OpenSSLRSAPublicKey{modulus=123..你的公钥...,publicExponent=10001}")); if(!isCorrect) return env->NewStringUTF( "wrong"); jstring jstr=env->NewStringUTF( "correct"); return jstr; } JNIEXPORT jstring JNICALL Java_com_example_singjni_MainActivity_sing (JNIEnv * env, jobject thiz){ jstring jstr=env->NewStringUTF( ""); return jstr; }
java端代码 package com.example.singjni; import java.io.ByteArrayInputStream; import java.io.File; import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.security.cert.Certificate; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.text.SimpleDateFormat; import java.util.Date; import android.app.Activity; import android.app.Application; import android.content.Context; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.Signature; import android.os.Bundle; import android.util.DisplayMetrics; import android.widget.EditText; import android.widget.TextView; import android.widget.Toast; public class MainActivity extends Activity { static{ System.loadLibrary("jniso"); } EditText et; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); et=(EditText) findViewById(R.id.et); String s=sing(this); et.setText(s); System.out.println(s); } public native String sing(); public native String sing(Context context); }
工程下载地址 点击打开链接
时间: 2024-11-25 09:56:17