日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

逆向so_安卓逆向 | 分析调试与so调用实战

發(fā)布時間:2024/8/23 编程问答 22 豆豆
生活随笔 收集整理的這篇文章主要介紹了 逆向so_安卓逆向 | 分析调试与so调用实战 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

聲明:本教程用于學(xué)習(xí)交流,如有侵權(quán)聯(lián)系本人刪除!

點(diǎn)擊上方“逆向小白”,選擇“加為星標(biāo)”

第一時間關(guān)注逆向技術(shù)干貨!

使用fiddler抓取某app登錄接口的時候,沒有看到任何相關(guān)的數(shù)據(jù)包,猜測app做了防抓包或者不走h(yuǎn)ttp協(xié)議,嘗試proxyDroid、小黃鳥還是不行,最后使用Packet Capture成功抓到數(shù)據(jù)。看了下登陸接口提交的參數(shù),不知道sign值是怎么來的,所以目標(biāo)很明確,就是需要逆向分析sign的生成算法。

將apk文件拖到j(luò)adx中進(jìn)行反編譯,ctrl+shift+f 搜索關(guān)鍵詞sign出來很多信息但沒找到有用的,試試搜索"sign",仔細(xì)查看發(fā)現(xiàn)圖示可疑位置,點(diǎn)進(jìn)去看看。

看到圖示內(nèi)容,可以確定找對了地方,sign值是getSign方法執(zhí)行后的結(jié)果,getSign方法中調(diào)用了SignManager類getSign方法,傳入了三個參數(shù),第一個參數(shù)不確定其值,第二個參數(shù)是token值,前面抓包發(fā)現(xiàn)這個值是空的,第三個值是時間戳,右擊getSign跳到方法聲明的地方。

加載so、通過native關(guān)鍵字定義了需要調(diào)用的方法getSign,也就是說,它這里調(diào)用的是so層的加密算法,so是什么?簡單來說,它是c/c++編譯后的產(chǎn)物。既然目標(biāo)app能調(diào)用,那我們也可以。在搞之前,還有個參數(shù)不確定。這里就用jeb調(diào)試一下看看。

將apk拖到j(luò)eb中進(jìn)行反編譯,dex反編譯成smali,我們可以調(diào)試這個smali代碼, ctrl+f 搜索"sign", 找到getSign方法,ctrl+b下斷點(diǎn)。

確保手機(jī)已root并且可調(diào)試,如果沒有開啟調(diào)試,到網(wǎng)上去下載相應(yīng)的mprop, ?使用adb推送到手機(jī)里,通過如下方法可以臨時設(shè)置調(diào)試狀態(tài),這個方法是修改內(nèi)存中的值,重啟手機(jī)后恢復(fù)不可調(diào)試狀態(tài)。如果你想要永久設(shè)置,到網(wǎng)上找相應(yīng)的教程。然后可以通過adb連接手機(jī),確保jeb可以識別到手機(jī)。

點(diǎn)擊附加調(diào)試,選擇需要調(diào)試的進(jìn)程包名附加進(jìn)程。

手機(jī)上輸入賬號密碼點(diǎn)擊登陸觸發(fā)斷點(diǎn)

上面分析過,斷點(diǎn)處的getSign傳入了四個參數(shù),而真正用到的是后面三個,這三個參數(shù)值分別放在寄存器v1、v2、 v3中,將int修改為string, 可以看到,v1中的值是空的,v2中的值是空的,v3中的值應(yīng)該是時間戳,如果你不放心可以多次嘗試。

三個參數(shù)值確定了,下面要做的工作就是調(diào)用so層的加密算法獲取sign值,關(guān)于so調(diào)用,可以去學(xué)學(xué)逆向大佬花哥的教程,通過壓縮軟件打開apk,因?yàn)槲沂謾C(jī)的cpu類型是arm64-v8a, 是向下兼容的,選擇使用armeabi-v7a中的so文件是可以的。

將so文件復(fù)制到安卓項(xiàng)目的libs->armeabi-v7a下面,并且在app->build.gradle中限制支持的平臺,不加這個我這是報(bào)錯的,加上限制條件,app也不會顯得那么臃腫。

在src->main->java下新建一個包名為com.sichuanol.cbgc.util的包,在包下面創(chuàng)建一個名叫SignManager的類,復(fù)制源碼過來就行。

然后在控制器中調(diào)用getSign方法,運(yùn)行項(xiàng)目安裝到手機(jī)上,啟動服務(wù)。

瀏覽器訪問服務(wù)接口,返回的是so文件名,竟然翻車了!!!

看了下日志信息,缺少了某個類,嘗試復(fù)制對應(yīng)的文件過來,但還是報(bào)錯缺各種東西,猜測是不是有簽名校驗(yàn),那么調(diào)用so的方案就失敗了?問題總得解決,換另一個方案,用IDA逆向分析so。跟著大佬學(xué)習(xí)一下IDA的調(diào)試過程,做一個簡單的記錄。

將so文件拖到IDA中,Exports->**getSign,雙擊點(diǎn)進(jìn)去。

這是so反編譯出來的匯編代碼,看不懂啊,像我這種菜雞還是去看看偽c代碼吧,按F5或者Tab。

**getSign函數(shù)中五個參數(shù),第一個參數(shù)是JNIEnv類型指針,它指向java環(huán)境,通過這個指針就可以對java的代碼進(jìn)行操作,第二個參數(shù)是java傳遞過來的類/類實(shí)例,后面參數(shù)就是我們上面分析的那三個,有人說,這里的參數(shù)類型明明都是int,而且看代碼似c不c,其實(shí)是這樣的,ida反編譯so不可能百分之百還原c/c++代碼, ?而且這里還用到j(luò)ni函數(shù),jni又是什么?簡單的說,有了jni可以實(shí)現(xiàn)java代碼和c/c++代碼的互調(diào)。?

這些強(qiáng)制類型轉(zhuǎn)換看著太不舒服了,右擊hide casts把它們隱藏。

看到一些*v5加上數(shù)字這又是什么操作,上面分析過,第一個參數(shù)a1是JNIEnv指針,賦值給v5, 那么這一些操作好像是指針偏移,可能是取了jni的函數(shù)或者變量。

為了讓人能看懂這些jni函數(shù),我們需要導(dǎo)入jni.h頭文件,然后改第一個參數(shù)為JNIEnv類型指針。

選中第一個參數(shù)a1, 右擊選擇convert to struct*, 選_JNIEnv, 然后再更改指針名為env。

我們將v5的名字也改一下,改成env_,改完之后你會發(fā)現(xiàn),這才是人能看懂的代碼啊。

GetStaticMethodID獲取java靜態(tài)方法ID, "getAppSign"為方法名,如果沒有取到方法ID就會進(jìn)行一系列操作。好吧,這就解釋了為啥我們調(diào)用so報(bào)錯了。

用jadx搜一下getAppSign方法,我們看到,方法所在的類就是之前報(bào)錯缺失的,getAppSign方法取了簽名值,如果異常返回一個空字符串。要知道,你不改動apk文件的情況下,這個app簽名值是固定不變的。看c代碼中沒有涉及到其他java自寫方法,那我們只要拿到這個簽名值,so調(diào)用的方案不就簡單了嗎?

編寫一個xposed模塊進(jìn)行hook操作,不會的請參考上一篇教程?xposed模塊編寫實(shí)戰(zhàn)

把取簽名方法所在的類文件復(fù)制到so調(diào)用的項(xiàng)目里,放在同樣的包名下,把多余的方法刪掉,getAppSign方法只需要返回這個固定字符串就可以了。

運(yùn)行項(xiàng)目安裝apk開啟服務(wù),我們拿教程第一張圖中的時間戳進(jìn)行驗(yàn)證,瀏覽器訪問這個接口發(fā)現(xiàn)拿到數(shù)據(jù)了,這個結(jié)果跟抓包的結(jié)果是一樣的。那么簡單的so調(diào)用就這么搞定了。那么我們是否可以用IDA調(diào)試?yán)^續(xù)來搞呢?

回到偽c代碼,大概看看代碼你應(yīng)該知道,取了簽名值之后,又有字符串拼接等操作,后面執(zhí)行MD5Digest函數(shù)傳入了三個參數(shù),第一個是字符串,第二個是字符串的長度,第三個用于存放運(yùn)行結(jié)果,我們只需要最終需要加密的字符串就好辦了,看偽c代碼是看不出來的,頂多可以猜一下。

調(diào)試狀態(tài)下為了效率問題并不會完全解析代碼,就會有個問題,我們不好找下斷點(diǎn)的地方,因?yàn)楹瘮?shù)名變成我們不認(rèn)識的,那么我們需要另一種方法,從函數(shù)開始的位置往下數(shù),看MD5Digest位于第幾個BLX, 記住這個位置。

到網(wǎng)上下載相應(yīng)的android_server,用adb將其推送到手機(jī)里,具體參考網(wǎng)上教程,然后把名稱和端口號最好改一下,有的app會根據(jù)這個名稱和端口號進(jìn)行反調(diào)試,但是本教程案例沒有反調(diào)試,默認(rèn)也可以,然后開啟服務(wù),進(jìn)行端口轉(zhuǎn)發(fā)。

重新打開IDA, 遠(yuǎn)程附加進(jìn)程。

慢慢等待,出來下圖所示的界面點(diǎn)擊左上角的啟動按鈕,讓app在調(diào)試狀態(tài)下運(yùn)行,然后找到Modules, ctrl+f 搜索你需要調(diào)試的so, 點(diǎn)進(jìn)去找到需要調(diào)試的函數(shù)

一般情況下,當(dāng)某個函數(shù)被調(diào)用的時候,R0, R1, R2, R3寄存器存放函數(shù)的參數(shù)值,因?yàn)镸D5Digest函數(shù),傳入了三個值,所以我們后面調(diào)試的時候,只需要關(guān)注R0、R1、R2寄存器就可以了,接下來,我們需要找到下斷點(diǎn)的位置。

找到前面記住的BLX位置,如果你不確定這個位置是否正確,可以點(diǎn)進(jìn)去,然后按c鍵,可以看到這個地方就是我們需要下斷點(diǎn)的位置,把方法函數(shù)名改一下,方便查看。

按F2添加斷點(diǎn),手機(jī)輸入賬號密碼點(diǎn)擊登陸觸發(fā)斷點(diǎn)。到Hex View-1右擊同步R0寄存器

根據(jù)R0寄存器的地址找到存放的數(shù)據(jù),可以看到該值是一個字符串,字符串前一部分就是我們上面取到的簽名值,后面一部分是時間戳,把這個字符串復(fù)制一下以遍后面驗(yàn)證使用

R1寄存器中存放的值是16進(jìn)制數(shù)值2D, 轉(zhuǎn)換為十進(jìn)制為45,正好是R0寄存器存放的字符串的長度。

同步R2寄存器,因?yàn)镸D5Digest函數(shù)還沒有執(zhí)行,所以這里的值不是最終的結(jié)果,我們按F8繼續(xù)執(zhí)行

下圖標(biāo)出來的就是計(jì)算后的結(jié)果,那么這個MD5Digest和python的md5計(jì)算結(jié)果是否一樣呢?

經(jīng)過驗(yàn)證,發(fā)現(xiàn)結(jié)果是一樣的。本教程案例沒有遇到反調(diào)試,app加固等情況,加密函數(shù)的邏輯比較簡單容易處理,即使這樣,搞起來還是很費(fèi)勁的,app逆向需要掌握很多知識,只能慢慢啃,急不得。

如果覺得教程不錯,幫忙分享轉(zhuǎn)發(fā),謝謝!

喜歡文章,點(diǎn)個在看??

總結(jié)

以上是生活随笔為你收集整理的逆向so_安卓逆向 | 分析调试与so调用实战的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。