因一紙設計稿,我把競品APP扒得褲衩不剩(下)

嚴正聲明php

  • 一、相關破解技術僅限於技術研究使用,不得用於非法目的,不然後果自負!
  • 二、筆者僅出於對逆向技術的好奇,無惡意破壞APP,尊重原開發者的勞動成果,未用於商業用途。

0x五、狩獵的時候到了 => 調試定位

  • 通過上一章的「淬鍊」,相信大部分「簡單APP的源碼」你都信手拈來了;
  • 但古語有云「弱水三千,只取一瓢」,在品嚐別人代碼時,可能會遇到不少美味的「奇淫巧技」
  • 但有限精力和時間,使得咱們沒法一一品嚐,抓住須要的同樣就夠了;
  • 美人鄉英雄冢,時刻保持清醒「知道本身要的是什麼」,以避免本身深陷其中(鑽牛角尖);
  • 快速定位到目標代碼,弄清邏輯,完成核心代碼的抽取

接着說下筆者經常使用的一些「調試定位技法」,沒有優劣之分,混合使用快速找到 G點(關鍵代碼) 便可~css


① 資源定位法


最簡單,卻最高效的方法,能夠經過「一行文字」「一張圖片」「一個音視頻」完成定位,「無腦全局搜索!java

記得先把apktool反編譯後的res和asserts文件夾和jadx反編譯後的代碼丟到一塊兒! (也可使用個人批處理反編譯腳本自動搞定)android

舉個例子:忽然以爲競品的對話框有點好看,可是好懶,不想本身寫:git

Ctrl+Shift+F 全局搜「快去登陸吧」或「登陸後會解鎖更精彩的內容哦github

打開DialogUtils類,6個參數,不難定位到第三個a方法:web

跟下CommonDialog類:面試

直接定位到了佈局文件:shell

複製粘貼,改點東西,精美對話框get√bash


② 獲取到當前Activity


ActivityFragment 也是很是好的切入點,經過簡單的adb命令便可得到棧頂(當前) Activity的相關信息:

# 獲取當前棧頂Activity的名稱
adb shell dumpsys activity | grep "mFocusedActivity"

# 你能夠經過alias爲上述命名設置一個別名:
alias ada="adb shell dumpsys activity | grep 'mFocusedActivity'"
複製代碼

效果以下圖所示:

你能夠能夠用:adb shell dumpsys activity top > info.txt 把Activity詳細信息打印到文件中。
也能夠安裝「開發者助手」直接獲取到(還能夠看到可能涉及的Fragment):

還能夠經過「反射大師」獲取到:


③ Android Device Monitor 跟蹤方法調用


舊版的as是有這個東西,新版把入口給隱藏了,直接來到「android-sdk/tools」目錄下,找到monitor,運行便可:

左側選擇待調試進程:

以爲跟蹤得差很少了,就點擊②那個按鈕中止,右側會出現以下所述的方法調用流程:

而後你就能夠一步步跟了~


④ Smali動態調試


Apktool反編譯apk後,生成的是「Smali」文件,而非「Java」文件,Smali 是一種虛擬機指令語言。
Jadx反編譯dex後雖然生成了Java代碼,看看能夠,是不支持調試的,而Smali是可調試的,在AS中想調試Smali的話,還須要安裝「smalidea」插件,插件的下載,可移步至:bitbucket.org/JesusFreke/…,下載後,AS安裝一波插件,安裝完畢重啓便可。

注意:如今是你想調試別人的APP,那首先,要先把別人的APP變成「可調教狀態(debugable)

一個看似簡單但卻很繁瑣的方法:

把目標APP的 AndroidManifest.xml 中的 debuggable屬性設置爲true,簽名重打包。

若是逆向的APP有多個,這應該顯得好繁冗,不如直接把「手機上全部應用都變成可調試狀態」,方法以下:

  • Android 7.0如下安裝了Xposed的
    下載安裝「BDOpener模塊」:github.com/riusksk/BDO…,啓用插件重啓便可。
     
  • Android 7.0及以上安裝了Magisk的
    Magisk裏下載安裝:「MagiskHide Props Config」和「Busybox for Android NDK」而後重啓。
    接着終端 adb shell,輸入 props 進行設置,找到:Edit MagiskHide props的選項,好比這裏是4:

回車,會提示是否設置爲0,輸入y,接着設置完,提示是否重啓,輸入y重啓,接着打開AS 的 Logcat 就能夠看到全部的進程了:

設置完可調教,就能夠把smail導入AS中,導入過程須要注意下哦,不是直接open!打開AS在導入腳本反編譯後的apktool文件夾:

導入後,點擊頂部菜單欄的這個位置,「Edit Configurations」,點「+」選擇「Remote

隨便填個名字,而後設置一個端口號 (本身定,auto.sh腳本那裏要配合着改哦!)

命令行啓動進程調試等待模式」比較繁瑣且重複,我直接寫到一個auto.sh文件中:

#!/bin/sh
if [[ $# == 0 ]]; then
    echo "./debugTool [package] [activity] "
    exit 1
fi
package=$1
activity=$2
adb shell am start -D -n ${package}/${activity}
varId=`adb shell ps | grep package| awk '{print $2}'`
adb forward tcp:4567 jdwp:$varId
複製代碼

接着命令行鍵入:./auto.sh 包名 入口Activity,示例以下:

./auto.sh com.xxx.xxx .MainActivity
複製代碼

APP進入待調試等待模式後,點擊頂部「Attach Debugger To Android Process」,下好斷點,選擇調試進程:

接着等待程序運行至斷點,Debugger就能夠看到相關的變量了:


⑤ Smali語法的學習姿式分享


Smali的語法比較繁雜(感受比我之前學彙編還麻煩),網上的教程不是通常的凌亂,有機會我整理一份吧…

你真的想學Smali得話,建議邊「實操邊學,即用即插(查)」,idea有個插件「intellij-java2smali
Github地址github.com/ollide/inte…,支持把「正確項目中的Java」轉換爲smali文件。
注意:正確!和 項目!項目有錯的話,轉換直接報錯,單個獨立的java文件也是不能轉換的!用法很簡單:

打開須要轉換的java文件,依次點擊頂部菜單欄的 run -> Compile to smali

說個bug:

官方說是支持kotlin轉的,可是新版的AS會報錯:Error:Kotlin: Unsupported plugin option: org.jetbrains.kotlin.android:enabled=true,估計是插件的用到的kotlin相關依賴沒升級,目前無解(等官方維護,或者本身改插件源碼);

你能夠選擇建立一個純Java的項目,程序沒報錯,能夠跑,可是轉換的時候,又會出現一個bug:

java: 程序包R不存在 ,R文件找不到,儘管你能夠在build目錄下找到它,猜想是沒有適配新版本AS的R文件路徑,一個治標不治本的方法,把setContentView()一行的代碼註釋掉。

另外,我的感受AS上看 smali並非很爽 !既然以爲不爽,那就換個體位,是吧?舉幾個例子:

  • 男的以爲不夠刺激,就用「推磨式」;
  • 女的以爲不夠刺激,就用「貓式」;
  • 男的想快感加倍,就用「後入式」;
  • 女的想自由把控,就用「傳統女上位式」;
  • 想豐富彼此情感交流,就用「傳教士體位」;
  • 想延長時間,就用「面對面側臥」;
  • em…體位有不少,就不一一列舉了,只是想告訴你們:哪一種方式適合本身就用哪一種~

若是你用「VS Code」的話,能夠安裝一個「Smalise」插件:Smali語法高亮 支持變量或者方法名的定位:

除此以外,還能夠直接看「Unicode轉換後的中文」、「變量信息」、「定位到定義處


⑤ 動態調試so

目前不會,之後有興趣或者須要學再去學吧,學完了再來補全~


0x六、是時候表演真正的技術了 => 破解


學完調試定位技巧,咱們已經能快速找到G點(核心代碼),再來玩點「刺激」的吧:

看到,有人在上一篇《因一紙設計稿,我把競品APP扒得褲衩不剩(中)》有人在評論區留言對「鄰居的故事」感興趣,我用簡單的幾句詩來歸納下後續劇情吧:

男子加班回家晚,草草了事交公糧
妹子以爲略失望,慾求不滿暗自嘆
鄰居首捷心暗爽,惟美畫面反思量
妹子軟萌待開發,制服跳蛋震動棒

以爲妹子過於乖巧,鄰居想二次開發妹子(APK),因而用上了三個道具,這些道具怎麼用等等再說。說回這一節,在使用別人APP的時候,你可能會想:若是是個人作的APP,我要…!建議別想,直接動手吧!加點什麼(自定義UI) 或者 改點什麼(付費變免費,開隱藏關卡),固然本身暗爽就行了,可別處處傳播,「破壞計算機信息系統罪警告」。以競品APP關卡付費爲例,講解一波:

問題描述以下:

  • 一、首頁課程有鎖,點擊:彈出須要開通完整課程的對話框;
  • 二、點擊下一關,沒法切換到下一關,提示:敬請期待;
  • 三、50-100節的課程帶鎖,點擊提示:努力建造中…;
  • 四、課程等級除了L1外,其餘級別帶鎖,點擊提示:敬請期待;

① 制服——調試下斷點直接改標誌位


怎麼動態調試Smali上面已經介紹過了,具體調試技巧可見《逮蝦戶!Android程序調試竟簡單如斯》,來到APP中的以下頁面:

點擊50-100 會出現「努力建造中」的提示語,打開開發者助手:

直接定位到 CourseChangeFragment

看下this.n是啥,以及裏面的d是什麼:

行吧,這個d就是圖片是否高亮,1爲高亮,接着看下this.n在哪裏完成賦值:

而關卡選擇,直接全局搜「選擇等級對應的課程地圖」定位到ChangeLevelDialog,全局搜,定位回CourseChangeFragment

一樣,看下this.k是啥,在哪裏完成了賦值:

跟到ChangeLevelDialog,能夠看到,提取的是裏面的CourseLevelInfo

跟過去看看:

行吧,這個c就是關卡的狀態1爲可用狀態,行吧,找下斷點的時機,搜下控件:

控件id爲0x7f0f0363,回到CourseChangeFragment.smali搜:

直接定位到sswitch_2:

這裏圈住的地方,實際上是中文的Unicode碼,不信,轉換下你就知道了:

定位到下面這段代碼:

接着講解一波這段代碼:

iget-object v0, p0, .../CourseChangeFragment;->n:.../$CourseLevelMapInfo;
# 引用對象,p0爲該變量所在類的實例,即this,把n的值放到v0寄存器中

if-eqz v0, :cond_1
# 判斷v0是否爲0(null),是的話跳到cond_1

iget-object v0, p0, .../CourseChangeFragment;->n:.../$CourseLevelMapInfo
# 同上上一行代碼把n的值放到v0寄存器中

iget v0, v0, ...$CourseLevelMapInfo;->d:I
# 引用v0寄存器中保存的n對象,把n.d的值放到v0寄存器中

if-ne v0, v1, :cond_1
# 判斷v0寄存器和v1寄存器中的值是否相等,不等跳到cond_1
複製代碼

如圖下完斷點,開始調試smail,來到關切頁面,點擊後進入調試模式:

右鍵d,選擇Set Value,把值設置爲1,接着往下執行斷點,能夠看到「隱藏關卡」開啓成功:

嘖嘖,有點意思,其餘幾個破解也是「如法炮製」,不過每次都要這樣調試顯得太麻煩了,有沒有一勞永逸的方法?固然有,寫個Xposed插件耍耍吧~


② 跳蛋——編寫Xposed插件


關於Xposed,以前寫過一個系列,就再也不詳細介紹了:

簡單說經過它,你能夠:

修改變量的值,Hook方法(執行先後作一些修改),顯式去執行一些方法等

咱們須要先定位到「標誌位的源頭處」(通常是方法),在方法執行前或後,進行一些修改,過程比較瑣碎,直接給出插件代碼吧!先是三、破解課程選擇的鎖

接着是:四、破解關卡選擇對話框

再接着是:二、破解首頁下一關切換

最後是:一、破解首頁全部關卡

把寫好的Xposed插件安裝到手機上,Xposed Installer勾選,重啓,接着打開APP,看下效果:

行吧,插件編寫完畢,可是畢竟不是每一個人的手機都會Root裝Xposed,索性破解後二次打包吧。


③ 振動棒——apktool二次打包


使用apktool二次打包的流程很簡單難的是改Samli代碼

改smali => apktool b 重打包 => jarsigner/apksigner 二次簽名

行吧,動手擼smali,定位到 CourseChangeFragment.smalionClick函數 的判斷處代碼:

前面這個數字是「十六進制的資源id」,能夠直接把jadx反編譯出來的id轉換下:

分別對應:7f0f03607f0f0363,對應跳=> sswitch_3sswitch_2,先去sswitch_2處,能夠看到源碼中作了判斷,若是不知足return,知足的話繼續走,這裏能夠鑽個空子,「直接把判斷相關的代碼刪掉」,只保留下圖圈着的代碼:

接着拖過以下命令把項目二次打包回apk:

apktool b xxx -o xxx.apk
複製代碼

接着用「jadx-gui」打開apk看看代碼:

嘖嘖,能夠,接着須要對APK進行二次簽名才能安裝到手機上,能夠經過「jarsigner」或「apksigner」完成簽名。玩法以下:

# 若是你沒有簽名,可經過下述命令建立,回車後會讓你輸入密碼,輸完無腦回車便可
keytool -genkey -v -keystore 文件名.jks -keyalg RSA -keysize 2048 -validity 10000 -alias 簽名別名

# ====== jarsigner簽名 ======

#  一、輸入下述指令,回車後輸入密碼
jarsigner -verbose -keystore 證書 -signedjar 簽名後.apk 簽名前.apk 證書別名

# 二、報錯的話可能須要最在-keystore前添加下述參數:
-digestalg SHA1 -sigalg MD5withRSA

# 三、Tips:可使用下述命令查看APK是否已簽名
jarsigner -verify xxx.apk

# ====== 使用谷歌提供的簽名及驗證的專用工具:apksigner ======
# 位於:Android SDK/build-tools/SDK版本/apksigner.bat

# 一、對齊
zipalign -v -p 4 xxx.apk xxx_aligned.apk    

# 二、簽名
sign --ks 證書 --out release.apk origin_aligned.apk

# 三、驗證是否簽名成功
apksigner verify release.apk
複製代碼

把簽名後的APK安裝到手機上,打開看下效果:

雖然還有鎖的那個圖標,可是卻能夠點擊切換關卡了,能夠,繼續折騰,選擇關卡部分:

點擊時判斷 courseLevelInfo.c == 1,那麼咱們找到初始化courseLevelInfo對象的地方,在這裏直接把c設置爲1便可,不難定位到:

在箭頭所指的代碼後,添加一句:courseLevelInfo.c = 1;,就行了,可是你須要把這個java語句轉換成smali!這個轉換可沒你想象中那麼簡單哦!打開ChangeLevelDialog.smali,定位a方法:

不難定位到以下位置,咱們須要在.line 添加賦值代碼:

賦值操做須要用一個寄存器保存1(0x1),而後用iput進行賦值:

接着apktool b打包,用jadx-gui打開看看:

行吧,轉換後除了行號,沒問題,直接jarsigner二次簽名,adb安裝到手機上驗證下:

能夠,nice,把剩下的首頁下一關和全部關卡也折騰下吧:

刪除賦值語句,對應Smali中:

重打包,jadx-gui打開查看:

每一個關卡鎖定位到:MainHomeworkAdapter$CommonViewHolder類 (美圓符號表明內部類)

在如圖所示的地方插入賦值語句,

重打包,jadx-gui打開查看:

運行下看下效果,結果和xposed大同小異,可是沒裝Xposed的手機也能直接使用~

而後說一點:

不是全部的APK都能直接二次打包簽名!有些會作簽名校驗,打開簽名不對,直接閃退,Java層能夠Hook掉檢驗的方法,Native層的只能去改So;還有些加固的APK,儘管能夠導出dex,可是二次打包的話還須要修復onCreate函數(如360加固寶)。因此大部分時候,咱們都只是能看看代碼而已~因此Xposed仍是香,Smali寫起來是真的繁瑣,複雜邏輯的代碼會寫到想哭,每次看效果都要重打包…


④ 移動端逆向利器——MT管理器2


PC端逆向,須要下載一堆反編譯工具(apktool, jadx等),一些更好用的工具(AndroidKillersmali2java)等還不支持mac,
因此它來了—— MT管理器2:移動端「雙窗口文件管理」和「強大的APK編輯功能」,可在手機上高效地修改安卓軟件,界面以下:

官方文檔中已有詳細的講解,就不嗶嗶了,讀者自行查看文檔把:MT管理器,另外還有個相關的逆向論壇:MT論壇

「Tips:基本上能夠說是付費的,部分功能須要會員才能使用~」

筆者有「記帳」的習慣,用的是「X記帳」,界面粉粉的,挺Gay的,就是每次打開彈出的「廣告閃屏頁」令我非常反感。行吧,就拿它來開刀吧,順帶給你們演示下「MT管理器2」怎麼耍。

點擊左側菜單欄的「跟蹤Activity」,開始跟蹤,接着打開軟件,而後回到MT管理器,能夠看到Activity的啓動記錄:

先進LogoActivity,再進MainActivity,點擊左側菜單「安裝包提取」:

提取後定位到/MT2/apks目錄下,點apk,「查看」,打開AndroidManifest.xml也看到:

行吧,入口是就是LogoActivity,點擊classex.dex打開,兩個dex都選擇:

接着按照包名,打開LogoActivity,點擊右上角,「轉成Java

轉換後的Java代碼和Jadx的同樣:

見名知意,圈着的就是顯示廣告的View(@BindView祖傳黃油刀),想把廣告禁掉,把相關加載的代碼都刪掉就好啦:

和PC同樣改smali,不過比起PC,改完,直接就能夠轉Java,方便好多,修改完後保存,返回會彈出以下對話框:

可是,打開二次打包後的APP:「廣告內容沒了,可是卻卡在了圖標頁,要點擊右上角才能關閉
我擦,估計是AdsView裏還有什麼邏輯(好比廣告加載完才跳轉),一不作二不休,直接把這個AdsView給去掉吧,
刪佈局文件裏的,再刪LogoActivity相關的代碼,正當我準備開始這樣作的時候,我看到了這些:

2333,爲了不「空指針異常」,調用adsView相關方法前都作了「判空」能夠,很好的開發習慣!

但也方便了我(內心樂開了花

我直接在頁面初始化的地方把這個「adsView設置爲null」不就行了!

定位到如圖所示位置,在初始化View的地方把View置空,沒毛病

打開initView函數對應的smali代碼,編寫把adsView置空的smali代碼:

二次打包,覆蓋安裝看看效果:

對比下沒去廣告的效果:

當真是日了狗,點擊跳過的按鈕很小很容易誤觸,並且點了還不是立馬關閉!改完後瞬間舒服了~
對了,學完這裏你能夠出去吹牛逼了:《兩行代碼去掉APP閃屏廣告頁》


0x7 、死亡如風,常伴吾身 => 爬取APP數據


其實,原本沒有這一節的,畢竟,APP源碼都被你扒得褲衩不剩「任意蹂躪」了,可是有一點:

她並不屬於你!

若是哪一天,這個APP下架了,服務器撤掉了,你所作的一切就「付之東流」了。

與其在之後的某一天說暗自感嘆

祝你歲月無波瀾,敬我餘生不悲歡

不如想辦法讓她真的屬於你:

說到底:APP只是一個資源展現工具,而後臺則是一個資源調度工具,關鍵的仍是「資源」!

把資源搞到手,APP和後臺隨便你折騰,接着抓包分析一波,而後寫個爬蟲把每一關的數據保存起來~
直接經過 Fiddler,Charles等 抓包工具抓取一波數據,移動端如何抓包,可參見我以前寫過的文章:《忘了他吧!我偷別人APP的代碼養你》,此處就再也不復述了,直接開抓:

好幾個接口,篩選出咱們須要的接口:

規則比較簡單,接口沒作用戶校驗,付費資源連接也有返回,只是在APP端作了限制。
直接頂一個一個存儲數據的類,把爬取到的數據塞到MongoDB中:

出於反爬蟲的習慣,使用「代理ip」訪問,關於代理IP如何獲取,之前說過,就不嗶嗶了,這裏用阿布雲的代理隧道,1塊錢1小時,美滋滋,相關配置以下:

除了使用代理ip,「設備名設備id版本」都隨機生成:

接着編寫請求和解析數據的方法:

最後開啓一波多進程訪問:

多進程+可用性比較高的代理,一分鐘不到就爬完,美滋滋:

lessonDay的順序有些不對,排序查詢一波:

行吧,數據爬取完畢,剩下的接口就不一一演示了,對了,你還能夠寫個腳本把全部的音視頻資源,圖片爬到本身電腦,或者同步到七牛雲等CDN站點,接着遍歷替換一波基地址。另外,若是抓包分析不出規律,你也能夠從APP入手~


0x八、小結


歷經坎坷,終於把最後一章給肝出來了,寫這個系列的初衷是想扒一些競品APP的好看效果,結果活生生寫成了逆向,也算是本身一個階段性學習的總結了,逆向的水挺深的,有機會和閒情再耍耍把,就這樣,接下來,準備寫個「面試準備週報」系列,以督查本身好好準備面試,敬請期待。


本系列最後一次送書,意思意思送「一本本身寫的Python爬蟲入門書」,評論區留言抽,包郵,下週五抽~ (可能延遲,但必定抽,無暗箱~)

謝謝各位一直以來的支持和厚愛,愛大家~

Tips:本你想系列用到的工具,都有給出比較官方的下載連接!!!你也能夠到公號
摳腚男孩」輸入000,回覆對應序號下載,謝謝~

相關文章
相關標籤/搜索