吾爱破解 - LCG - LSG |安卓破解|病毒分析|www.52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

搜索
查看: 6850|回复: 66

[原创] 摩尔庄园页游数据包加密算法逆向及复现

  [复制链接]
FinchK 发表于 2020-5-18 17:08

0x1 前言

​ 本文对摩尔庄园页游进行逆向与分析,解密并复现其核心加解密算法。本思路也适用于其他形式的加解密算法分析过程,尤其是对flascc技术(一种能够在flash中运行C++编译生成的字节码的技术)进行逆向分析。

0x2 所用工具

​ WireShark(数据包抓包)

​ ffdec(Flash反编译)

0x3 逆向分析过程

​ 首先,我们进入游戏,使用抓包工具抓得swf文件,尝试反编译,发现其加密。

​ 我们使用ffdec提供的“搜索内存中的SWF”功能,尝试直接从内存中dump出swf文件。

​ 这里有个小技巧。当下的浏览器为了追求稳定和渲染速度都采用一种技术,将多个页面分为多个进程,很难确定游戏页面到底在哪一个进程里面。我这里自己写了个单进程的小程序。

​ 这样就能轻松dump出我们想要的swf文件了。对文件大小排个序,剔除掉尺寸特别大的,然后逐个反编译。最终我们找到了核心加解密算法所在的文件。

​ 看看反编译的结果:

package com.fcc
{
   import avm2.intrinsics.memory.li8;
   import avm2.intrinsics.memory.si32;
   import avm2.intrinsics.memory.si8;
   import flash.utils.ByteArray;
   import flash.utils.getDefinitionByName;
   import sample.MEncrypt.CModule;
   import sample.MEncrypt.ESP;
   import sample.MEncrypt.F_malloc;
   import sample.MEncrypt.eax;
   import sample.MEncrypt__3A__5C_Development_5C_Crossbridge_5C_cygwin_5C_tmp_5C_cc4krDaY_2E_lto_2E_bc_3A_d3346e37_2D_9080_2D_43e6_2D_a632_2D_6710752e3a2f.F_IDAlloc;
   import sample.MEncrypt__3A__5C_Development_5C_Crossbridge_5C_cygwin_5C_tmp_5C_cc4krDaY_2E_lto_2E_bc_3A_d3346e37_2D_9080_2D_43e6_2D_a632_2D_6710752e3a2f.L__2E_str5;

   public function MDecrypt(param1:ByteArray, param2:int, param3:ByteArray) : void
   {
      var _loc6_:* = 0;
      var _loc17_:* = 0;
      var _loc16_:int = 0;
      var _loc10_:* = 0;
      var _loc13_:int = 0;
      var _loc14_:int = 0;
      var _loc12_:int = 0;
      var _loc11_:* = 0;
      var _loc9_:* = 0;
      var _loc7_:* = 0;
      var _loc5_:* = int(ESP);
      _loc6_ = _loc5_;
      ESP = _loc5_ & -16;
      var _loc4_:* = int(getDefinitionByName("com.taomee.mole.net.ConnectionServerAgent").size);
      if(_loc4_ == 5477)
      {
         ESP = _loc5_ & -16;
         _loc17_ = param2;
         _loc5_ = int(_loc5_ - 16);
         si32(_loc17_,_loc5_);
         ESP = _loc5_;
         F_malloc();
         _loc5_ = int(_loc5_ + 16);
         _loc16_ = eax;
         ESP = _loc5_ & -16;
         CModule.writeBytes(_loc16_,_loc17_,param1);
         _loc5_ = int(_loc5_ - 16);
         _loc14_ = _loc17_ + -1;
         si32(_loc14_,_loc5_);
         ESP = _loc5_;
         F_malloc();
         _loc5_ = int(_loc5_ + 16);
         _loc13_ = eax;
         if(_loc14_ >= 1)
         {
            _loc12_ = _loc16_ + 1;
            _loc11_ = int(_loc17_ + -1);
            _loc10_ = li8(_loc16_);
            _loc9_ = _loc13_;
            do
            {
               _loc4_ = _loc10_ & 224;
               var _loc8_:int = _loc4_ >>> 5;
               _loc10_ = li8(_loc12_);
               _loc4_ = _loc10_ << 3;
               _loc4_ = _loc4_ | _loc8_;
               si8(_loc4_,_loc9_);
               _loc12_ = _loc12_ + 1;
               _loc11_ = int(_loc11_ + -1);
               _loc9_ = int(_loc9_ + 1);
            }
            while(_loc11_ != 0);

            if(_loc14_ >= 1)
            {
               _loc12_ = _loc17_ + -1;
               _loc11_ = _loc13_;
               _loc7_ = 0;
               do
               {
                  _loc10_ = li8(_loc11_);
                  _loc9_ = 0;
                  _loc17_ = int(L__2E_str5);
                  if(_loc7_ != 21)
                  {
                     _loc17_ = int(L__2E_str5 + _loc7_);
                     _loc9_ = int(_loc7_ + 1);
                  }
                  _loc4_ = li8(_loc17_);
                  _loc4_ = _loc4_ ^ _loc10_;
                  si8(_loc4_,_loc11_);
                  _loc11_ = int(_loc11_ + 1);
                  _loc12_ = _loc12_ + -1;
                  _loc7_ = _loc9_;
               }
               while(_loc12_ != 0);

            }
         }
         if(_loc16_ != 0)
         {
            _loc5_ = int(_loc5_ - 16);
            si32(_loc16_,_loc5_);
            ESP = _loc5_;
            F_idalloc();
            _loc5_ = int(_loc5_ + 16);
         }
         ESP = _loc5_ & -16;
         CModule.readBytes(_loc13_,_loc14_,param3);
         if(_loc13_ != 0)
         {
            _loc5_ = int(_loc5_ - 16);
            si32(_loc13_,_loc5_);
            ESP = _loc5_;
            F_idalloc();
            _loc5_ = int(_loc5_ + 16);
         }
      }
      _loc5_ = _loc6_;
      ESP = _loc5_;
      return undefined;
   }
}

​ 相信各位看了后也感觉这代码的可读性的确不佳,在此我对它进行简单的解读。

​ 首先介绍一下代码中所用到的一些函数:

函数签名 函数解释
CModule.readBytes(sourceAddress,count,target) 将源地址的数据写到as代码的变量中
CModule.writeBytes(targetAddress,count,source) 将as代码的变量的值写到目标地址中
si32/si16/si8(value,address) 将定长(8/16/32位)的值写到地址中
li32/li16/li8(address) 从地址中读取定长的数据(8/16/32位)

​ 因为Flash技术的过时,因此我之前并没有接触过ActionScript和Flascc技术,但是相信大家看到这里,应该敏感的发现,这类函数似乎是在模拟底层的内存读写。并且,我们还发现反编译代码中有“ESP”,“eax”这样的关键词,可以大胆的猜测,flascc技术应该是模拟了一个虚拟的运行环境,包含虚拟文件系统,标准的C函数等,这样的代码更接近于汇编代码。

​ 我们通过分析汇编代码的思路,直接分析这个反编译代码,发现其不过是先对每一个byte的8bit进行拆分的预处理,然后异或一个常量值(L__2E_str5),这里的关键就是找到这个常量值在哪。

​ 我们找到这个变量定义的地方:

​ 继续查找定义:

​ 发现其数据拷贝自DS2这个类,我们查看这个swf文件的二进制数据块:

​ 发现了我们想要的:

​ 查看其内容(计算数据偏移:208=0xD0):

​ 嗯,应该是这个没错了。我们直接写一个python脚本,抓取数据包测试我们的加解密函数。

​ 这里我们选择抓取喊话数据包,因为如果我们的解密算法正确,那么我们解密后的数据包中就能看到我们所发送的字符。

​ 抓到包了,丢进python脚本试试。

​ 成功了,看到了我发送的文本。

0x4 后记

​ 话说淘米这算法是真坑啊,当初以为是循环异或,下标应该是0,1,2...n,0,1,2...这样循环的,没想到nt开发者竟然是这样设计的:0,1,2...n,0,0,1,2...给我整了两个0,我都懵了。

​ 其实有了这算法,加上swf反编译后的那些代码,可以做一个真正的云玩家了,懂我意思吧。

0x5 附录

  1. 加解密脚本下载

免费评分

参与人数 38威望 +2 吾爱币 +135 热心值 +36 收起 理由
Harson + 1 + 1 用心讨论,共获提升!
Daemonicly + 1 + 1 我很赞同!
bricher9988 + 1 + 1 谢谢@Thanks!
volcanocan + 1 + 1 用心讨论,共获提升!
dillane + 1 用心讨论,共获提升!
乄落日乀 + 1 + 1 用心讨论,共获提升!
DDFer + 1 + 1 大佬&amp;amp;#128002;&amp;amp;#127866;
中二二 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
xQAQx + 1 + 1 我很赞同!
zeroyearn + 1 + 1 谢谢@Thanks!
q105277951 + 1 + 1 欢迎分析讨论交流,吾爱破解论坛有你更精彩!
gaosld + 1 + 1 热心回复!
Naxior + 1 + 1 用心讨论,共获提升!
sktline + 1 我很赞同!
37566454 + 1 + 1 用心讨论,共获提升!
jnez112358 + 1 + 1 谢谢@Thanks!
独行风云 + 1 + 1 用心讨论,共获提升!
x51zqq + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
Hmily + 2 + 100 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
香烟烈酒无睡意 + 1 + 1 谢谢@Thanks!
3141592654 + 1 用心讨论,共获提升!
雪之下阳乃 + 1 + 1 热心回复!
东方学痞 + 1 + 1 热心回复!
Roberick + 1 我很赞同!
冷淘 + 1 我很赞同!
972038516 + 1 + 1 我很赞同!
blywq + 1 + 1 谢谢@Thanks!
七尺大豆腐 + 1 + 1 热心回复!
tbb233 + 1 + 1 用心讨论,共获提升!
地球守护者 + 1 + 1 用心讨论,共获提升!
wxc6688 + 2 + 1 我很赞同!
忆魂丶天雷 + 1 + 1 我很赞同!
笙若 + 1 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
涛之雨 + 3 + 1 分析到这里应该是目前来说这个游戏能做出的最大贡献 了
巴别塔 + 1 热心回复!
Agzcx + 1 + 1 用心讨论,共获提升!
dddl + 1 + 1 我很赞同!
牧鱼龙 + 1 + 1 用心讨论,共获提升!

查看全部评分

本帖被以下淘专辑推荐:

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

JoeW 发表于 2020-5-18 22:54
0202年了还有人捣鼓摩尔庄园真是不容易啊,我还以为除了搞辅助的人之外没人对这游戏感兴趣了呢,lz辛苦了。现在虽然没关服,但也不会再更新了,当个养老游戏玩玩还好,官方对辅助的态度也是睁一只眼闭一只眼,不做太出格的事也不会封你号,毕竟这游戏已经不能盈利了。说实话对辅助里面的一部分功能我还是挺好奇运行的原理是什么的。
Eaysuild.xean 发表于 2020-5-18 17:52
吞茶嚼花 发表于 2020-5-18 18:47
totoroyyw 发表于 2020-5-18 19:28
淘米也有人干了 有趣
肌肉猛男吴亦凡 发表于 2020-5-18 19:48
```牛嗷
私心作怪 发表于 2020-5-18 20:12
哈哈哈  让我康康谁还玩这个
yawang 发表于 2020-5-18 21:06
爱了爱了
52pjShiron 发表于 2020-5-18 23:02
17roco可以安排一下嘛哈哈哈
小飞虫 发表于 2020-5-18 23:29
下一个目标:赛尔号

点评

似乎挺难的,论坛以前有个大佬拓海真一做过辅助没多久就失效了  发表于 2020-5-22 21:36
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则 警告:本版块禁止灌水或回复与主题无关内容,违者重罚!

快速回复 收藏帖子 返回列表 搜索

RSS订阅|小黑屋|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2020-5-27 20:40

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

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