AS3 加解密的隐藏常用方式分析


前言

随着时代的进步,flash逐渐推出了舞台,但曾经火爆的flash游戏,还在坚持,as3还在。


一、AS3加密/解密函数隐藏

在实际业务开发过程中,socket通信的安全性,至关重要,必须采用一些加密,减少外挂工具的出现,为提高破解者难度,其对应的加密和解密函数隐藏,其重要作用。


二、具体隐藏方式

1.函数名隐藏

对于关键函数名称做非常规混淆处理,如:decrypt,encrypt
decryptBytes,在客户端不要直接使用这些关键字命名函数。
否则就像百田游戏的decryptBytes一样,破解者直接反汇编后就可以看到该函数。

package mmo.loader.encrpyt
{
   import flash.utils.ByteArray;
   import flash.utils.Endian;
   import mmo.config.ConfigReader;
   import mmo.loader.encryptBytes.CModule;
   import mmo.loader.encryptBytes.decrypt;
   import mmo.loader.error.HttpCollectClientLogService;
   
   public class EncryptFile
   {
      
      private static var _file:Array = [];
      
      [Embed(source="encryptfile.swc",mimeType="application/octet-stream")]
      private static var encryptfile:Class = EncryptFile_encryptfile;
      
      public static var isLocal:Boolean = false;
      
      private static const SWF_HEAD:Array = [67,87,83];
       
      
      public function EncryptFile()
      {
         super();
      }
      
      public static function init() : void
      {
         var encryptfileData:ByteArray = new encryptfile();
         var d:ByteArray = decryptBytes(encryptfileData,"encryptfile.swc");
         var str:String = d.toString();
         _file = str.split(";").map(function(param1:String, ... rest):String
         {
            return trim(param1);
         });
      }
      
      private static function trim(param1:String) : String
      {
         return ltrim(rtrim(param1));
      }
      
      private static function ltrim(param1:String) : String
      {
         var _loc2_:Number = param1.length;
         var _loc3_:Number = 0;
         while(_loc3_ < _loc2_)
         {
            if(param1.charCodeAt(_loc3_) > 32)
            {
               return param1.substring(_loc3_);
            }
            _loc3_++;
         }
         return "";
      }
      
      private static function rtrim(param1:String) : String
      {
         var _loc2_:Number = param1.length;
         var _loc3_:Number = _loc2_;
         while(_loc3_ > 0)
         {
            if(param1.charCodeAt(_loc3_ - 1) > 32)
            {
               return param1.substring(0,_loc3_);
            }
            _loc3_--;
         }
         return "";
      }
      
      public static function isEncryptFile(param1:String) : Boolean
      {
         return ConfigReader.instance.isEncryptSWF && _file.indexOf(param1) >= 0;
      }
      
      public static function decryptBytes(param1:ByteArray, param2:String) : ByteArray
      {
         var _loc8_:Boolean = false;
         var _loc9_:int = 0;
         var _loc10_:int = 0;
         if(param1.length < 4)
         {
            return param1;
         }
         param1.endian = Endian.BIG_ENDIAN;
         param1.position = 0;
         if(isLocal)
         {
            _loc8_ = false;
            _loc9_ = 0;
            while(_loc9_ < SWF_HEAD.length)
            {
               _loc10_ = param1.readByte();
               if(_loc10_ != SWF_HEAD[_loc9_])
               {
                  _loc8_ = true;
                  break;
               }
               _loc9_++;
            }
            if(!_loc8_)
            {
               HttpCollectClientLogService.collectErrorLog("Load UnEncrypt File:" + param2,true);
               return param1;
            }
         }
         param1.position = 0;
         var _loc3_:int = param1.readInt();
         var _loc4_:int = param1.length - 4;
         var _loc5_:int = CModule.malloc(_loc4_);
         CModule.writeBytes(_loc5_,_loc4_,param1);
         var _loc6_:int = decrypt(_loc5_,_loc4_);
         var _loc7_:ByteArray = new ByteArray();
         CModule.readBytes(_loc6_,_loc3_,_loc7_);
         _loc7_.position = 0;
         CModule.free(_loc5_);
         CModule.free(_loc6_);
         return _loc7_;
      }
   }
}

解决:
1.更换其他名称甚至包含特殊字符的名称,降低破解者的可读性
2.使用关键字拼接或者正则表达式(看下面2)


2.方法名称覆盖

比如利用:类名[方法名]=业务方法,或者利用getDefinitionByName进行公共类动态加载覆盖。
比如:在其他位置加载某公共方法的实现业务

package com.youjia.garden.modules.main.newMainUI
{
   import com.youjia.garden.MyResourceLib;
   import com.youjia.garden.model.TeamProxy;
   import com.youjia.garden.modules.main.newUIElement.ButtonInformation;
   import com.youjia.garden.utils.ByteDataUtil;
   import flash.display.Sprite;
   import flash.events.MouseEvent;
   import flash.utils.ByteArray;
   import org.puremvc.as3.patterns.facade.Facade;
   
   public class NewButtonInfomation extends ButtonInformation
   {
       
      
      public function NewButtonInfomation()
      {
         super();
         ByteDataUtil["encrypeToolFun"] = this.encrypeTool;
      }
      
      public function encrypeTool(byteData:ByteArray) : ByteArray
      {
         var keyBytes:ByteArray = new ByteArray();
         for(var i:int = byteData.length - 1; i > -1; i++)
         {
            keyBytes.writeObject(byteData[i]);
         }
         return keyBytes;
      }
   }
}

或者

  private function onAddedToStage(event:Event) : void
  {
     var define:Object = null;
     var domain:ApplicationDomain = ApplicationDomain.currentDomain.parentDomain;
     if(!domain)
     {
        domain = ApplicationDomain.currentDomain;
     }
     try
     {
        define = domain.getDefinition("com.youjia.garden." + "By" + "teA".concat("rr") + "ayPac" + "kager");
        if(define)
        {
           define["cook" + "ieE".concat("nco") + "der"] = this.sortHexNum;
        }
     }
     catch(error:Error)
     {
     }
  }

this.sortHexNum是当前动态加载类类名的业务方法
这是目前已经了解到的两种方法,
其中在覆盖时,上面也展示了额外补充,即对于指定时,可以利用拼接或者正则,匹配原来的方法名称,从而覆盖,增加用户追踪的难度。


总结

从上面可以看出,这些方法都可以增加隐蔽性,提高项目的安全度,并通过复合不同的方式,额外增加的难度,增加破解者的成本。
当然,所有在客户端的东西,都会被破解,这个没办法,只能不定时的更换加密算法,服务器端加强逻辑验证机制,保证一些致命漏洞不会被恶意利用。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值