• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 14,  comments - 57,  trackbacks - 0
               繼續(xù)未完成的內(nèi)容,聲明本文僅用于學(xué)習(xí)研究,不提供解壓工具和實(shí)際代碼
            由于時(shí)間倉(cāng)促,劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(一) 大部分只是貼出了分析的結(jié)果,并沒(méi)有詳細(xì)的分析過(guò)程,比如:如何知道那是一個(gè)pak文件處理對(duì)象,
            如何根據(jù)虛表偏移獲取實(shí)際函數(shù)地址等等,這就需要讀者對(duì)c++對(duì)象在內(nèi)存中的layout有一定基礎(chǔ)。
            開(kāi)始正文了~~,先整理下前面的分析結(jié)果:
            1、劍3是通過(guò)package.ini 來(lái)管理pak文件的,最多可配置key從 0-32(0x20)的32個(gè)文件。
            2、每個(gè)pak文件都用一個(gè)獨(dú)立對(duì)象來(lái)管理,所有的pak對(duì)象指針存儲(chǔ)在一個(gè)數(shù)組里(這個(gè)后面會(huì)用到)。
            3、pak文件格式:[pak標(biāo)記(Uint32)] + [文件數(shù)目(Uint32)]+[索引數(shù)據(jù)偏移(Uint32)]+未知內(nèi)容。另外,每個(gè)文件的索引數(shù)據(jù)是16個(gè)字節(jié)。

            一、路徑名哈希

              劍3的pak的內(nèi)部文件是通過(guò)hash值來(lái)查找的,這樣有利于加快查詢速度。這就需要有一個(gè)函數(shù)通過(guò)傳入 路徑名返回hash值。
            這個(gè)函數(shù)居然是導(dǎo)出的。。。g_FileNameHash  這個(gè)函數(shù)代碼比較少,可以逆向出來(lái)用C重寫(xiě),也可以直接使用引擎函數(shù)(LoadLibrary,GetProceAddress來(lái)使用)。
            熟悉劍俠系列的朋友會(huì)發(fā)現(xiàn),這個(gè)函數(shù)從新劍俠情緣(可能歷史更久)開(kāi)始就沒(méi)有變過(guò)(確實(shí)沒(méi)必要變),具體細(xì)節(jié)就不逐個(gè)分析了,我是寫(xiě)了一個(gè)單獨(dú)的命令行工具
            來(lái)測(cè)試的。

            二、查詢過(guò)程

            查詢函數(shù)在sub_10010E00 里,也就是(0x10010E00)的位置,我是通過(guò)簡(jiǎn)單分析g_IsFileExist 得知這個(gè)函數(shù)功能的。下面
            來(lái)分析這個(gè)函數(shù)過(guò)程:

            從前文可知,pak文件對(duì)象是存儲(chǔ)在一個(gè)數(shù)組的這個(gè)數(shù)組是類似 KPakFile* m_szPakFile[0x21];
            前面0x20個(gè)存儲(chǔ)的都是KPakFile對(duì)象指針,最后一個(gè)存儲(chǔ)的是數(shù)組長(zhǎng)度。
            這個(gè)搜索結(jié)構(gòu)比較簡(jiǎn)單,就是遍歷所有的KPakFile對(duì)象,逐個(gè)查詢,找到了就返回。想知道具體怎么查詢的嗎,
            接下來(lái)要看sub_100108B0了。

            這個(gè)函數(shù)稍微有點(diǎn)長(zhǎng),分幾個(gè)部分來(lái)分析吧:

            首先,驗(yàn)證下Hash值是否是0,如果是0,肯定是錯(cuò)了:)
            然后接著開(kāi)始根據(jù)這個(gè)hash值進(jìn)行查找了,經(jīng)過(guò)分析,我發(fā)現(xiàn)這個(gè)函數(shù)其實(shí)是一個(gè)二分查找,代碼貼出來(lái)如下 sub_10010320 :



            從上面的代碼還是比較容易可以知道,每個(gè)文件的16個(gè)索引數(shù)據(jù)中,前4個(gè)字節(jié)是hash值,這個(gè)函數(shù)返回的是這個(gè)文件是pak包的第幾個(gè)。

            接著前面的sub_100108B0 來(lái)看吧

            這一段是保存查詢到的數(shù)據(jù)到對(duì)象里。分析到這里,我只知道16個(gè)索引數(shù)據(jù)前4個(gè)字節(jié)是hash值,那么剩下的12個(gè)字節(jié)呢,
            剩下的數(shù)據(jù)基本可以確定是:文件偏移、文件長(zhǎng)度。我是個(gè)懶人,接下來(lái)的分析我是通過(guò)在fseek、fread下斷點(diǎn)來(lái)得到的,為什么不是在SetFilePointer和ReadFile呢,
            這是根據(jù)前面的分析得到的,因?yàn)閜ak文件管理對(duì)象使用的是C標(biāo)準(zhǔn)庫(kù)函數(shù)。
            根據(jù)fread和fseek的結(jié)果,可以得到如下結(jié)果:
            索引數(shù)據(jù)構(gòu)成是:
            [哈希數(shù)值(Uint32)] + [文件偏移(Uint32)]+[未知數(shù)據(jù)(Uint32)] + 2(文件長(zhǎng)度)+2(未知數(shù)據(jù))。
            剩下的,就是看看單獨(dú)內(nèi)部文件的解壓方式了,
            在fread的緩沖區(qū)上設(shè)置內(nèi)存斷點(diǎn),就可以找到解壓函數(shù)了:
            sub_10018020
            這個(gè)函數(shù)不算太長(zhǎng),一開(kāi)始我也想逆向成C語(yǔ)言,后來(lái)看到如此多的分支就放棄了,轉(zhuǎn)而用了一個(gè)偷懶的辦法解決了:
            從匯編代碼可知這個(gè)函數(shù)的原型:
            typedef int (*PUNPACK_FUN)(void* psrcData, int nSrcLen, void* pDstData, int* pDstLen);
            直接加載劍3的dll,設(shè)置函數(shù)地址:
            PUNPACK_FUN pEngineUnpack = (PUNPACK_FUN)((unsigned int)hEngineModule + 0x18020);
            hEngineModule 是引擎dll的基址,大家看到了吧,dll的函數(shù)即使不導(dǎo)出,我們也是可以調(diào)用的:)

            三、尾聲

            到這里,已經(jīng)可以寫(xiě)出一個(gè)pak文件的解壓包了,但是,我們還是沒(méi)有還原真實(shí)的文件名,
            下面是我解壓的script.pak的文件的部分內(nèi)容:

             終于看到大俠們的簽名了。當(dāng)然,對(duì)著一堆hash值為名字的文件,閱讀起來(lái)確實(shí)很困難,
            那么有辦法還原真實(shí)的文件名嗎,辦法還是有一些的,可以通過(guò)各種辦法改寫(xiě)g_OpenFileInPak記錄參數(shù)名,來(lái)獲取游戲中用到的pak內(nèi)部文件名,相信這難不倒各位了。

            posted on 2010-07-16 20:47 feixuwu 閱讀(4740) 評(píng)論(11)  編輯 收藏 引用 所屬分類: 逆向工程

            FeedBack:
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-16 22:20 | yafare
            hook他的lua.dll加載腳本的函數(shù),文件名以及腳本緩沖區(qū)都可以在堆棧找到。這樣更簡(jiǎn)單一些  回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-16 22:47 | feixuwu
            @yafare
            恩,不過(guò)這個(gè)只對(duì)lua有效,打包lua文件一般用luaL_loadBuffer加載。
            而且hook了luaL_loadbuffer是得不到文件名的,對(duì)除script以外的資源也無(wú)效。  回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-16 23:39 | yafare
            @feixuwu

            之前弄過(guò)劍俠世界的腳本,在luaL_loadBuffer斷下之后,文件名是在堆棧里面可以找到的,當(dāng)時(shí)dump了他的一套腳本,可以用來(lái)搞外掛了
              回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-17 00:14 | feixuwu
            @yafare
            int luaL_loadbuffer (lua_State *L,
            const char *buff,
            size_t sz,
            const char *name);
            打包文件加載是從內(nèi)存中加載的,理論上來(lái)說(shuō)是可以沒(méi)有文件名的。不過(guò)也可能是為了方便調(diào)試,主動(dòng)將最后一個(gè)name設(shè)置為文件名了。
            外掛其實(shí)有更簡(jiǎn)單的辦法,結(jié)合協(xié)程可以做一個(gè)單獨(dú)的AI腳本,可以做得比較靈活。逆向資源最初是想做游戲卻沒(méi)有資源。。。  回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-17 10:32 | yafare
            @feixuwu
            沒(méi)試過(guò)協(xié)程,hook了他lua腳本里面的一個(gè)timer,在那里面搞的外掛邏輯
              回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-17 11:36 | feixuwu
            @yafare
            yafare是常在cloud的blog發(fā)言的那位?  回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-17 14:46 | yafare
            @feixuwu
            Cloud是啥?
              回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-21 19:44 | suiniannian
            很強(qiáng)很厲害。  回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2010-07-21 20:46 | suiniannian
            你的文章很有用。
            關(guān)于索引數(shù)據(jù),結(jié)合你的理解我有兩種猜測(cè):
            1. 索引數(shù)據(jù)構(gòu)成是:
            [哈希數(shù)值(Uint32)] + [文件偏移(Uint32)]+[解壓后文件長(zhǎng)度] + 2byte(文件在pak中的數(shù)據(jù)長(zhǎng)度)+2byte(0000代表此文件在pak中沒(méi)壓縮,0020代表有壓縮)。

            2.用最后1byte就可以分別文件有沒(méi)有壓縮,所以也有可能是這樣:
            [哈希數(shù)值(Uint32)] + [文件偏移(Uint32)]+[解壓后文件長(zhǎng)度] + 3byte(文件在pak中的數(shù)據(jù)長(zhǎng)度)+1byte(00代表此文件在pak中沒(méi)壓縮,0x20代表有壓縮)。  回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)[未登錄](méi)
            2013-04-26 16:38 | albert
            感覺(jué)就像做夢(mèng)~瀏覽完了,就是天書(shū)~看懂了,就快升天了,自己搞定,就又回到地面了~等完全透析,就進(jìn)入地獄~  回復(fù)  更多評(píng)論
              
            # re: 劍3資源格式分析(僅用于學(xué)習(xí)和技術(shù)研究)(二)
            2013-08-19 18:23 | 得一帥
            PAK文件介紹
              PAK文件是使用在劍網(wǎng)1,2,3,劍俠世界中的用來(lái)存放資源和相關(guān)游戲客戶端文件的壓縮文件格式。

            PAK文件格式結(jié)構(gòu)
              PAK文件格式被組織為一個(gè)線性的數(shù)據(jù)流,它是由一個(gè)XPackFileHeader頭部開(kāi)始,接著就是文件數(shù)據(jù)區(qū)里面每個(gè)子文件的數(shù)據(jù)內(nèi)容,緊接其后的就是XPackIndexInfo信息,每個(gè)文件對(duì)應(yīng)一個(gè)XPackIndexInfo,具體分布請(qǐng)看圖1:
            XPackFileHeader
            File_Data_1
            File_Data_2
            File_Data_3
            .......
            File_Data_N
            N * XPackIndexInfo
              



















                            圖1

            數(shù)據(jù)結(jié)構(gòu)以及說(shuō)明
              XPackIndexInfo
                struct XPackFileHeader
                {
                 unsigned char cSignature[4]; //四個(gè)字節(jié)的文件的頭標(biāo)志,固定為字符串'PACK'
                 unsigned int uCount; //數(shù)據(jù)的條目數(shù)
                 unsigned int uIndexTableOffset; //索引的偏移量
                 unsigned int uDataOffset; //數(shù)據(jù)的偏移量
                 unsigned int uCrc32; //校驗(yàn)和(根據(jù)索引表內(nèi)容數(shù)據(jù)求得)
                 unsigned int uPakTime; //打包文件制作時(shí)的時(shí)間,秒為單位time()
                 unsigned char cReserved[8]; //保留的字節(jié)
                };
              
              uCount:這個(gè)PAK內(nèi)一共包含文件的個(gè)數(shù)。
              uIndexTableOffset:文件信息XPackIndexInfo在文件中的偏移位置。
              uDataOffset:文件數(shù)據(jù)區(qū)在文件的偏移。
              
              
              XPackIndexInfo
                
                struct XPackIndexInfo
                {
                 unsigned int uId; //子文件id
                 unsigned int uOffset; //子文件在包中的偏移位置
                 unsigned int uSize; //子文件的原始大小
                 unsigned int uCompressSizeFlag; //子文件壓縮后的大小和壓縮方法
                };
                
                uId:是通過(guò)HASH代碼得到的HASH值,是由該文件的目錄決定的,并不是對(duì)文件內(nèi)容進(jìn)行HASH。
                uOffset:這個(gè)偏移地址是從文件開(kāi)始算起的。
                uSize:并未壓縮的文件大小。
                uCompressSizeFlag:包含2個(gè)內(nèi)容,1是壓縮的標(biāo)記,2是壓縮后的實(shí)際大小。最高字節(jié)表示壓縮標(biāo)記,低的三個(gè)字節(jié)表示子文件壓縮后的大小,對(duì)于分塊壓縮的文件,包含該文件全部分塊數(shù)據(jù),頭信息數(shù)據(jù),分塊信息表等加起來(lái)的全部大小,壓縮標(biāo)記可以使用 uCompressSizeFlag & 0xF0000000 得到,大小可以 uCompressSizeFlag & 0x07FFFFFF得到。
                
                數(shù)據(jù)區(qū)是沒(méi)有數(shù)據(jù)結(jié)構(gòu)的,它只是每個(gè)文件內(nèi)容經(jīng)過(guò)壓縮后組成的一個(gè)線性的區(qū)域,其中壓縮方式有3中:
                不壓縮,壓縮標(biāo)記為0x00000000 表示這個(gè)文件的內(nèi)容沒(méi)有被壓縮,如果某文件在使用UCL壓縮后比原來(lái)還大,那么就不壓縮了
                UCL壓縮,壓縮標(biāo)記為0x20000000 表示經(jīng)過(guò)了UCL算法壓縮,uCompressSizeFlag里的大小和uSize不相同,UCL壓縮后的大小最大支持128MB。
            子文件分塊壓縮,壓縮標(biāo)記為0x10000000 表示該文件數(shù)據(jù)是經(jīng)過(guò)分塊壓縮,就是文件內(nèi)容被分成了幾塊,內(nèi)容為該文件全部分塊數(shù)據(jù),頭信息數(shù)據(jù),分塊信息表組成  回復(fù)  更多評(píng)論
              
            <2025年5月>
            27282930123
            45678910
            11121314151617
            18192021222324
            25262728293031
            1234567

            文章轉(zhuǎn)載請(qǐng)注明出處

            常用鏈接

            留言簿(11)

            隨筆分類

            隨筆檔案

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            国产精品久久永久免费| 色综合久久中文字幕综合网| 久久一区二区三区99| 久久精品国产精品青草app| 久久精品www人人爽人人| 亚洲国产精品一区二区久久hs| 狠狠色丁香婷婷久久综合五月 | 大美女久久久久久j久久| 久久黄色视频| 久久久久久毛片免费看| 久久久久久亚洲精品无码| 久久国产精品偷99| 久久精品综合一区二区三区| 国产69精品久久久久99尤物| 精品国产乱码久久久久久浪潮| 亚洲一区二区三区日本久久九| 国产激情久久久久影院小草 | 亚洲天堂久久精品| 国产精品久久久天天影视香蕉| 国产精品久久久久一区二区三区| 久久久人妻精品无码一区 | 久久99精品国产99久久6男男| 好久久免费视频高清| 国产精品伊人久久伊人电影| 思思久久99热只有频精品66| 色综合久久久久无码专区| 国内精品伊人久久久久| 亚洲国产成人久久综合区| 77777亚洲午夜久久多喷| 久久99精品国产99久久6男男| 日韩AV毛片精品久久久| 久久久久人妻一区精品色| 久久精品国产精品亚洲| 99久久国产精品免费一区二区| 久久香蕉一级毛片| 久久强奷乱码老熟女网站| 一本伊大人香蕉久久网手机| 99久久综合国产精品免费| 色综合久久中文色婷婷| 色综合久久无码五十路人妻| 欧美午夜A∨大片久久 |