apk防破解方案的一种方式。
把自己的发布和调试签名公钥,放于cpp,然后用jni从apk中提取包公钥进行对比可以简单加大破解难度。
这里我只拿到PackageInfo这一层,有兴趣的朋友可以拿
PackageManager或ApplicationInfo,这样更不怕被伪造。
先照例一个跨平台的接口
class CheckPackage
{
public:
CheckPackage(){}
virtual ~CheckPackage(){}
public:
virtual bool checking() = 0;
};
typedef Milk::SingletonHolder<CheckPackage,UnImplCreatePolicy> CheckPackageManager;
class CheckPackageAndroid
: public CheckPackage
{
public:
virtual bool checking();
};
template<>
CheckPackage* UnImplCreatePolicy<CheckPackage>::Create()
{
return new CheckPackageAndroid;
}
template<>
void UnImplCreatePolicy<CheckPackage>::Destroy(CheckPackage* p)
{
delete p;
}
bool CheckPackageAndroid::checking()
{
jobject _packageInfo = UtilJni::getPackageInfo();
JniHelper& jh = JniHelperManager::Instance();
JNIEnv* _env = jh.getJNIEnv();
//
jclass _jPackageInfo = _env->FindClass("android/content/pm/PackageInfo");
//jclass _jSignature = _env->FindClass("android/content/pm/Signature");
//jfieldID aId = env->GetFieldID(jcClass, "a", "[B");
//jfieldID topicFieldId = (*env)->GetFieldID(env, objectClass,"topic", "Ljava/lang/String;");
jfieldID _signatureFieldID = _env->GetFieldID(_jPackageInfo,"signatures","[Landroid/content/pm/Signature;");
//
jobject _signatureArrayObject = _env->GetObjectField(_packageInfo,_signatureFieldID);
jobjectArray* _signatureArray = reinterpret_cast<jobjectArray*>(&_signatureArrayObject);
//jobject (*GetObjectArrayElement)(JNIEnv*, jobjectArray, jsize);
jobject _signature = _env->GetObjectArrayElement(*_signatureArray,0);
//jobject _signature = UtilJni::getSignature();
if (_signature)
{
JniMethodInfo t;
std::string ret("");
JniHelper& jh = JniHelperManager::Instance();
if (jh.getMethodInfo(t, "android/content/pm/Signature", "toCharsString", "()Ljava/lang/String;"))
{
jstring str = (jstring)t.env->CallObjectMethod(_signature,t.methodID);
t.env->DeleteLocalRef(t.classID);
ret = jh.jstring2string(str);
t.env->DeleteLocalRef(str);
}
//dish_log("_signature :["<<ret<<"]");
int i1 = ret.find(_PublicKeyRelease);
int i2 = ret.find(_PublicKeyDebug);
if (i1>0||i2>0)
{
return true;
}
else
{
return false;
}
}
else
{
return false;
}
}
然后判别:
if (!dish::<span style="font-family: Arial, Helvetica, sans-serif;">CheckPackage</span><span style="font-family: Arial, Helvetica, sans-serif;">Manager::Instance().checking())</span>
{
dish_log("PublicKey error.");
dish::LayerNotityManager::Instance().logV(0,"Good luck!");
}