admin管理员组

文章数量:1608850

0x00 用浏览器打开QQ空间的侠物语,按下F12(开发者工具),点放大镜定位到游戏,看看游戏入口,GameLoader.swf 这个是游戏的入口文件,beta201506191013是版本号

 

0x01 用flash嗅探工具把GameLoader.swf下载下来

 

0x02 GameLoader.swf是一个flash文件,对该文件进行反编译,反编译软件我用的是Sothink SWF Decompiler(硕思闪客精灵)
反编译后主要看看它的AS代码,是如何下载加载资源的

初步分析:zip_load 是个zip压缩库,GameLoader加载资源列表、下载资源,SwfLoader加载下载后的swf文件,SwfEncrypt是对下载后的swf文件加解密的

 

0x03先分析GameLoader.as是如何加载资源列表并下载的

 

0x04根据上面的分析写一个下载资源列表并解密的小程序(PS:自己熟悉什么语言就用什么写,我用C#写的片段)

//下载资源列表文件
public void DownVersionFile()
{
    //下载路径参照 _flashvars["rootURL"] + "config/version" + this._flashvars["ver"] + ".t"
    string verRes = "http://app100645087.imgcache.qzoneapp/app100645087/xwygame/config/versionbeta201506191013.t";

    using (WebClient wc = new WebClient())
    {
        string path = @"C:\" + Path.GetFileName(verRes);
        wc.DownloadFile(verRes, path);
    }
}

//对资源列表进行解密
private void decodeRes(byte[] param1)
{
    byte[] _loc_2 = new byte[param1.Length];
    int _loc_3 = 0;
    var _loc_4 = @"I\'m a big big girl with a big big hole";
    int _loc_5 = 0;
    int _loc_6 = 0;
    int index = 0;

    while (_loc_6 < param1.Length) //参照GameLoder中的Decode解密算法
    {
        if (_loc_3 >= _loc_4.Length)
        {
            _loc_3 = 0;
            _loc_5 = _loc_5 + 1;
            if (_loc_5 >= 40)
            {
                Array.Copy(param1, 40 * _loc_4.Length, _loc_2, index, param1.Length - 40 * _loc_4.Length);
                index += param1.Length - 40 * _loc_4.Length;
                break;
            }
        }

        char[] l4 = _loc_4.Substring(_loc_3, 1).ToCharArray();
        _loc_2[index] = (byte)(param1[_loc_6] - l4[0]);
        index++;

        _loc_6 = _loc_6 + 1;
        _loc_3 = _loc_3 + 1;
    }

    FileStream fs = new FileStream(@"C:\versionbeta201506191013.zip", FileMode.OpenOrCreate, FileAccess.ReadWrite);
    BinaryWriter bw = new BinaryWriter(fs);
    bw.Write(_loc_2);
    bw.Close();
    fs.Close();
}

这里就不用zip库去解压了,直接用解压软件去解压,得到了xml资源列表文件(起初*.t解密后我并没看出是什么文件,用WinHex看了一下文件头才确定是zip文件)


0x05 有了资源列表,再打开浏览器加载下游戏,还是按F12,点NetWork看看都下载了哪些文件

xml资源列表中能找到*.swf 但是没有*.swf.pak,同样能找到*.json *.xml 但是没有*.json.cfg *.xml.cfg,由此分析应该是对这三类文件进行了加密这些文件的解密算法应该也在入口文件中,所以继续分析:GameLoader.as中的translateURL方法是进行xml解析并返回真实的资源路径

 

SwfEncrypt.as中的dealCode方法是进行swf加解密的

 

0x06 根据上面的分析写出对xml文件的解析下载以及swf文件的解密

private Dictionary<string, string> xmlDictionary = new Dictionary<string, string>();

//解析xml资源列表
private void ReaderXml()
{
    XmlDocument doc = new XmlDocument();
    doc.Load(@"C:\versionbeta201506191013.xml");    //加载Xml文件  
    XmlElement rootElem = doc.DocumentElement;   //获取根节点  
    XmlNodeList fileNodes = rootElem.GetElementsByTagName("file");
    foreach (XmlNode node in fileNodes)
    {
        string path = ((XmlElement)node).GetAttribute("path");
        string md5 = ((XmlElement)node).GetAttribute("md5");

        xmlDictionary.Add(path, md5);
    }

    DownResFile();
}

//下载资源文件(这里只是简单的写了下,没用异步和多线程)
private void DownResFile()
{
    foreach (KeyValuePair<string, string> pair in xmlDictionary)
    {
        string path = pair.Key;
        path = path.Replace(".", pair.Value + ".");

        if (path.Substring((path.LastIndexOf(".") + 1)) == "swf")
        {
            path = path + ".pak";
        }

        using (WebClient wc = new WebClient())
        {
            string rootURL = "http://app100645087.imgcache.qzoneapp/app100645087/xwygame/";
            string verRes = rootURL + path;
            string savePath = @"C:\" + Path.GetFileName(verRes);
            wc.DownloadFile(verRes, savePath);
        }
    }
}

//解密*.swf.pak
private void swfDealCode(byte[] param1, string fileName)
{
    byte[] _loc_3 = new byte[param1.Length];
    int _loc_4 = 0;
    int _loc_5 = 0;
    int _loc_6 = 0;
    int index = 0;
    string KEY = "helloworld";

    while (_loc_6 < param1.Length)
    {

        if (_loc_4 >= KEY.Length)
        {
            _loc_4 = 0;
            _loc_5 = _loc_5 + 1;
            if (_loc_5 >= 50)
            {
                //_loc_3.writeBytes(param1, 50 * KEY.length, param1.length - 50 * KEY.length);
                Array.Copy(param1, 50 * KEY.Length, _loc_3, index, param1.Length - 50 * KEY.Length);
                index += param1.Length - 50 * KEY.Length;
                break;
            }
        }

        //_loc_3.writeByte(param1[_loc_6] - KEY.charCodeAt(_loc_4));
        char[] l4 = KEY.Substring(_loc_4, 1).ToCharArray();
        _loc_3[index] = (byte)(param1[_loc_6] - l4[0]);
        index++;

        _loc_6 = _loc_6 + 1;
        _loc_4 = _loc_4 + 1;
    }

    FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite);
    BinaryWriter bw = new BinaryWriter(fs);
    bw.Write(_loc_3);
    bw.Close();
    fs.Close();
}

 

0x07 用Sothink SWF Decompiler(硕思闪客精灵)可以把swf里面的图片资源导出来

需要注意的是从形状里面导出的图片是svg格式,可以用ImageMagick Display中的convert.exe命令行工具转换成png

新创建个文本文件把下面的内容保存进去,后缀名改为bat;(%path%; 后面的是convert.exe文件的路径 例如 C:\Users\UserName\Desktop\Convert )

@echo off
#convert.exe文件所在路径
path %path%;

for /f "usebackq tokens=*" %%d in (`dir /s /b *.svg`) do (
convert.exe "%%d" "%%~dpnd.png"
)
pause

把上述文件 放到资源文件夹的根目录,它会自动把包括子目录里的svg转换成png

 

资源提取源码

链接:http://pan.baidu/s/1nv8nbw1 密码:t2z3

本文标签: 物语美术资源页游