破解TexturePacker加密資源

 最近我們要開一個新項目,UI與交互打算借鑑當前正火的《聖火英雄傳》,程序開發爲了和美術製作並行,打算用聖火的資源暫代使用。我解壓聖火apk,發現用TexturePacker命令行無法把它的pvr.ccz資源文件轉成png,稍微瞭解一下,才知道TP提供了加密功能。我最近做Unity開發,只需要TP最基本的打圖集功能,所以一直用v2.4.5,很久沒有升級了,out了。


    

    聖火資源加密了,沒有密鑰無法打開


    美術同學可以先截圖或畫草圖給程序用,但是,截圖/草圖跟原圖比:大小規格不對,質量差,圖元疊在一起,也會缺漏很多。不說耗費美術大量精力做繁重的體力活,這樣做出的東西也會“慘不忍睹”,等正式美術資源來了,所有美術顯示也都需要程序重新調整,這是不小的工作量。所以,最好的方法是研究破解聖火的加密資源。工程師的工作就是減小人的勞動,提高生產效率。


    動態庫注入與API攔截

    開始時,我心裏一點底兒也沒有,因爲我是開發遊戲的,從來沒做過破解。僅有的一點相關經驗是幾年前看《Windows核心編程》時用DLL注入和API攔截,做過一些遊戲的反外掛工作。幾年沒做PC開發,具體實現早忘光了,只記得大致原理是通過注入自己的DLL到目標進程,劫持某些API,替換成自己的實現。


    android內核是基於linux的,我想linux下是否也可以通過注入攔截API呢?只要能劫持API,就能破解。google "linux + inject",linux下果然也可以注入,更進一步發現有人已經開源了自己寫的注入庫,LibInject,核心的系統API是ptrace,還有幾個操作動態鏈接庫的API,dlopen、dlsym、dlclose、dlerror。注入之後,就是劫持,遍歷got表,找到接口的地址然後替換成自己寫的接口即可。


    注入和劫持都ok之後,我試着劫持printf,替換成自己的函數,成功,我心裏對破解有底了。下面是一些具體的操作過程。


    首先要把手機root,把注入進程和劫持庫拷貝到手機上,比如/data目錄下,adb push命令。如果提示“Permission Denied”,就先把/data掛載(mount),然後改變文件權限(chmod)。


    然後,打開聖火包裏面lib目錄,發現聖火用的是cocos2d-js v2.2開發,去cocos2d-x官方下載v2.2.5。然後,找到加載pvr.ccz的模塊,都在ZipUtils.h/.cpp文件中。

  1. void ZipUtils::ccSetPvrEncryptionKeyPart(int index, unsigned int value)// 設置密鑰的接口  
  2.   
  3. int ZipUtils::ccInflateCCZFile(const char *path, unsigned char **out) // 加載ccz文件的接口  


    我本想劫持設置密鑰的用戶自定義接口:ccSetPvrEncryptionKeyPart,這樣可以直接獲取密碼。但是,從soinfo->symtab中獲取的符號名始終是亂碼,目前我還沒搞明白原因,請知道的朋友指導。我就轉而看ccInflateCCZFile的實現,這個接口會讀取ccz文件的二進制數據,然後根據前四個字節判斷是否合法的ccz文件(“CCZ!”)或者是否加密的ccz文件(“CCZp”),如果是加密的,就解密。接着,調用了libz的解壓縮接口:

  1. int uncompress(Bytef *dest, uLongf *destLen, const Bytef *source, uLong sourceLen);  
    原來ccz也是一種zip壓縮格式。這裏需要用到source和destLen這兩個參數,source是解密出來的ccz文件數據,*destLen是壓縮前的大小。既然如此,我只要把uncompress接口劫持了,就可以破解出資源。ps. 除了劫持uncompress,還可以劫持opengl接口,畢竟所有圖都要送到opengl繪製。


    破解

    看看ccz的文件頭:

  1. /** @struct CCZHeader 
  2. */  
  3. struct CCZHeader {  
  4.     unsigned char   sig[4];             // signature. Should be 'CCZ!' 4 bytes  
  5.     unsigned short  compression_type;   // should 0  
  6.     unsigned short  version;            // should be 2 (although version type==1 is also supported)  
  7.     unsigned int    reserved;           // Reserverd for users.  
  8.     unsigned int    len;                // size of the uncompressed file  
  9. };  

   source是不包含文件頭的,所以需要自己把文件頭填充進去。sig是“CCZ!”,compress_type是0,version是2,reserved是0,len是*destLen。創建一個ccz文件,把文件頭和source寫入。然後,把生成的ccz文件拷回本機,adb pull,“Permission Denied”?chmod。懷着激動地心情用TexturePacker打開,卻報告失敗。然後用Notepad++的Hex Editor打開,轉成16進制,發現文件頭的大小端逆序了。比如version,在大端機器上16進製表示是0x00 02,小端機器上是0x02 02。如果是小端,逆序寫就可以了。改了之後重新生成ccz,成功打開。

    

    解密出來的聖火資源——Activity.pvr.ccz


    文件命名

    劫持uncompress是無法知道文件名的。寫一個文件掃描聖火資源目錄,根據以文件size爲key,文件名爲value。然後,根據文件size做匹配就可以了。因爲文件的size是精確到byte的,一般不會有文件是同樣大小。我檢查了聖火,211個ccz文件,沒有同樣大小的。


    轉png與切圖

    TexturePacker可以直接命令行把ccz轉png,然後再寫一個工具,讀plist切散圖就可以了,可以用CocosStudio,網上也有人用python寫的。至此,我們已經完美的破解了聖火所有的資源,獲得了所有美術資源。

    

    切出來的聖火美術資源散圖


     除了《聖火英雄傳》,還有很多遊戲也是用TexturePacker加密資源,都可以用這個方法破解。爲了避免爭端,暫不放出工具及代碼。


ps. 兩篇相關的操作blog:

查看android進程信息 http://blog.csdn.net/ynnmnm/article/details/38417829

使用adb在電腦和手機間傳文件 http://blog.csdn.net/ynnmnm/article/details/38415221


轉載請註明出處: http://blog.csdn.net/ynnmnm/article/details/38392795。作者:夜風。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章