设为首页收藏本站|繁體中文

Project1

 找回密码
 注册会员
搜索
查看: 9698|回复: 13
打印 上一主题 下一主题

[原创发布] RMMV 游戏数据加密,JS混淆(只适合代码人,非一键)

[复制链接]

Lv2.观梦者

梦石
0
星屑
945
在线时间
114 小时
注册时间
2017-8-3
帖子
63
跳转到指定楼层
1
发表于 2019-2-27 14:52:07 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有帐号?注册会员

x
本帖最后由 神秘中国人 于 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 加密解密,秘钥就隐藏分几段出来就好



以后会更新一下,外壳加密的方法, 这样子。不是做外挂的大哥应该都没机会修改了。暂时先这样

点评

以前给人做data加密,加了三层壳(不同的加密方法),最后还要有规律的替换或插入字母或字符,,,  发表于 2019-2-27 23:40

评分

参与人数 3+3 收起 理由
garfeng + 1 精品文章
if216 + 1 精品文章
guoxiaomi + 1 精品文章

查看全部评分

Lv4.逐梦者

梦石
0
星屑
7592
在线时间
1227 小时
注册时间
2008-12-14
帖子
555
2
发表于 2019-2-27 15:15:06 | 只看该作者
本帖最后由 if216 于 2019-2-27 15:18 编辑

太好了,解锁新姿势。
其实混淆是很有用的,本来代码就难读,混淆后基本没人想去读代码,解混淆。反而脱壳的机器有一些。所以代码推荐混淆。当然,我没很好的混淆方案...

点评

混淆,不用自己写,网上找。 虽然本质上是加无用代码。但是自己写还是有点相当麻烦。如果确实不好混淆。 只能做加密,壳子在解密  发表于 2019-2-27 16:08
需要购买本人MV插件必须先加wx好友。加不上wx就是本人忙,没时间卖。原则上太久以前的插件也不想卖,因为我也忘了,维护上会不给力。wx名:alskyif    本人插件地址:
   LCK_SRPG梦幻模拟战、火焰纹章类系统
   究极立绘ADV系统

   究极换装统合系统
   究极! 回想与CG系统
   消息文字的距离调整  
   自动返回上一张地图
回复 支持 反对

使用道具 举报

Lv5.捕梦者 (版主)

梦石
1
星屑
23994
在线时间
3339 小时
注册时间
2011-7-8
帖子
3926

开拓者

3
发表于 2019-2-27 16:29:46 | 只看该作者
原来是把所有的文件都放到函数体里,了解了。

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

混淆后函数名和变量名应该全部被替换掉了吧?所以基于原来的代码写的事件脚本是不是就无法使用了?
比如说这种:
$gameVariables.get(1)类似的……

点评

印象中事件脚本里的代码是json数据,在MV中以eval调用,如果变量名不正确应该会报错吧,我去测试一下  发表于 2019-2-28 14:34
不会,只要保证你的事件。 是存活在函数里面。  发表于 2019-2-28 11:18
熟悉rgss和ruby,xp区版主~
正在填坑:《膜拜组传奇》讲述膜拜组和学霸们的故事。
已上steam:与TXBD合作的Reformers《变革者》
* 战斗调用公共事件 *
* RGSOS 网络脚本 *
回复 支持 1 反对 0

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
4349
在线时间
552 小时
注册时间
2017-12-2
帖子
41
4
发表于 2019-2-27 19:38:58 | 只看该作者
本帖最后由 Mehmet 于 2019-2-27 19:46 编辑

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

点评

你这个cmain.js是例子吧。你可以用自己工程试试。 在控制台的帮助下?是啥意思....我不是熟RMMV,把对应的window 对象都闭包了,控制台无法访问  发表于 2019-2-28 10:01
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
2075
在线时间
211 小时
注册时间
2018-4-23
帖子
119
5
发表于 2019-6-25 17:31:00 | 只看该作者
楼主打扰了~闭包这一步不太会
打开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)替换
游戏进不去  小白一个 希望能帮忙指出错误
回复 支持 反对

使用道具 举报

Lv4.逐梦者

梦石
0
星屑
14622
在线时间
718 小时
注册时间
2011-7-16
帖子
1428

开拓者

6
发表于 2019-9-6 21:19:09 | 只看该作者
楼主非常厉害呀,这下mv做的游戏可以高枕无忧了
RMMV网络插件,开源免费,内含服务器端,无需强制登录,云数据,弹幕,云存档,排名,兑换码,版本检测,可自由上架下架删除。q群399090587
免打包运行MV游戏,云游戏,安卓App雷神游戏厅,在线玩游戏,上传下载游戏
开源游戏:重装机兵之重装归来【RMMV制作】全球首款按照美剧分季分集的方式发布的游戏
体素画 -- MV画3D像素图的画板
RMMV显示3D模型和场景的插件
RMMV显示spine骨骼动画的插件
RMMV秘密通道插件
突破敌群数量上限8个的插件
在rmmv中显示gif动态图片的插件
一款可以在mv游戏界面的任意位置显示任意文字的插件
RMMV Toast 插件 带物品得失提示,可以设置开启关闭 兼容yep itemcore
制作一个改名卡道具插件、调整标题页面菜单的插件、在标题页面之前显示大段文字的插件、标题页面显示版本号的插件
物品得失自动提示自动上色自动换行插件
我的Q群 663889472
另外,我的插件、范例、游戏都在这里
回复 支持 反对

使用道具 举报

Lv3.寻梦者

梦石
0
星屑
4139
在线时间
500 小时
注册时间
2011-3-26
帖子
110
7
发表于 2022-7-15 16:40:44 | 只看该作者
各种插件里频繁使用,甚至可以算作滥用的eval让加密成了深坑。不动eval,懂点游戏数据结构的人分分钟找到注入代码的位置;动了eval,你要改不知道多少代码,给那些放飞自我随意获取数据的脚本料理后事。有很多eval明明可以限定范围,给定变量成为简单的表达式的。

点评

除此之外,闭包后的混淆会改变类名称,这让存档的反序列化变得更困难了,如果游戏代码更新,混淆的类名也跟着更新,就会导致存档的类名失效。  发表于 2022-7-15 22:36
另外楼主大大的方案也有同样的问题,eval在不加密前可以获取到闭包里的变量,加密后变量名改变就拿不到了,在尝试改掉所有eval的方案  发表于 2022-7-15 17:12
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

拿上你的纸笔,建造一个属于你的梦想世界,加入吧。
 注册会员
找回密码

站长信箱:[email protected]|手机版|小黑屋|无图版|Project1游戏制作

GMT+8, 2024-11-16 06:57

Powered by Discuz! X3.1

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表