Project1

标题: RMMV 游戏数据加密,JS混淆(只适合代码人,非一键) [打印本页]

作者: 神秘中国人    时间: 2019-2-27 14:52
标题: RMMV 游戏数据加密,JS混淆(只适合代码人,非一键)
本帖最后由 神秘中国人 于 2019-2-27 15:21 编辑

使用默认工程的来做的示范。

步骤一:闭包。   新建cmain.js 文件,写上(function (){ })()
        
  把注释的JS文件,按顺序把内容复制到cmain.js里面。


然后代码中找到DataManager.loadDataFile   把window[name] 改成 eval(name)



这样子,代码就会形成闭包。  在控制台是无法访问到对应的JSON数据。

步骤二,加密解密JSON。
加密:
1.在我们的工程index.html. 在加载cmain.js之前添加
  1. <script type="text/javascript">
  2.             window.Base64 = {
  3.                 _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  4.                 encode: function(e) {
  5.                     var t = "";
  6.                     var n, r, i, s, o, u, a;
  7.                     var f = 0;
  8.                     e = Base64._utf8_encode(e);
  9.                     while (f < e.length) {
  10.                         n = e.charCodeAt(f++);
  11.                         r = e.charCodeAt(f++);
  12.                         i = e.charCodeAt(f++);
  13.                         s = n >> 2;
  14.                         o = (n & 3) << 4 | r >> 4;
  15.                         u = (r & 15) << 2 | i >> 6;
  16.                         a = i & 63;
  17.                         if (isNaN(r)) {
  18.                             u = a = 64
  19.                         } else if (isNaN(i)) {
  20.                             a = 64
  21.                         }
  22.                         t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
  23.                     }
  24.                     return t
  25.                 },
  26.                 decode: function(e) {
  27.                     var t = "";
  28.                     var n, r, i;
  29.                     var s, o, u, a;
  30.                     var f = 0;
  31.                     e = e.replace(/[^A-Za-z0-9+/=]/g, "");
  32.                     while (f < e.length) {
  33.                         s = this._keyStr.indexOf(e.charAt(f++));
  34.                         o = this._keyStr.indexOf(e.charAt(f++));
  35.                         u = this._keyStr.indexOf(e.charAt(f++));
  36.                         a = this._keyStr.indexOf(e.charAt(f++));
  37.                         n = s << 2 | o >> 4;
  38.                         r = (o & 15) << 4 | u >> 2;
  39.                         i = (u & 3) << 6 | a;
  40.                         t = t + String.fromCharCode(n);
  41.                         if (u != 64) {
  42.                             t = t + String.fromCharCode(r)
  43.                         }
  44.                         if (a != 64) {
  45.                             t = t + String.fromCharCode(i)
  46.                         }
  47.                     }
  48.                     t = Base64._utf8_decode(t);
  49.                     return t
  50.                 },
  51.                 _utf8_encode: function(e) {
  52.                     e = e.replace(/rn/g, "n");
  53.                     var t = "";
  54.                     for (var n = 0; n < e.length; n++) {
  55.                         var r = e.charCodeAt(n);
  56.                         if (r < 128) {
  57.                             t += String.fromCharCode(r)
  58.                         } else if (r > 127 && r < 2048) {
  59.                             t += String.fromCharCode(r >> 6 | 192);
  60.                             t += String.fromCharCode(r & 63 | 128)
  61.                         } else {
  62.                             t += String.fromCharCode(r >> 12 | 224);
  63.                             t += String.fromCharCode(r >> 6 & 63 | 128);
  64.                             t += String.fromCharCode(r & 63 | 128)
  65.                         }
  66.                     }
  67.                     return t
  68.                 },
  69.                 _utf8_decode: function(e) {
  70.                     var t = "";
  71.                     var n = 0;
  72.                     var r = c1 = c2 = 0;
  73.                     while (n < e.length) {
  74.                         r = e.charCodeAt(n);
  75.                         if (r < 128) {
  76.                             t += String.fromCharCode(r);
  77.                             n++
  78.                         } else if (r > 191 && r < 224) {
  79.                             c2 = e.charCodeAt(n + 1);
  80.                             t += String.fromCharCode((r & 31) << 6 | c2 & 63);
  81.                             n += 2
  82.                         } else {
  83.                             c2 = e.charCodeAt(n + 1);
  84.                             c3 = e.charCodeAt(n + 2);
  85.                             t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
  86.                             n += 3
  87.                         }
  88.                     }
  89.                     return t
  90.                 }
  91.             }
  92.         </script>
复制代码
2.在桌面上新建一个index.html把以下内容拷贝进去。
  1. <body></body>
  2. <script type="text/javascript">
  3.         window.Base64 = {
  4.     _keyStr: "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=",
  5.     encode: function(e) {
  6.         var t = "";
  7.         var n, r, i, s, o, u, a;
  8.         var f = 0;
  9.         e = Base64._utf8_encode(e);
  10.         while (f < e.length) {
  11.             n = e.charCodeAt(f++);
  12.             r = e.charCodeAt(f++);
  13.             i = e.charCodeAt(f++);
  14.             s = n >> 2;
  15.             o = (n & 3) << 4 | r >> 4;
  16.             u = (r & 15) << 2 | i >> 6;
  17.             a = i & 63;
  18.             if (isNaN(r)) {
  19.                 u = a = 64
  20.             } else if (isNaN(i)) {
  21.                 a = 64
  22.             }
  23.             t = t + this._keyStr.charAt(s) + this._keyStr.charAt(o) + this._keyStr.charAt(u) + this._keyStr.charAt(a)
  24.         }
  25.         return t
  26.     },
  27.     decode: function(e) {
  28.         var t = "";
  29.         var n, r, i;
  30.         var s, o, u, a;
  31.         var f = 0;
  32.         e = e.replace(/[^A-Za-z0-9+/=]/g, "");
  33.         while (f < e.length) {
  34.             s = this._keyStr.indexOf(e.charAt(f++));
  35.             o = this._keyStr.indexOf(e.charAt(f++));
  36.             u = this._keyStr.indexOf(e.charAt(f++));
  37.             a = this._keyStr.indexOf(e.charAt(f++));
  38.             n = s << 2 | o >> 4;
  39.             r = (o & 15) << 4 | u >> 2;
  40.             i = (u & 3) << 6 | a;
  41.             t = t + String.fromCharCode(n);
  42.             if (u != 64) {
  43.                 t = t + String.fromCharCode(r)
  44.             }
  45.             if (a != 64) {
  46.                 t = t + String.fromCharCode(i)
  47.             }
  48.         }
  49.         t = Base64._utf8_decode(t);
  50.         return t
  51.     },
  52.     _utf8_encode: function(e) {
  53.         e = e.replace(/rn/g, "n");
  54.         var t = "";
  55.         for (var n = 0; n < e.length; n++) {
  56.             var r = e.charCodeAt(n);
  57.             if (r < 128) {
  58.                 t += String.fromCharCode(r)
  59.             } else if (r > 127 && r < 2048) {
  60.                 t += String.fromCharCode(r >> 6 | 192);
  61.                 t += String.fromCharCode(r & 63 | 128)
  62.             } else {
  63.                 t += String.fromCharCode(r >> 12 | 224);
  64.                 t += String.fromCharCode(r >> 6 & 63 | 128);
  65.                 t += String.fromCharCode(r & 63 | 128)
  66.             }
  67.         }
  68.         return t
  69.     },
  70.     _utf8_decode: function(e) {
  71.         var t = "";
  72.         var n = 0;
  73.         var r = c1 = c2 = 0;
  74.         while (n < e.length) {
  75.             r = e.charCodeAt(n);
  76.             if (r < 128) {
  77.                 t += String.fromCharCode(r);
  78.                 n++
  79.             } else if (r > 191 && r < 224) {
  80.                 c2 = e.charCodeAt(n + 1);
  81.                 t += String.fromCharCode((r & 31) << 6 | c2 & 63);
  82.                 n += 2
  83.             } else {
  84.                 c2 = e.charCodeAt(n + 1);
  85.                 c3 = e.charCodeAt(n + 2);
  86.                 t += String.fromCharCode((r & 15) << 12 | (c2 & 63) << 6 | c3 & 63);
  87.                 n += 3
  88.             }
  89.         }
  90.         return t
  91.     }
  92. }


  93. var jsonbase64Data = (Base64.encode('我是地图数据'));


  94. var secret1 = {
  95.         encryption:function (txt){
  96.                 var key = [];
  97.                 key[0] = 'DAsMCww4ad46yLDE1NTIak2MDE2LMiiwxNTUyLDE1NTIsMTU1Miw2MDE2LDE1MKOmmaaD5wLDAsMCwwLDA';
  98.                 key[1] = 'DcCw4ad46yLDE1NTIak2esMTU1Miw2MdDE1MKOmmdaaD5wLDAsMCwwLDA';
  99.                 key[2] = 'ecCw4ad46ywxNTUyLDE1NTIxiixNTUyLDE1NTIxNTUyLDE1NTIsMTDA';
  100.                 var to = '2dcMDE2LMiiwxNTUyL';
  101.                 var footer = 'e1MKOmmaaD5wLDAsC2C12casdQD';
  102.                 var newJsonbase64Data = to;

  103.                 var keyNumber  = Math.ceil(Math.random()*100);

  104.                 for(var k in jsonbase64Data){

  105.                         newJsonbase64Data += jsonbase64Data[k];
  106.                        
  107.                         if(k == keyNumber){
  108.                                 var num = Math.ceil(Math.random());
  109.                                 newJsonbase64Data += key[num];
  110.                                 keyNumber  = Math.ceil(Math.random()*100)*1 + (k*1 + key[num].length*1);
  111.                         }
  112.                 }

  113.                 return newJsonbase64Data+footer;
  114.         },
  115.         decryption:function (){

  116.         }
  117. }
  118. jsonbase64Data = secret1.encryption(jsonbase64Data);
  119. document.querySelector('body').innerHTML = jsonbase64Data;
  120. </script>
复制代码
把你要加密的JSON数据内容拷贝代码中的 “我是地图数据替换掉。
使用谷歌浏览器打开index.html。 你就可以看到加密后的JSON数据。 把数据拷贝出来替换源代码的JSON文件。

解密:
直接拷贝粘贴吧,不多说了。



  1. if(url.indexOf('Map001.json') != -1){
  2.                 var temporary = xhr.responseText;
  3.                temporary = temporary.replace(/DAsMCww4ad46yLDE1NTIak2MDE2LMiiwxNTUyLDE1NTIsMTU1Miw2MDE2LDE1MKOmmaaD5wLDAsMCwwLDA/g,"");
  4.                temporary = temporary.replace(/DcCw4ad46yLDE1NTIak2esMTU1Miw2MdDE1MKOmmdaaD5wLDAsMCwwLDA/g,"");
  5.                temporary = temporary.replace(/ecCw4ad46ywxNTUyLDE1NTIxiixNTUyLDE1NTIxNTUyLDE1NTIsMTDA/g,"");
  6.                temporary = temporary.replace(/2dcMDE2LMiiwxNTUyL/g,"");
  7.                temporary = temporary.replace(/e1MKOmmaaD5wLDAsC2C12casdQD/g,"");
  8.                jsonDataParam = Base64.decode(temporary);
  9.             };
复制代码
注意:url.indexOf('Map001.json')   和 url.indexOf('.json') 的区别。
注意:文档中的 key 要对应
  1. var key = [];
  2. key[0] = 'DAsMCww4ad46yLDE1NTIak2MDE2LMiiwxNTUyLDE1NTIsMTU1Miw2MDE2LDE1MKOmmaaD5wLDAsMCwwLDA';
  3. key[1] = 'DcCw4ad46yLDE1NTIak2esMTU1Miw2MdDE1MKOmmdaaD5wLDAsMCwwLDA';
  4. key[2] = 'ecCw4ad46ywxNTUyLDE1NTIxiixNTUyLDE1NTIxNTUyLDE1NTIsMTDA';
  5. var to = '2dcMDE2LMiiwxNTUyL';
复制代码
  1. var temporary = xhr.responseText;
  2. temporary = temporary.replace(/DAsMCww4ad46yLDE1NTIak2MDE2LMiiwxNTUyLDE1NTIsMTU1Miw2MDE2LDE1MKOmmaaD5wLDAsMCwwLDA/g,"");
  3. temporary = temporary.replace(/DcCw4ad46yLDE1NTIak2esMTU1Miw2MdDE1MKOmmdaaD5wLDAsMCwwLDA/g,"");
  4. temporary = temporary.replace(/ecCw4ad46ywxNTUyLDE1NTIxiixNTUyLDE1NTIxNTUyLDE1NTIsMTDA/g,"");
  5. temporary = temporary.replace(/2dcMDE2LMiiwxNTUyL/g,"");
  6. temporary = temporary.replace(/e1MKOmmaaD5wLDAsC2C12casdQD/g,"");
复制代码




步骤3:JS混淆。
把cmain.js 混淆,不让正常阅读。
JS加密:这个大文件是付费功能,所以我就没亲自测试了。
https://www.sojson.com/jsobfuscator.html


这些步骤跑完后,如果想,从代码上作修改的,能防止99%的程序员了。  

原因很简单:
90%都是,这个游戏价值不大,浪费时间研究破解方法。
9% 努力尝试一下发现还是有点难。

本来就是做这行的1% 专业破解。

这个方法不限制,本来就是做外挂的同胞。 那些是从内存里面修改的。 不是一回事。


例子:
新建默认工程,把地图json拷贝进地图。  并且设置,角色本身就存在是地图001里面。....其他就不多说了。。。留言吧。 本来就不推荐非程序使用。
例子.zip (127.73 KB, 下载次数: 348)


还有一点就是,加密解密的方法,自己编写一次比较好,因为我在这里都公布出来了。 所以建议程序员们自己编写一次。 这样你的加密解密方法都是独一无二。
这里也推荐一下AES 加密解密,秘钥就隐藏分几段出来就好



以后会更新一下,外壳加密的方法, 这样子。不是做外挂的大哥应该都没机会修改了。暂时先这样
作者: if216    时间: 2019-2-27 15:15
本帖最后由 if216 于 2019-2-27 15:18 编辑

太好了,解锁新姿势。
其实混淆是很有用的,本来代码就难读,混淆后基本没人想去读代码,解混淆。反而脱壳的机器有一些。所以代码推荐混淆。当然,我没很好的混淆方案...
作者: guoxiaomi    时间: 2019-2-27 16:29
原来是把所有的文件都放到函数体里,了解了。

关于混淆有一个问题我不太确定:

混淆后函数名和变量名应该全部被替换掉了吧?所以基于原来的代码写的事件脚本是不是就无法使用了?
比如说这种:
$gameVariables.get(1)类似的……
作者: Mehmet    时间: 2019-2-27 19:38
本帖最后由 Mehmet 于 2019-2-27 19:46 编辑

这个方法比昨晚那个完善很多,在不知道怎么加密的情况下估计部分人会无从下手,不过用到控制台的帮助还是可以弄出来.
方法不错,改了秘钥之后就可以自己用来加密了.
不过好像插件会失效,也是需要弄进cmain里面吗?
>>>

作者: pajiman1999    时间: 2019-6-25 17:31
楼主打扰了~闭包这一步不太会
打开index.html写成这样对吗
<!DOCTYPE html>
<html>
    <head>
        <meta charset="UTF-8">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent">
        <meta name="viewport" content="user-scalable=no">
        <link rel="icon" href="icon/icon.png" type="image/png">
        <link rel="apple-touch-icon" href="icon/icon.png">
        <link rel="stylesheet" type="text/css" href="fonts/gamefont.css">
        <title>迷宫</title>
    </head>
    <body style="background-color: black">
        <script type="text/javascript" src="js/libs/pixi.js"></script>
        <script type="text/javascript" src="js/libs/pixi-tilemap.js"></script>
        <script type="text/javascript" src="js/libs/pixi-picture.js"></script>
        <script type="text/javascript" src="js/libs/fpsmeter.js"></script>
        <script type="text/javascript" src="js/libs/lz-string.js"></script>
        <script type="text/javascript" src="js/libs/iphone-inline-video.browser.js"></script>
<script type="text/javascript" src="js/cmain.js"></script>
<!--
<script type="text/javascript" src="js/rpg_core.js"></script>
        <script type="text/javascript" src="js/rpg_managers.js"></script>
        <script type="text/javascript" src="js/rpg_objects.js"></script>
        <script type="text/javascript" src="js/rpg_scenes.js"></script>
        <script type="text/javascript" src="js/rpg_sprites.js"></script>
        <script type="text/javascript" src="js/rpg_windows.js"></script>
        <script type="text/javascript" src="js/plugins.js"></script>
<script type="text/javascript" src="js/main.js"></script>
        //-->
    </body>
</html>

然后 新建
cmain.js

写入
(function (){

       <script type="text/javascript" src="js/rpg_managers.js"></script>
        <script type="text/javascript" src="js/rpg_objects.js"></script>
        <script type="text/javascript" src="js/rpg_scenes.js"></script>
        <script type="text/javascript" src="js/rpg_sprites.js"></script>
        <script type="text/javascript" src="js/rpg_windows.js"></script>
        <script type="text/javascript" src="js/plugins.js"></script>
<script type="text/javascript" src="js/main.js"></script>

})()

最后按照 步骤修改rpg_managers.js里的DataManager.loadDataFile  eval(name)替换
游戏进不去  小白一个 希望能帮忙指出错误
作者: walf_man    时间: 2019-9-6 21:19
楼主非常厉害呀,这下mv做的游戏可以高枕无忧了
作者: rfvtgbzxc    时间: 2022-7-15 16:40
各种插件里频繁使用,甚至可以算作滥用的eval让加密成了深坑。不动eval,懂点游戏数据结构的人分分钟找到注入代码的位置;动了eval,你要改不知道多少代码,给那些放飞自我随意获取数据的脚本料理后事。有很多eval明明可以限定范围,给定变量成为简单的表达式的。




欢迎光临 Project1 (https://rpg.blue/) Powered by Discuz! X3.1