使用IDA靜態分析解密《艦娘Collection》的lua腳本


  好久沒寫東西了,換工作之后忙得一比。你說創業?風太大沒聽清啊看了看以前寫的東西,覺得以前寫得太嚴肅了,從現在開始要輕松一點,要做一名逗逼碼農。

 

  本文不會介紹破解的細節,最終完成破解所編寫的代碼也不會公開。雖然這個游戲非常無恥,但已經上線運營了,我不想被查水表啊。所以,該文僅以這個游戲為例,講一下如何使用IDA靜態分析破解簡單的cocos2dx-lua腳本加密。

 

  對了,這里說的《艦娘Collection》是一個手游,不是那個艦娘,嗯。

 

  為什么我要突然去搞破解呢?事情是這樣的:某天,一個以前的關系很好的美術同事跟我說,他無意中發現一個手游,里面盜用了部分《艦隊Collection》的原畫。然后給我看了提取出來的圖。

  

 

  顯然開發商就是用艦C的原畫,自己稍微潤了下色就用進去了。其實這種事在國內手游圈應該是屢見不鮮的吧,之前有個叫《艦娘國服》的頁游也干過類似的事,不過他們更直接,功能和界面直接就是原版的了。這個是題外話。

 

  他又說,他解包了apk,發現美術資源可以直接拿出來用,但是有很多后綴名是lua的文件,不知道是干啥的,是不是也是圖片?

 

  我說,這是代碼文件,不是圖片的。

 

  他又說,這些文件用記事本打不開,有沒有辦法看看里面寫了什么?

 

  我說,打不開肯定是加密了,你研究這個干啥,想轉行當碼農啊?別和自己青春過不去。

 

  他繼續說,你給破解了看看唄,反正閑着也是閑着。

 

  “另請高明吧,”我說,“我實在我也不是謙虛,我一個U3D前端碼農,怎么就去搞反向工程了呢?” (其實我也挺好奇堂而皇之偷圖的公司,寫出的代碼是什么水准的,但是懶得去折騰)

 

  他又說:你看,那個游戲里面,他們把你太太畫成這樣了:

  

  

  ……

  ……

  ……

  太太!!!!!

  你怎么變成死魚眼了!!!!!!

  

  而且這個神似曾哥的表情是鬧哪樣!!!!!!!!

 

  

  I AM ANGRY!

  當時我就念了兩首詩:“苟利太太破解以,豈因禍福避趨之”。然后找那位同事要來了APK。

  

  其實一開始的時候我也不敢保證能破解出來,我對反向工程基本上是只懂一點點雞毛蒜皮,IDA也用得不熟。但是裝出來的逼就像潑出去的水啊,強行上吧。想想曾經有人200人口飛龍狗毒爆打120人口都輸了,我作為一個新手怎么就不能破出來呢~

 

  在破解之前還是容我先裝上看看這游戲到底是個什么玩意。裝上之后:

  

  艾瑪這App名和圖標真夠直接的,還有個“二次元”的角標。

  

 

  點進去,喲呵還有新手引導呢(而且這引導到后面還有bug,在不合時宜的時候彈出來,或者錯位。為了節約篇幅后面不截圖了)

  然后就是看電影一樣開打了,全自動,尼瑪四傻打對面雷爺太太和北方,居然還贏了???

  接下來是選擇關卡,媽的還有對話啊,居然是用的艦C的語音,更牛逼的是居然用那些語音組成了劇情!

  雖然全自動戰斗的設定和原作一致,但是特效要好看很多啊~打起來的時候的動態也比原作多太多了,看着都比較爽。 

  然后不知不覺就打到第二張圖了……

 

  等等……

 

  我特么不是要破解他們的腳本么,怎么就玩上了還玩得挺嗨?

        

  好吧,關閉游戲,開始破解。先看看apk。直接解壓。在assets/src下面就是所有的lua腳本了(順便打開res下面看了看原畫,簡直……):

  

  

  這是cocos2dx-lua(也可能是quick-cocos2dx)做的啊,真是令人懷念的東西。雖然我只用過純C++的cocos,lua的還沒碰過。

 

  用記事本打開Lua文件的話,可以看到共同點是使用jts開頭:

     

   

  按照常理,解密Lua的邏輯就在編譯后的so文件里面了。lib\armeabi下面有兩個so,一個100多K,一個10多M,那么肯定大的就是正主。小的那個百度了一下名字,似乎是某個銀行的SDK?不管了。接下來分析so文件。祭出神器IDA打開SO文件,可以看到里面cocos自己的類都沒有CC的開頭,說明是3.x的:

  

 

  因為明確了這個游戲是cocos做的,所以看IDA生成的反匯編C代碼有原版對照了。找了下硬盤,以前寫EasyLive時的3.2還在,cocos new一個lua工程輔助分析。依稀記得在C++版的cocos中,如果要讀取加密的pvr.ccz圖片,一般是在AppDelegate::applicationDidLunchFinished中進行的。於是打開cocos工程中的該方法,在這里就是設置XXTEA加密參數的部分:

  

 

 

  然后在IDA中搜索這個方法,F5生成C++代碼,對比一下看:

  

  

  是不是非常相似,而且看到了兩段關鍵的字符串?在cocos工程中,LuaStack::luaLoadBuffer里面做了XXTEA解密的操作,心中想:看來這波要解密出腳本輕而易舉啊!研發團隊根本不敢說什么,復雜的加密算法也沒有……哎呀奶不死的,媽的老子是專業程序員好嗎?專業程序員,這種代碼都看不懂啊?這怎么奶死嘛!有IDA的情況下怎么會解不出你告訴我,直接復制代碼都解出來了。開新項目穩破解,復制代碼也破了,不可能失敗的,不可能的……

  

  於是我把cocos中的xxtea.h、xxtea.c提出來開一個控制台工程,然后照着前面的參數對腳本進行解密試試。結果是爆炸了,根本解不出。很明顯的,代碼中設置的xxteaSign是一個比較長的字符串,而腳本中的簽名只有三個字符(jts)。所以,這個游戲中對腳本的解密不是直接使用xxtea算法的,甚至可能根本就沒有使用xxtea。(小色:IDA騎臉是你自己玩得菜,跟我有什么關系)

 

  因為cocos在讀取lua的時候必然要經過LuaStack::luaLoadBuffer方法。所以在IDA中打開LuaEngine::executeScriptFile,一路跟蹤進去,最后進到了LuaStack::luaLoadBuffer。把邏輯整理一下就是:

  

 

  整理的時候我不小心掉進坑里掙扎了半天。strcmp和strncmp這兩個函數,字符串相等返回0,不相等返回1。因為我用C#習慣了,所以直接以為相等返回1(true),用XXTEA搞了半天沒搞出來……

  

  分析一下加密后的腳本內容,這里會走使用BlowFish解密數據的流程,並沒有使用XXTEA,所以自己把自己奶死了……接下來得照着IDA代碼的算法寫一個解密的工程。有些變量看着不舒服,可以單擊選中變量,然后按N鍵,就可以重命名變量了。寫好之后,處理src/main.lua文件試試:(這個文件是cocos生成的,直接放出來也無所謂了)

  

 

  漂亮!一個文件解出了,是不是其他文件也可以用這一套來解密呢?

 

  在cocos工程中查找LuaStack::luaLoadBuffer的所有引用,發現它在cocos2dx_lua_loader中被調用了一次;再查找cocos2dx_lua_loader,在LuaStack::init中有設置該回調的代碼。所以可以肯定,這里就是Lua層調用腳本的入口了。在IDA中查找對應的地方,也是一樣的,說明他們沒有做特殊處理,所有的Lua腳本讀取的時候,都會走LuaStack::luaLoadBuffer進行解密。所以剛才寫的解密工程對所有的lua腳本都可用。通過分析IDA代碼,可以分析出他們的腳本是這么個文件格式:(一個格子表示一個字節)

  

 

  於是可以寫一個GUI,將所有的腳本解密了。GUI想怎么做都可以,我用的C#調用dll的方式。

  

  

  看了下代碼,很意外的是對規范比較注重,從游戲體驗上,細節處理比較好,也不像小公司的作品。那么是出自哪個公司之手呢?代碼中看到了“武將”等詞匯,難道是一個換皮游戲?

 

  再吐槽一下C++層的代碼。IDA中可以看到很多加了j_j_前綴的底層方法,比如這個:

  

 

  點進去:

   

 

  再點進去:

   

  

 

  其實這次破解說不上是用了什么牛逼的技術,完全就是參照着cocos源生項目,然后跟着IDA反匯編出來的代碼分析。大牛們看了勿噴。

 

  不過我覺得我還是捍衛了深海提督的尊嚴!

 

  最后說一下如何避免自己的項目被這種方式攻破。

 

  一般來說可以對so文件加殼,使IDA打開這個文件的時候,就報錯退出;或者修改一下加密類的名字,這樣破解者就找不到你用的什么方式加密了,拿着密鑰也沒用(不過費點心思還是可以把IDA中的代碼整理出來當解密模塊用的);再或者使用更高級的加密方式,但是別人可以用動態調試直接hook luaL_loadbuffer拿到解密后的腳本……

 

  加密方法有一千種,解密方法更有一萬種,如何有效保護自己項目的資源是一個值得研究的問題。

 

  至於對這個游戲的開發商還有沒有什么想說的呢?——“我今天得罪了你們一下!”

 

  如果說還有一句的話,那應該是:——“別抄襲,做個有骨氣的開發商。多花點功夫在原畫上,至少有機會可以像戰艦少女一樣成功,而抄襲,注定一輩子上不了台面。”

 

  很慚愧,就做了一點微小的工作,謝謝大家!

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM