逆向APK進行smali注入實現(xiàn)“秒破WIFI”
近期開始關(guān)注手機安全了,以往都是在PC上玩,對這個領(lǐng)域也想了解一下,可是拿什么來開刀呢?突然想起Wifi***鑰匙這個神器了,這個軟件的wifi分享模式鄙人非常喜歡,裝了這貨基本上很多地方都有免費的WIFI用!(這并非植入廣告!是真心話!)鄙人也把自己的家用wifi給共享了,10M的帶寬歡迎你連進來(只要你敢,嘿嘿)。不過這個軟件還是有美中不足的地方,軟件提供wifi連接的功能,但是并不會告訴你wifi的密碼是什么,估計廠家也是基于安全和隱私的角度考慮,這樣做也是對的,但其實密碼應(yīng)該就在軟件的某個地方,只要想找肯定會找到(在data/misc/wifi/wpa_supplicant.conf文件中),但這不是本文的重點,本文主要討論的是apk軟件的逆向和修改打包技術(shù),純技術(shù)交流用途。
好了,開始說干貨了(高手直接飄過吧),這次開刀的版本是官方2.9.27版本。首先APKTOOL反編譯安裝包,請注意版本號Apktool 2.0.0-Beta9。
得到smali源碼后開始找關(guān)鍵代碼,我們的主要目的是讓wifi***鑰匙把從服務(wù)器傳回來的密碼顯示出來,這樣我們不但能連入wifi,而且還能知道明文密碼。
首先與PC端軟件逆向的流程應(yīng)該是一樣的,找關(guān)鍵字定位關(guān)鍵代碼,這軟件每次連wifi都會顯示一些日志,其中有一條很關(guān)鍵,“嘗試獲取網(wǎng)絡(luò)密碼成功”,這應(yīng)該是成功獲取到了密碼之后的日志,這個字符串位于資源目錄中的strings.xml文件里。
依據(jù)XML的name字段"act_autoconnect_state_get_net_pwd_success"我們可以繼續(xù)搜索到位于public.xml中對應(yīng)的字符串ID。
依據(jù)這個 id="0x7f0d051e",我們能定位到關(guān)鍵的smali代碼,\WiFiMaster\smali\com\snda\wifilocating\ui\activity\fc.smali這里使用了這個字符串,代碼如下:
const v1, 0x7f0200bd
const v2, 0x7f0d051e
invoke-virtual {v0, v1, v2}, Lcom/snda/wifilocating/ui/activity/fe;->b(II)V
iget-object v0, p0, Lcom/snda/wifilocating/ui/activity/fc;->a:Lcom/snda/wifilocating/ui/activity/AutoConnectActivityWithStateList;
iget-object v1, p0, Lcom/snda/wifilocating/ui/activity/fc;->a:Lcom/snda/wifilocating/ui/activity/AutoConnectActivityWithStateList;
invoke-static {v1}, Lcom/snda/wifilocating/ui/activity/AutoConnectActivityWithStateList;->i(Lcom/snda/wifilocating/ui/activity/AutoConnectActivityWithStateList;)Lcom/snda/wifilocating/f/s;
move-result-object v1
可以從代碼中看到0x7f0d051e字符串作為參數(shù)傳遞進了b方法中,而后又被AutoConnectActivityWithStateList這個類進行了多次調(diào)用,看來AutoConnectActivityWithStateList類是個非常關(guān)鍵的環(huán)節(jié),我們不如直接找到這個類的實現(xiàn)代碼進去看看。
這個類的smali代碼路徑如下:\WiFiMaster\smali\com\snda\wifilocating\ui\activity\AutoConnectActivityWithStateList.smali
為了節(jié)省篇幅,省去讀這個類代碼的過程描述,直接粘貼關(guān)鍵代碼如下(大概1500行的位置):
.method private a(Lcom/snda/wifilocating/ui/activity/support/AccessPoint;Ljava/lang/String;)Lcom/snda/wifilocating/ui/activity/fd;
.locals 5
const/4 v4, -0x1
new-instance v0, Ljava/lang/StringBuilder;
const-string v1, "connect ap:"
invoke-direct {v0, v1}, Ljava/lang/StringBuilder;-><init>(Ljava/lang/String;)V
iget-object v1, p1, Lcom/snda/wifilocating/ui/activity/support/AccessPoint;->b:Ljava/lang/String;
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
const-string v1, " with pwd:"
invoke-virtual {v0, v1}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0, p2}, Ljava/lang/StringBuilder;->append(Ljava/lang/String;)Ljava/lang/StringBuilder;
move-result-object v0
invoke-virtual {v0}, Ljava/lang/StringBuilder;->toString()Ljava/lang/String;
invoke-static {p2}, Landroid/text/TextUtils;->isEmpty(Ljava/lang/CharSequence;)Z
move-result v0
if-nez v0, :cond_0
這是一個非常關(guān)鍵的方法的實現(xiàn),我們看到該方法有兩個參數(shù),一個是AccessPoint類的對象,另一個是String字符串,方法的一開始就實例化了一個StringBuilder的對象,然后使用append不斷的拼接該字符串,大概的拼接規(guī)則是這樣的:
“connect ap: ”+ “AccessPoint;->b”+“with pwd:”+“String”
看到了這里似乎就已經(jīng)明朗了,意思就是 連接熱點:XXX 使用密碼:XXX。
所以我們完全有理由相信,這個String類型的參數(shù)實際上就是wifi熱點的密碼!
OK,到了這里,我們要做一些工作來進行驗證,你可以選擇使用ADB調(diào)試然后跟蹤到這里,或者干脆修改smali,讓它輸出這里的String給我們看,我選擇第二種方法,因為本來我們也是為了要讓它顯示密碼。
手動輸入如下的代碼插入到該方法中(smali有很嚴格的語法規(guī)則,拿到一段代碼先要搞清楚含義,隨意插在什么地方幾乎是跑不通的,關(guān)于smali的語法網(wǎng)上有很多資料了,建議先學(xué)習懂了以后再去寫,當然如果你是高手就飄過吧)
new-instance v5,Landroid/app/AlertDialog$Builder;
invoke-direct {v5,p0}, Landroid/app/AlertDialog$Builder;-><init>(Landroid/content/Context;)V
const-string v6, "|Cracked by \u6210\u738B\u8D25\u5BC7| PASSWORD IS:"
invoke-virtual {v5,v6}, Landroid/app/AlertDialog$Builder;->setTitle(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;
invoke-virtual {v5,p2},Landroid/app/AlertDialog$Builder;->setMessage(Ljava/lang/CharSequence;)Landroid/app/AlertDialog$Builder;
invoke-virtual {v5},Landroid/app/AlertDialog$Builder;->create()Landroid/app/AlertDialog;
move-result-object v6
invoke-virtual {v6},Landroid/app/AlertDialog;->show()V
這段代碼就是使用AlertDialog類的一系列方法彈出對話框,把密碼顯示出來。(真搞不懂java彈個對話框怎么要用到這么多方法,這里懷念一下windows的MessageBoxA。)
插入過后就是對整個代碼進行編譯打包的工作了,不要以為這個活就干完了,真正鬧心的還在后面呢!
我們使用apktool b [反編譯后的目錄] 進行打包,多數(shù)情況你會發(fā)現(xiàn)打包過程是會報錯的,千奇百怪的錯!只有少數(shù)APK會成功打包。后來我專門研究了一下這個問題,主要其實是資源出的錯,當然前提是要先把smali代碼編譯過去,剩下再解決資源的問題。本例中的這個APK也是有報錯的,好在還不多,都一一解決了。其實我本來想把資源報錯這個問題的細節(jié)寫進來,但其實這是個體力活!而且每款軟件都不同,幾乎沒有借鑒意義。所以我準備把一些方法性的東西告訴大家,具體問題你只能具體分析了。
解決打包報錯問題的基本思路就是先看報錯內(nèi)容(這不是廢話么~),因為這是我們唯一的線索,先搞清楚問題的原因再去對癥下藥,smali報錯我就不說了,因為這多數(shù)是語法的問題,只能好好學(xué)學(xué)了。如果報錯類型是資源文件出錯,例如string.xml、public.xml什么的,那你就把原始的apk資源解包出來,然后把反編譯的對照原始資源文件進行參考修改,缺啥就補啥,多啥就刪啥,引用錯了啥就改啥,這也是需要你對安卓的整個打包文件結(jié)構(gòu)有一定的了解才行,具體問題具體分析。
好了,此處省略一萬次報錯修改的過程……(真心希望google能把apktool好好做做,這么多bug不像是google的產(chǎn)品作風啊!)***終于生成出了打包好的文件,它在你反編譯后的dist目錄中。
先別急,我們還要對這個APK進行簽名,否則安裝不了。
OK,我們下面安裝這個APK,來看看效果。
安裝后開啟wifi,然后點擊一鍵查詢***鑰匙,搜出來個901,估計是門牌號,信號很好并且已經(jīng)共享了wifi,我們連進去看看。
點擊“***鑰匙自動連接”,順利的話就應(yīng)該能爆出密碼了。
OK,密碼已經(jīng)成功彈出,大功告成!有了這貨你基本上就可以秒破很多WIFI了!對于已經(jīng)修改好的APK我就不提供下載了,我們的目的是純技術(shù)交流,你懂的。