Android手游apk破解及GooglePlay正版去驗證

之前做了一段時間的安卓手游破解正版驗證工作射沟,總結(jié)一些基本的方法和知識辉懒,便于分享交流愉耙。破解的目的是讓國內(nèi)一些“被閹割”過(無GooglePlay框架)的安卓手機也能暢快地玩兒上GooglePlay上的游戲蔬蕊,所以文章主要討論海外游戲市場下載的apk包如何去除正版驗證。國內(nèi)的手游大部分還是做了防破解工作的奕枝,加殼棺榔、防反編譯等等(此篇不予討論)。大概海外市場的氛圍較好隘道,所以GooglePlay症歇、Amazon商店的游戲基本都可以反編譯成功,頂多加了代碼混淆谭梗、調(diào)用了GP/Amazon的驗證SDK而已忘晤。

適合誰看?

破解初學(xué)者激捏、懂一些編程知識的童鞋(完全不懂編程也可以设塔,只能破解那些只需要替換一些文件/文本的游戲)、以及對apk破解/安全性維護感興趣的童鞋缩幸。

什么是Smali壹置?

先說Dalvik是google專門為Android操作系統(tǒng)設(shè)計的一個虛擬機,經(jīng)過深度的優(yōu)化表谊。雖然Android上的程序是使用java來開發(fā)的,但是Dalvik和標(biāo)準(zhǔn)的java虛擬機JVM還是兩回事盖喷。Dalvik VM是基于寄存器的爆办,而JVM是基于棧的;Dalvik有專屬的文件執(zhí)行格式dex(dalvik executable)课梳,而JVM則執(zhí)行的是java字節(jié)碼距辆。Dalvik VM比JVM速度更快余佃,占用空間更少。

通過Dalvik的字節(jié)碼我們不能直接看到原來的邏輯代碼跨算,這時需要借助如Apktool或dex2jar+jd-gui工具來幫助查看爆土。但是,注意的是最終我們修改APK需要操作的文件是.smali文件诸蚕,而不是導(dǎo)出來的Java文件重新編譯(況且這基本上不可能)步势。

詳細(xì)的Smali語法學(xué)習(xí)可以參考這篇文章:http://blog.csdn.net/lpohvbe/article/details/7981386,里面詳細(xì)介紹了Smali中的數(shù)據(jù)類型背犯、方法調(diào)用等等坏瘩。

此外,反編譯過程中遇到不懂的關(guān)鍵字漠魏,可參考http://pallergabor.uw.hu/androidblog/dalvik_opcodes.html倔矾,非常實用的文檔。

如何去除正版驗證柱锹?

你需要的工具

工欲善其事哪自,必先利其器,反編譯工具很多禁熏,針對點也不同壤巷,本文主要用的是APKIDE(也叫APK改之理,一個類似APK studio的可視化反編譯軟件匹层,內(nèi)部已經(jīng)集成了dex轉(zhuǎn)smali隙笆、dex轉(zhuǎn)jar、重新編譯升筏、簽名撑柔、搜索等功能,推薦使用)您访,其他工具和功能如下:

apktool铅忿,命令行工具,可以decode和build apk文件灵汪,主要用來解析xml等資源文件檀训。

dex2jar,一系列命令行工具享言,能將文件在dex峻凫、jar和smali之間相互轉(zhuǎn)換,反編譯時可以dex轉(zhuǎn)為smali后修改smali代碼览露,再將smali轉(zhuǎn)回成dex荧琼。

jd_guid,可視化工具,將jar文件反編譯為java代碼命锄,便于閱讀代碼邏輯堰乔,至于直接編輯java代碼什么的,你想多了脐恩。

baksmali镐侯,命令行工具,也是用來轉(zhuǎn)換dex和smali文件驶冒。

apksigner苟翻,命令行簽名工具,反編譯重新打包之后用來重新簽名apk只怎。

apk studio袜瞬,類似APK IDE,英文界面身堡,有時候會反編譯失敗而APK IDE不會邓尤,猜想可能是內(nèi)嵌的baksmali之類的版本不一樣或者編碼問題吧。

以上工具在百度贴谎、谷歌上下載都可搜到下載汞扎。

常用方法

通常不能運行的游戲表現(xiàn)有這幾種:

1. 提示未安裝谷歌框架,不能游戲擅这;或者提示谷歌驗證此游戲為盜版(可能你的apk不是從GooglePlay下載而來)澈魄。

2. 提示當(dāng)前賬號并未購買此游戲(同樣,可能此游戲并非GooglePlay上購買后直接下載的)

你打開游戲可能會卡在這樣的頁面:

GooglePlay驗證失敗頁

第一種情況是因為代碼中調(diào)用了Google官方的驗證SDK仲翎,僅驗證游戲是否來自GooglePlay痹扇,而第二種添加了Google賬號驗證,檢查你是否購買了此游戲溯香,這兩種情況都可以通過繞開Google驗證來破解:

去除GooglePlay驗證(可寫成腳本進(jìn)行自動化破解)

最簡單的思路其實是找到代碼中調(diào)用驗證的地方鲫构,將其注釋掉,直接調(diào)用callback函數(shù)(一般此類SDK都是異步返回玫坛,開發(fā)者實現(xiàn)一個帶callback的Listener)中驗證成功的方法结笨,拷貝復(fù)制即可。至于調(diào)用的地方湿镀,一般都在入口Activity類中炕吸,函數(shù)名一般帶有verify、certificate勉痴、auth之類的字樣赫模。這也的確是個可行的辦法,但用這個辦法破解了幾款游戲后發(fā)現(xiàn)游戲之間差異很大蒸矛,你必須針對每款游戲去找調(diào)用入口嘴瓤,太費時了扫外,有沒有規(guī)律性的莉钙、可自動化的方法呢廓脆?

答案是肯定的,既然是SDK進(jìn)行的驗證磁玉,我們只修改SDK內(nèi)的代碼不就好了嗎停忿?只要驗證的結(jié)果每次都返回成功就OK了。按Google文檔上的教程蚊伞,接入驗證使用的是sdk\extras\google\play_licensing下的sdk工程席赂,引入后就一個包:com.google.android.vending.licensing,用APK IDE打開如下:

GooglePlay SDK包結(jié)構(gòu)

其內(nèi)部大致做的事情就是驗證apk簽名时迫,請求Google服務(wù)器檢查驗證是否通過颅停、并得到游戲的擴展數(shù)據(jù)包信息(obb文件名、大小等)掠拳,其中夾雜超時處理癞揉、緩存過期時間等等。

找到了負(fù)責(zé)驗證的sdk包溺欧,修改哪里就可以強制返回成功了呢喊熟?一個是LicenseValidator,負(fù)責(zé)解析Google服務(wù)器返回的responseCode姐刁,另一個是實現(xiàn)Policy接口的類芥牌,負(fù)責(zé)解析從服務(wù)器獲取的額外信息(擴展包文件等)。這里偷了一點懶聂使,沒仔細(xì)研究SDK壁拉,而是找到個市面上比較好用的安卓破解器:幸運破解器(裝在手機上就能直接破解游戲的神器,還能破解內(nèi)購)柏靶,用它破解一款游戲后導(dǎo)出apk弃理,反編譯出smali文件,寫個腳本批量對比前后文件變化宿礁,過濾掉注釋等無用信息得到的就是我們要修改的地方了案铺!總結(jié)后如下:

1. 工程中所有調(diào)用java/security/Signature;->verify的地方,將下一行的

move-result v3

改為

const/4 v3, 0x1

move-result v3的意思是將verify函數(shù)的返回結(jié)果賦值給v3梆靖,我們直接替換成聲明一個值為true的v3變量即可控汉。verify函數(shù)用以驗證簽名,我們在破解后必然要重新簽名返吻,無法保留原有開發(fā)者簽名姑子,所以所有驗證簽名的地方都需要進(jìn)行這一步修改。

2. 實現(xiàn)了Policy接口的類(一般是APKExpansionPolicy和ServerManagedPolicy)中的函數(shù)allowAccess测僵,將函數(shù)開頭的聲明

const/4 v1, 0x0

改為

const/4 v1, 0x1

(其中v1命名不確定街佑,可能叫v0或v2等等)此函數(shù)根據(jù)上次請求結(jié)果和重試次數(shù)判斷是否驗證通過谢翎,v1是默認(rèn)返回值,初始化時為false沐旨,后續(xù)代碼判斷滿足某些條件后將v1賦值為true森逮,函數(shù)退出時必然返回v1。所以我們將v1默認(rèn)值設(shè)為true就相當(dāng)于默認(rèn)驗證通過了磁携。

注意褒侧,這里可能v1默認(rèn)值已經(jīng)是true了,而是在判斷驗證未通過時將v1賦值為false再返回谊迄,因此可以將此函數(shù)所有的變量聲明都改為默認(rèn)值為true闷供。

3.?smali\com\google\android\vending\licensing\LicenseValidator.smali中的函數(shù)verify,將

0x1 -> :sswitch_1

0x2 -> :sswitch_0

改為

0x1 -> :sswitch_0

0x2 -> :sswitch_1

這里是將switch中驗證失敗的情況指向了驗證成功時要執(zhí)行的代碼段统诺。

4. 為了以防萬一歪脏,可以在繼承了Lcom/google/android/vending/licensing/LicenseCheckerCallback接口的類中修改dontAllow函數(shù),在函數(shù)一開始加入:

const/16 v1, 0x100

invoke-interface {p0, v1}, Lcom/google/android/vending/licensing/LicenseCheckerCallback;->allow(I)V

return-void

這里的意思是直接調(diào)用listener的allow函數(shù)粮呢,p0是callback自己婿失,變量v1聲明的初始值為0x100,是代表成功的常量鬼贱,調(diào)用p0的allow函數(shù)移怯,參數(shù)為v1,然后直接返回这难,之后的代碼就不會被執(zhí)行了舟误。這樣就確保必然調(diào)用allow,萬無一失姻乓。

5. 完成以上的步驟就可以通過GooglePlay驗證了嵌溢,但打開游戲后會開始下載游戲擴展包(obb文件),強制忽略手機上已存在的obb文件蹋岩。這是因為正常的sdk在驗證的同時會返回此游戲最新的擴展包名赖草、包大小等信息,方便用戶下載剪个、開發(fā)者更新等秧骑。因此為了可以順暢游戲,還要在實現(xiàn)了Lcom/google/android/vending/licensing/Policy接口的類中修改getExpansionFileName等一系列函數(shù)扣囊,直接將游戲擴展包的信息寫在代碼中直接返回乎折。

完成以上步驟即可順利游戲了,因為這些步驟都是有跡可循侵歇、規(guī)律的骂澄,所以寫個腳本就可以一鍵破解了(腳本正在編寫中)。

至于為什么不用破解后的驗證sdk直接覆蓋替換其他游戲的sdk惕虑,是因為各自游戲開發(fā)時間不同坟冲,采用的sdk版本不同磨镶,直接覆蓋可能會導(dǎo)致有些方法找不到,而以上的這些修改都是在sdk核心邏輯中健提,親自驗證了幾個版本發(fā)現(xiàn)這些核心邏輯并沒有改變琳猫。

可能遇到的特殊處理

有些游戲可能在進(jìn)行完以上步驟會出現(xiàn)閃退、報錯等情況矩桂,這可能是由于該游戲接入的第三方工具在搗亂沸移。以“拔拔曼陀羅”為例,本人完成以上步驟后報錯NullPointer侄榴,遂打開Eclipse查找Logcat(不得不說查Logcat是非常實用的辦法,只要眼疾手復(fù)制出來即可)网沾,發(fā)現(xiàn)的錯誤如下:

1. 無com.android.vending.CHECK_LICENSE權(quán)限錯誤:游戲中有個corona的包癞蚕,搜索后得知這是個打包插件,方便開發(fā)者集成Google辉哥、Amazon等sdk桦山、方便build。在Google驗證處調(diào)用enforceCallingOrSelfPermission時報錯醋旦,但Manifest中已添加此權(quán)限恒水,未找到原因,反正已經(jīng)破解了驗證饲齐,直接注釋掉钉凌,運行通過。

2. 空指針報錯:同樣還是Corona的坑捂人,在獲取谷歌框架服務(wù)時未判斷null御雕,大概corona的開發(fā)者覺得全世界的安卓機都應(yīng)該有谷歌框架吧,呵呵滥搭,注釋后運行成功酸纲。

當(dāng)然需要特殊處理的地方肯定會很多,并不是所有游戲都能自動化破解瑟匆,但有了自動化腳本就已經(jīng)節(jié)省不少工作量了闽坡。

那些難以跨越的坑

1. 代碼混淆

混淆后的代碼幾乎找不到從哪個類下手、從哪個方法下手愁溜,因為放眼望去所有類名疾嗅、方法名全部都是a、b祝谚、c宪迟。海外市場也有不少游戲和應(yīng)用添加混淆,但這也僅僅是“幾乎”而已交惯,并不是完全沒辦法次泽,具體如何破解下一篇再來闡述穿仪。

2. 加殼等防反編譯措施

還有很多種辦法可以防止apk被反編譯,如字符串混淆讓反編譯后的String類型不可讀、用花指令或動態(tài)加載等方式讓反編譯看不到源碼甚至無法反編譯源代碼。所幸目前見到的海外市場游戲較少采取此種措施粥诫,無需對此進(jìn)行破解特幔。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市蕾羊,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖笤昨,帶你破解...
    沈念sama閱讀 217,542評論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異握恳,居然都是意外死亡瞒窒,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評論 3 394
  • 文/潘曉璐 我一進(jìn)店門乡洼,熙熙樓的掌柜王于貴愁眉苦臉地迎上來崇裁,“玉大人,你說我怎么就攤上這事束昵“挝龋” “怎么了?”我有些...
    開封第一講書人閱讀 163,912評論 0 354
  • 文/不壞的土叔 我叫張陵锹雏,是天一觀的道長巴比。 經(jīng)常有香客問我,道長逼侦,這世上最難降的妖魔是什么匿辩? 我笑而不...
    開封第一講書人閱讀 58,449評論 1 293
  • 正文 為了忘掉前任,我火速辦了婚禮榛丢,結(jié)果婚禮上铲球,老公的妹妹穿的比我還像新娘。我一直安慰自己晰赞,他們只是感情好稼病,可當(dāng)我...
    茶點故事閱讀 67,500評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著掖鱼,像睡著了一般然走。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上戏挡,一...
    開封第一講書人閱讀 51,370評論 1 302
  • 那天芍瑞,我揣著相機與錄音,去河邊找鬼褐墅。 笑死拆檬,一個胖子當(dāng)著我的面吹牛洪己,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播竟贯,決...
    沈念sama閱讀 40,193評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼答捕,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了屑那?” 一聲冷哼從身側(cè)響起拱镐,我...
    開封第一講書人閱讀 39,074評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎持际,沒想到半個月后沃琅,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡选酗,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,722評論 3 335
  • 正文 我和宋清朗相戀三年阵难,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片芒填。...
    茶點故事閱讀 39,841評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖空繁,靈堂內(nèi)的尸體忽然破棺而出殿衰,到底是詐尸還是另有隱情,我是刑警寧澤盛泡,帶...
    沈念sama閱讀 35,569評論 5 345
  • 正文 年R本政府宣布闷祥,位于F島的核電站,受9級特大地震影響傲诵,放射性物質(zhì)發(fā)生泄漏凯砍。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,168評論 3 328
  • 文/蒙蒙 一拴竹、第九天 我趴在偏房一處隱蔽的房頂上張望悟衩。 院中可真熱鬧,春花似錦栓拜、人聲如沸座泳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,783評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽挑势。三九已至,卻和暖如春啦鸣,著一層夾襖步出監(jiān)牢的瞬間潮饱,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,918評論 1 269
  • 我被黑心中介騙來泰國打工诫给, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留香拉,地道東北人啦扬。 一個月前我還...
    沈念sama閱讀 47,962評論 2 370
  • 正文 我出身青樓,卻偏偏與公主長得像缕溉,于是被迫代替她去往敵國和親考传。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,781評論 2 354

推薦閱讀更多精彩內(nèi)容