看雪论坛
发新帖
4

[原创]土X视频播放器的swf解密过程

IamHuskar 2014-7-31 16:30 11874
没太多技术含量,主要是普通的分析与实践,大牛莫笑
某视频网站土X的播放器Portalxxx_116.swf下载下来以后用asv打开发现关键的swf被加密了,当前的swf只是一个loader。没办法看到内部的内容,这让我这个一直用修改播放器去广告的小菜来说,简直伤心。
相比于优X ,iqiX的没有加密的swf播放器。土X的加密强度虽然不高,但是绝对能够阻挡很大一部分试图通过修改播放器去广告的行为。

当然作为小菜的我还是要试一试的。

任意打开一个视频播放页面,右键查看源代码
看到最主要的播放器swf文件为

http://js.tuxxxxxx.com/bin/linxxxxx/Portalxxx_116.swf

用下载工具下载下来。打开swf看里面的资源以及as文件,发现完全不符合这个500K的文件大小。

分析以后发现主要有用的的as文件有三个,主要是利用as的bytearray来进行加解密。
1 SWZLoader           主要用来解密的函数
2 playerloader           主要用来加载文件解密等处理
3 playerloader_xxxplayer  加密后的swf数据

先来看2用来加载文件加解密的这个as的主要内容
private function init(_arg1:Event=null):void
{
var _local2:SWZLoader;
var _local3:ByteArray;
removeEventListener(Event.ADDED_TO_STAGE, this.init);
//生成一个SWZLoader解密模块的对象
_local2 = new SWZLoader();
//将playerloader_xxxplayer这个加密后的swf数据块作为bytearray读入local3中
_local3 = ByteArray(new this.tudouPlayer());
//调用解密模块解密字节流
_local2.load(_local3);
//完成后调用onLoadedHlr
_local2.contentLoaderInfo.addEventListener(Event.COMPLETE, this.onLoadedHlr);
}

private function onLoadedHlr(_arg1:Event):void
{
       //将字节流作为一个swf加载运行
         this.mainSwf = (_arg1.target.content as Sprite);
            if (this.mainSwf != null){
                addChild(this.mainSwf);
         ......
};


加载过程了解清楚以后剩下的就是查看SWZLoader的load函数式如何解密的。
看1的SWZLoader类的load函数
public function load(param1) : void
{
           ..................
            if (param1 is ByteArray)
            {
//传入字节码解密,返回解密后的字节码
                _loc_2 = this.decode(param1);

//this.dataByteArray=_loc_2;这句是我自己添加的,用于存解密后的数据,dataByteArray申明一个bytearray的变量就好了

                this.loadBytes(_loc_2);
                return;
            }
            ............................
}
关键的解密过程就是this.decode(param1);




private function decode(param1:ByteArray) : ByteArray
{
//这里看不懂,不过肯定不是在这里返回
            if (int(Capabilities.version.split(/[ ,]+""[ ,]+/)[1]) > 10)
            {
                return param1;
            }
//验证字节流有效性
            if (param1 == null || param1.length < 32)
            {
                return null;
            }
            var _loc_2:* = new ByteArray();
/*生成一个字节流对象_loc_2。为何_loc_2的长度是这么来的呢。
由于SWF文件的开头八个字节是有意义的。
00000000h: 46 57 53 0A 2A 34 0B 00                         ; FWS.*4..
46 57 53 是SWF标记,也有可能是SWC SWZ代表是zlib加密过的 0A是版本 后面四个字节 00 0B 034 2A表示解密后的文件大小
param1[4] | param1[5] << 8 | param1[6] << 16 | param1[7]所以这里是取swf文件大小
 */
            _loc_2.length = param1[4] | param1[5] << 8 | param1[6] << 16 | param1[7] << 24;

//调用Decoder().decode从字节流的param1的位置17开始解密到_loc_2的第八个字节后面
            if (!new Decoder().decode(param1[12], param1, 17, _loc_2, 8, _loc_2.length - 8))
            {
                return null;
            }
//复制swf文件的头八个字节
            var _loc_3:* = 0;
            while (_loc_3 < 8)
            {
                
                _loc_2[_loc_3] = param1[_loc_3];
                _loc_3++;
            }
//70就是ascii F 也就是SWF标记里的F 代表已经被解密过了,如果是Z或者是C表示还是加密的。
            _loc_2[0] = 70;
//修正版本号为 10
            _loc_2[3] = param1[13] > 0 ? (param1[13]) : (10);
//返回解密后的swf字节流
            return _loc_2;
}// end function


后来才知道Decode用的是LZMA算法。这里就懒得再说了。有点麻烦。如果熟悉可以用C写出来。

接下来就是还原这个过程。
首先用avs提取这个playerloader_xxxplayer加密块


用adobe flash cs 5.5新建一个工程,为test.fla添加关联的默认as。也就相当于MAIN函数.
将SWZloader中有用的部分抠出来。这个解密的函数没办法完全反编译过来,我从网上扣了一个。 关键词搜索public class LZMA{ public static function decode应该就可以了。这样SWZLoader基本不用改什么就是完好可用的as,我只是自己添加一些变量,用于获取数据。
现在自己开始写主要的调用as

我用我半桶水的java语言终于还是完成了一个艰难的任务。
public function aaa()
{
			 trace("Hello world!");
			var loa:loader1=new loader1();//所有的过程都放在loader1里面进行
}
class loader1
{
	public function loader1()
	{

			trace("enter");
var ul:URLLoader = new URLLoader(); 
ul.dataFormat = URLLoaderDataFormat.BINARY; 
ul.addEventListener(Event.COMPLETE, onComplete); 
//上面抠出来的bytearray重命名为data.bin作为URLRequest load进来,完成后调用onComplete

ul.load(new URLRequest("data.bin")); 
trace("loaded");

	}
	
	function onComplete(e:Event):void
	{ 
          var ba:ByteArray = (e.target as URLLoader).data; 
		    var _loc_2:SWZLoader = null;
            _loc_2 = new SWZLoader();
            _loc_2.load(ba);
		    var fr:FileReference = new FileReference(); 
//dataByteArray, 是前面我SWZLOADER添加过的变量。
            fr.save(_loc_2.dataByteArray, "player.swf")
	}
}

调试运行一下,就会弹出一个框让你保存player.swf 这个就是解密后的swf文件了。
最后才是真正播放器的庐山真面目啊

上传的附件:
本主题帖已收到 0 次赞赏,累计¥0.00
最新回复 (21)
fujing 2014-7-31 16:33
2
写得不错,我回去试下
4
ycmint 2014-7-31 19:59
3
其实认真想想  lzma 为什么要用,有时候并不一定是为了加密....
4
IamHuskar 2014-7-31 21:17
4
本来swf就是用这个方法压缩的
cjkillyes 2014-8-1 10:26
5
本来swf就是用这个方法压缩的
5
noword_forever 2014-8-1 17:55
6
以前的swf用zlib压缩,新的swf开始用lzma了。
杜晨 2014-8-2 23:34
7
好复杂 看不懂 膜拜大神
枫清淡 2014-9-29 19:59
8
压缩对用户和视频站都有好处,解压缩后的播放器里面还嵌有两个flash
hbcld 2014-10-1 20:16
9
写的挺好的,谢谢
5
荒野无灯 2014-10-2 23:19
10
手机回复mark
asdsugar 2014-11-25 15:18
11
楼主用的什么反编译啊
asdsugar 2014-11-25 15:58
12
我这个反编译渣渣啊,as3搞的跟汇编一样 看不明白 楼主那个看起来好高端的样子
4
IamHuskar 2014-11-25 16:39
13
硕思闪客精灵
asdsugar 2014-11-25 17:14
14
破解版的吗。。方便发给我一份么,我这个不能导出 1875910057@qq.com 谢谢
kxjhcs 2015-4-10 12:25
15
好复杂 看不懂 膜拜大神
求拜师
fzfh 2015-6-28 19:31
16
链接: http://pan.baidu.com/s/1gdu8H1L 密码: yvtp
应该是最新的7.4版的,可用,已测试。
asdsugar 2015-12-8 15:56
17
3Q
tiffanyD 2016-12-2 14:36
18
闪客精灵专业版 :http://wm.makeding.com/iclk/?zoneid=12313
学习破解啊 2017-1-3 10:03
19
求楼主联系方式
黑洛 2017-1-8 15:28
20
其实好多网课也是类似的加密
故人人 2017-8-13 23:33
21
大大你真牛
最早的故人 2017-8-13 23:51
22
返回



©2000-2017 看雪学院 | Based on Xiuno BBS | 微信公众号:ikanxue
Time: 0.015, SQL: 13 / 京ICP备10040895号-17