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

  • 相关阅读:
    自定义类似MessageBox小窗体操作
    WinForm 遍历用户控件里CheckBox
    WinForm BaseClass类常用通用方法
    分页的几种写法
    克服粗心毛病的伪代码
    C++queue的使用
    Unix网络编程学习 < 一 >
    使用log4cxx
    memset函数
    libcurl在windows下的使用
  • 原文地址:https://www.cnblogs.com/thorqq/p/6397611.html
Copyright © 2011-2022 走看看