本文将介绍一个简单的防破解版的方法,希望能跟大家一起讨论学习。
目前最常见也是最简单的单机游戏破解方法就是直接反编译apk,然后寻找三大运营商的计费函数调用代码,然后粗暴的将支付结果强制改为成功,然后用破解者自己的keystore打包发布。下面我们要介绍的防破解方法,就是检查keystore是否被更换,一旦发现更换,就直接退出游戏。
1、执行命令keytool -list -v -keystore thorqq.keystore , 其中thorqq.keystore改成你的秘钥库文件名。
将执行结果中MD5后面的一长串字符串去掉冒号并改为小写后保存下来(在这里是:3f8e70eea5bedb593525623c0c47822f)。
2、在android工程中新建MyApplication.java,增加如下代码获取apk包签名的md5值。
private static String FingerprintMd5 = "";
public static String getFingerprintMd5()
{
return FingerprintMd5;
}
public Signature[] getRawSignature(Context context) {
PackageManager pkgMgr = context.getPackageManager();
PackageInfo info = null;
try {
info = pkgMgr.getPackageInfo(getPackageName(),
PackageManager.GET_SIGNATURES);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
if (info == null) {
return null;
}
return info.signatures;
}
private static String FingerprintMd5 = "";
public String stringToMD5(byte[] string) {
byte[] hash;
try {
hash = MessageDigest.getInstance("MD5").digest(string);
} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
return "";
} catch (Exception e) {
e.printStackTrace();
return "";
}
StringBuilder hex = new StringBuilder(hash.length * 2);
for (byte b : hash) {
if ((b & 0xFF) < 0x10)
hex.append("0");
hex.append(Integer.toHexString(b & 0xFF));
}
return FingerprintMd5 = hex.toString();
}
@Override
public void onCreate() {
//MD5 fingerprint
stringToMD5(getRawSignature(this)[0].toByteArray());
super.onCreate();
}
3、在cpp工程中增加检查指纹的函数,比较从java中获取的md5值与我们自己的md5是否一致,如果不一致,则认为指纹错误,返回false
bool checkFingerprint()
{
//check fingerprint
JniMethodInfo minfo;
bool isHave = JniHelper::getStaticMethodInfo(minfo,
"org/cocos2dx/cpp/MyApplication", "getFingerprintMd5", "()Ljava/lang/String;");
//没有在java中找到getFingerprintMd5这个函数
if (!isHave)
{
return false;
}
else
{
//调用getFingerprintMd5
jstring jstr = (jstring)minfo.env->CallStaticObjectMethod(minfo.classID, minfo.methodID);
std::string ret = JniHelper::jstring2string(jstr);
Analytics::getInstance()->event(AnalyticsEvent::FingerPrint, ret.c_str());
GameData::getInstance()->setValue(GAMEDATA::FINGER_PRINT, ret);
//这里就是上面我们在keytool命令后保存的md5指纹。为增加破解难度,这里最好要对字符串进行加密处理
std::string a = "3f8e70eea5bedb593525623c0c47822f";
//判断指纹是否一致
if (a != ret)
{
return false;
}
}
return true;
}
4、在上层业务逻辑中调用checkFingerprint(),如果返回false,则提醒用户并直接退出游戏。
本游戏正式开放源代码啦~~
代码库:https://git.oschina.net/thorqq/RaidenFree
Win版试玩:http://pan.baidu.com/s/1hsbrUug