zoukankan      html  css  js  c++  java
  • 仿《雷霆战机》飞行射击手游开发--防破解

    本文将介绍一个简单的防破解版的方法,希望能跟大家一起讨论学习。

        目前最常见也是最简单的单机游戏破解方法就是直接反编译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

  • 相关阅读:
    WebForm跨页面传值---内置对象
    后台获得集合,变成json字符串,放到EL表达式,js进行获取遍历
    Delphi 编写DLL动态链接库文件的知识和样例(有详细步骤,很清楚)
    DELPHI美化界面(2009开始TPanel增加了ParentBackGround)
    在Delphi中创建线程,请一定使用BeginThread()代替CreateThread()创建线程!(更好的管理异常)
    delphi中最小化其他程序及所有程序最小化(使用 shell.minimizeAll 和自己寻找窗口这两种办法)
    电脑睡眠状态(ACPI规范定义了七个状态,使用powercfg -a进行查看)
    javascript
    Master-Worker模式
    程序员的基础和解决问题的思维
  • 原文地址:https://www.cnblogs.com/thorqq/p/6397611.html
Copyright © 2011-2022 走看看