最近項目臨出包測試時,測試反饋部分敏感數據可以在運行時被八門神器或gg大玩家等工具搜索到並進行修改。
迫不得已,只能暫停手頭的工作重新檢查既定的內存加密方案情況。然而,不查不要緊,一查嚇一跳:
1)內存加密的方案最開始的時候推行下去並加到項目中了,但是使用的是網上搜索的插件(也就基本相當於開源了),同時防破解機制不夠穩固
2)項目后續開發的過程中,不斷更新提交相關腳本及proto生成的協議時竟然沒有對比檢查修改的有效性,導致覆蓋問題
3)方案的引入及使用過程有數據定義的遺漏以及使用的不合理導致的Bug
那么就怪不得我了,祭起工具干起來吧。
除了3是瑣碎的排查,針對前兩個問題就寫個小工具處理下就OK了:
protected static string protobufPath = "/Source/Proto/"; [MenuItem("Tools/EncryptProtoScript")] protected static void encryptProtoScript() //對ProtoBuf中定義的int/float等類型的private field進行加密(有需要可以進行文件導入的監聽及自動化處理) { var tArr = Directory.GetFiles(Application.dataPath + protobufPath, "*.cs"); foreach(var filePath in tArr) { var tContent = File.ReadAllText(filePath); bool tIntFlag = tContent.Contains("using Int = EncryptInt;"); bool tFloatFlag = tContent.Contains("using Float = EncryptFloat;"); bool tNeedEncrypt = false; if(tContent.Contains("private int ") || tContent.Contains("private int? ")) { tNeedEncrypt = true; if(!tIntFlag) { tContent = tContent.Replace("EncryptInt", "Int"); tContent = "using Int = EncryptInt;\n" + tContent; } tContent = tContent.Replace("private int ", "private Int ").Replace("private int? ", "private Int? "); } if(tContent.Contains("private float ") || tContent.Contains("private float? ")) { tNeedEncrypt = true; if(!tFloatFlag) { tContent = tContent.Replace("EncryptFloat", "Float"); tContent = "using Float = EncryptFloat;\n" + tContent; } tContent = tContent.Replace("private float ", "private Float ").Replace("private float? ", "private Float? "); } if(tNeedEncrypt) { File.WriteAllText(filePath, tContent); } } AssetDatabase.Refresh(); }
最后總結下吧:
首先,無論何種本地數據安全方案,都基於兩個大前提,不然毫無意義:
1)游戲本身不被破解
2)游戲代碼不被破解
其次針對各種類型的內存搜索數值修改,都是基於數值變化的原理進行不斷縮小范圍來定位,不過同樣基於兩個前提:
1)數值常駐內存
2)數值在內存中的地址穩定不變
因此可以想見,針對內存數據破解的防范或安全方案(需要評估並平衡效率)有以下幾種常見方案:
1)內存中的數據及時清理(實時存盤)
2)進行實時內存存儲位置/地址的修改
3)進行數據加密(加密算法)/進行數據校驗(Hash算法)
4)加鹽/噪音干擾(引入冗余數值,伴隨敏感數據一起變化)