Flash之swf文件的加密与破解

Flash之swf文件的加密与破解

Flash,现在叫animate,风靡于PC网络时代,整个时代弥漫着无数经典的作品,现在是移动互联时代H5逐渐代替了她的位置。逐渐地,flash变成了制作H5的一个工具。


深呼吸一下……顺便追忆前世今生
好了,闲言少叙,且看flash的swf文件。
swf文件是一种公开标准的文件格式,一般由flash软件发布。
文件格式(SWF)详细说明书
https://blog.csdn.net/yjfkpyu/article/details/4032202
http://www.360doc.com/content/15/0112/12/9200790_440101266.shtml


用其开发软件可以承载交互丰富的多媒体内容。
为了保护软件内容不被轻易的盗取,一般都要进行加密。



一般swf加密方法,都是按照一定的算法将文件的bytearray进行变换,得到一个player无法识别的文件。
player播放时需要按照算法逆运算,就可以得到swf文件然后进行装载播放了。
说白了加密解密就是玩一个字符串的游戏。


常用的操作如下
异或、替换或增加数据、改变字节顺序、base64转换、压缩等

本来嘛,内容既要隐藏又要展现就是矛盾的。

软件可以扫描内存从中提取展示的swf文件。
不管怎样内容还是要给人看的,所以再怎么变换也有让别人拿走的机会。
因此这些加密的手法也只能做到在一定程度上的防备。


对于一个经验多一点的闪客来说,想要的都能想办法拿到。
声明:本人遵纪、守法、讲道德,且一贯的尊重所有软件的知识产权。反编译代码仅为学习研究之目的,并无恶意。


下面举个栗子:
案例1

base64+增加数据实施对文件的加密。                
反编译代码

package 
{


    import com.hurlant.util.*;
    import flash.utils.*;
    
    public class ByteCodeMix extends Object
    {
        public function ByteCodeMix(arg1:String)
        {
            super();
            if (arg1) 
            {
                _key = arg1 + innerKey;
            }
            else 
            {
                _key = innerKey;
            }
            endkb = new flash.utils.ByteArray();
            endkb.writeUTFBytes(endkey);
            return;
        }

        public function enCodeMix(arg1:flash.utils.ByteArray, arg2:int):flash.utils.ByteArray
        {
            var loc3:*;
            (loc3 = new flash.utils.ByteArray()).writeUTF(_key);
            var loc4:*;
            (loc4 = new flash.utils.ByteArray()).writeInt(loc3.length);
            loc4.writeBytes(loc3);
            loc4.writeBytes(arg1);
            loc4.writeBytes(endkb);
            var loc5:*;
            (loc5 = new flash.utils.ByteArray()).writeBytes(loc4, 0, arg2);
            var loc1:*=com.hurlant.util.Base64.encodeByteArray(loc5) + _key;
            var loc2:*;
            (loc2 = new flash.utils.ByteArray()).writeUTF(loc1);
            loc2.writeBytes(loc4, arg2);
            return loc2;
        }

        public function deCodeMix(arg1:flash.utils.ByteArray):flash.utils.ByteArray
        {
            arg1.position = 0;
            var loc3:*=(loc3 = arg1.readUTF()).replace(_key, "");
            var loc2:*=com.hurlant.util.Base64.decodeToByteArray(loc3);
            var loc1:*=new flash.utils.ByteArray();
            arg1.readBytes(loc1, 0, arg1.bytesAvailable);
            var loc4:*;
            (loc4 = new flash.utils.ByteArray()).writeBytes(loc2);
            loc4.writeBytes(loc1);
            var loc6:*=new flash.utils.ByteArray();
            loc4.position = 0;
            var loc5:*=loc4.readInt();
            loc4.position = loc4.position + loc5;
            loc4.readBytes(loc6, 0, loc4.length - loc5 - 4 - endkb.length);
            return loc6;
        }

        private var _key:String;

        private var innerKey:String="iZSBGbGV4IDQgQXBwbGljYXRpb248";

        private var endkey:String="lt_xggh_fla.sprite185copy3_89";

        private var endkb:flash.utils.ByteArray;
    }


解密方法
 

loc1 = (loc3 = new ByteCodeMix("RpdGxlPjxkYzpkZXNjcmlwdG")).deCodeMix(flash.net.URLLoader(arg1.target).data as flash.utils.ByteArray);

分析:
能看出 有用的加密的文件结构是
--------------------------------------------------------------------------
| RpdGxlPjxkYzpkZXNjcmlwdGiZSBGbGV4IDQgQXBwbGljYXRpb248 |
--------------------------------------------------------------------------
| swf数据                                                                                          |
--------------------------------------------------------------------------
| lt_xggh_fla.sprite185copy3_89                                                         |
--------------------------------------------------------------------------

扫描二维码关注公众号,回复: 8873290 查看本文章

案例2

改变顺序反编译代码

package 
{


    import flash.display.*;
    import flash.events.*;
    import flash.net.*;
    import flash.system.*;
    import flash.utils.*;
    
    public class DecryptLoader extends flash.events.EventDispatcher
    {
        public function DecryptLoader(arg1:String, arg2:String, arg3:Boolean=true)
        {
            super();
            isEncode = arg3;
            _strUrl = arg1;
            _strKey = arg2;
            return;
        }

        public function get getUrl():String
        {
            return _strUrl;
        }

        public function get getKey():String
        {
            return _strKey;
        }

        public function set setUrl(arg1:String):void
        {
            _strUrl = arg1;
            return;
        }

        public function set setkey(arg1:String):void
        {
            _strKey = arg1;
            return;
        }

        private function validKey(arg1:Array):Boolean
        {
            arg1.sort();
            trace(arg1);
            return arg1.every(sequential);
        }

        private function sequential(arg1:*, arg2:int, arg3:Array):Boolean
        {
            return arg1 == arg2;
        }

        public function startLoad(arg1:Function=null):void
        {
            var loc2:*=new flash.net.URLRequest(_strUrl);
            var loc1:*=new flash.net.URLLoader();
            loc1.dataFormat = "binary";
            loc1.addEventListener("complete", handleUrlLoadComplete);
            loc1.addEventListener("ioError", onErr);
            if (arg1 != null) 
            {
                _progress = arg1;
                loc1.addEventListener("progress", arg1);
            }
            loc1.load(loc2);
            return;
        }

        private function onErr(arg1:flash.events.IOErrorEvent):void
        {
            dispatchEvent(new flash.events.Event("LoadFail"));
            return;
        }

        private function handleUrlLoadComplete(arg1:flash.events.Event):void
        {
            if (_progress != null) 
            {
                arg1.target.removeEventListener("progress", _progress);
            }
            var loc1:*=arg1.target.data as flash.utils.ByteArray;
            var loc4:*=new flash.utils.ByteArray();
            if (isEncode) 
            {
                if (!decrypt(loc1, loc4)) 
                {
                    dispatchEvent(new flash.events.Event("LoadFail"));
                    return;
                }
            }
            var loc2:*=new flash.display.Loader();
            loc2.contentLoaderInfo.addEventListener("complete", handleByteLoadComplete);
            var loc3:*;
            (loc3 = new flash.system.LoaderContext()).allowCodeImport = true;
            loc3.allowLoadBytesCodeExecution = true;
            loc3.applicationDomain = flash.system.ApplicationDomain.currentDomain;
            if (isEncode) 
            {
                loc2.loadBytes(loc4, loc3);
                bytes = loc4;
            }
            else 
            {
                loc2.loadBytes(loc1, loc3);
                bytes = loc1;
            }
            loader = loc2;
            return;
        }

        private function decrypt(arg1:flash.utils.ByteArray, arg2:flash.utils.ByteArray):Boolean
        {
            var loc4:*=0;
            var loc6:*=0;
            var loc3:*=0;
            if (arg1.length < 2000) 
            {
                return false;
            }
            if (_strKey.length != 20 * 2) 
            {
                return false;
            }
            var loc5:*=[];
            var loc7:*=[];
            loc4 = 0;
            while (loc4 < _strKey.length) 
            {
                loc5.push(_strKey.substr(loc4, 2));
                loc7.push(_strKey.substr(loc4, 2));
                loc4 = loc4 + 2;
            }
            if (!validKey(loc7)) 
            {
                return false;
            }
            var loc2:*=[];
            var loc1:*=new flash.utils.ByteArray();
            loc6 = 0;
            while (loc6 < loc5.length) 
            {
                loc2["byte" + loc6] = new flash.utils.ByteArray();
                arg1.readBytes(loc2["byte" + loc6], 0, 2000 / 20);
                ++loc6;
            }
            arg1.readBytes(loc1);
            loc3 = 0;
            while (loc3 < loc5.length) 
            {
                trace("byte" + loc5[loc3]);
                arg2.writeBytes(loc2["byte" + int(loc5[loc3])]);
                ++loc3;
            }
            arg2.writeBytes(loc1);
            return true;
        }

        private function handleByteLoadComplete(arg1:flash.events.Event):void
        {
            trace((arg1.target as LoaderInfo).loader);
            dispatchEvent(arg1);
            return;
        }
        public var loader:Loader;
        public var bytes:ByteArray;
        private const KEYLENGTH:uint=20;

        private const BUFFERSIZE:uint=2000;

        private var _strUrl:String;

        private var _strKey:String;

        private var _progress:Function;

        private var isEncode:Boolean;
    }
}
}


解密代码

 

var loc1:*=new DecryptLoader(arg1, "0010170918061315121405160704110803021901");
            loc1.addEventListener("LoadFail", loadFail);
            loc1.startLoad();

分析:
很有意思的参数"0010170918061315121405160704110803021901"是0-19的组合
也是打乱顺序的规则。
100个字节为1组,打乱前20组。


 

发布了78 篇原创文章 · 获赞 76 · 访问量 14万+

猜你喜欢

转载自blog.csdn.net/qq_38288618/article/details/85332710
今日推荐