Anroid逆向學習從編寫so到靜動態除錯分析arm的一次總結
Anroid逆向學習從編寫so到靜動態除錯分析arm的一次總結
一、前言
最近跟著教我兄弟學逆向這篇教程學習Android逆向,在第七課後作業反覆折騰了好幾天,正好在折騰的時候對前面的學習總結一波,動態分析一下arm彙編(靜態看arm感覺跟看天書沒什麼區別。。。),涉及到的東西都很簡單基礎,大神就不要浪費時間了!!!
二、所使用到的工具
- Android studio v3.3
- IDA v7.0
- AndroidKiller
- ApkToolBox v1.6.4
三、編寫所需要用到的so和apk檔案
關於怎麼編寫Android應用和so檔案,網上一大堆超詳細的教程,這裡就不再細說了,只簡單說一下so檔案的編寫過程。
1、新建一個java類,使用System.loadLibrary("so_name");
2、在Android Studio的終端使用
javac java_name.java
命令編譯剛才新增的類3、跳轉到java目錄,生成.h檔案,生成命令格式為
javah -jni Android專案包名.類名
4、在main資料夾下面新建jni資料夾,然後將上一步在java資料夾下面生成好的.h檔案複製到剛新建好的jni資料夾下面,並在相應函式下面編寫邏輯程式碼(我這裡比較簡單,只實現了兩個整數相加並返回結果),然後新建一個util.c的空檔案(不加上這個檔案會報錯。。。)
5、在build.gradle檔案中新增相應配置,並且在src目錄下建立CMakeLists.txt檔案
[程式碼]
ndk{ moduleName "myjni" } externalNativeBuild{ cmake { cppFlags "" abiFilters "arm64-v8a","armeabi-v7a","x86","x86_64" } } } externalNativeBuild { cmake { path "CMakeLists.txt" } }
[CMakeLists檔案內容]
\# Sets the minimum version of CMake required to build the native
\# library. You should either keep the default value or only pass a
\# value of 3.4.0 or lower.
cmake_minimum_required(VERSION 3.4.1)
\# Creates and names a library, sets it as either STATIC
\# or SHARED, and provides the relative paths to its source code.
\# You can define multiple libraries, and CMake builds it for you.
\# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.AndroidStudio開始支援Cmake了,ndk感覺挺費勁的,這個是不是好玩點,,這裡是要生成的庫的檔名 libtest.so
\#這裡是liuxin
myjni \#so檔名字
\# Sets the library as a shared library.
SHARED
\# Provides a relative path to your source file(s).
\# Associated headers in the same location as their source
\# file are automatically included.對應的C檔案的目錄位置
src/main/jni/main.c)
\# Searches for a specified prebuilt library and stores the path as a
\# variable. Because system libraries are included in the search path by
\# default, you only need to specify the name of the public NDK library
\# you want to add. CMake verifies that the library exists before
\# completing its build.
find_library( \# Sets the name of the path variable.
log-lib
\# Specifies the name of the NDK library that
\# you want CMake to locate.
log )
\# Specifies libraries CMake should link to your target library. You
\# can link multiple libraries, such as libraries you define in the
\# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.指定依賴庫
\#這裡是liuxin
myjni \#so檔名字
\# Links the target library to the log library
\# included in the NDK.關聯日誌記錄庫檔案,在ndk目錄中
${log-lib} )
6、在Build->Rebuild Project
編譯好so檔案,so檔案位置存放在build->intermediates->cmake->debug->obj
目錄下,選取相應的so檔案在main的JniLibs目錄下(該目錄需要自己建立),然後編譯好apk即可
四、破解該apk,將結果變為呼叫該so中該函式時無論引數輸入多少,返回結果恆等於0
1、將apk拖進夜神中,觀察一波(這裡結果為52,參入引數為22和30)
2、將該apk拖進AndroidKiller中反編譯,在jd中檢視java程式碼(這裡就不再分析smali程式碼了,直接看java),可以看到在關鍵函式中呼叫myTest類的add函式,在jd中雙擊該類跟進,發現載入了so檔案,並且定義了native函式int add(int,int),所以經過上面分析要修改返回值需要修改so檔案(也可以在smali層直接修改,但這篇文章主要講so,如果有興趣的可以去smali層修改)
3、使用ida靜態分析myjni這個so檔案。在AndroidKiller中找到該so檔案,右鍵開啟檔案路徑,然後拖進ida中,在export視窗(提供給外界呼叫的函式名集合的一個視窗)中找到add函式,雙擊進入該函式,可以看到彙編指令就這兩條ADDS R0, R3, R2
BX LR
(因為我的函式功能過於簡單所以就2條彙編指令,作為學習只有就不要糾結那麼多了),第一條意思很簡單就是將r3和r2暫存器的值相加複製給r0暫存器,第二條指令意思是跳轉到lr暫存器中所指地址中去執行下面的指令(lr是鏈路暫存器,用於儲存函式返回地址,就是相當於儲存了函式返回後下一條指令的地址)
4、動態除錯。靜態其實看著還是挺懵逼的,作為一個arm彙編的初學者,真的是搞不清楚呼叫函式過程中引數傳到那個暫存器中去了,返回值跑哪裡去了(暫時只關注這兩點),所以那就動態除錯so吧(記住一定要用真機除錯,反正我用夜神模擬器除錯就木有成功過,網上有大佬分析說的是模擬器底層還是x86的彙編,不是arm,所以有各種各樣的奇葩錯誤無法解決)(而且要root)。
(1)、將手機連線好,並進入除錯模式,將ida的dbgsrv->android_server拷貝到手機的/data/local/tmp目錄下面(開啟cmd,輸入adb push ida路徑/dbgsrv/android_serevr /data/local/tmp
拷貝檔案至手機),然後輸入adb shell進入除錯模式下,執行su
獲取root許可權,cd /data/local/tmp
進入android_server所在目錄下面,chmod 777 android_server
賦予android_server檔案777(可讀可寫可執行)許可權,./android_server
執行android_server檔案,最後另外開啟一個cmd視窗,執行adb forward tcp:23946 tcp:23946
進行埠轉發(23946是ida的預設埠,因為木有反除錯所以懶得改了)。
(2)、在手機上點選要除錯的app啟動,然後開啟ida,在彈出的初始介面中,選擇go這個選項,直接進入ida,然後選擇Debugger->Attach->Remote ARMLinux/Android Debugger選項,在彈出的視窗中點選Debug Options選項,勾選下圖所示三個選項(這三個選項名字太長了,麻煩看一下圖吧),然後點選ok,在點選ok,彈出選擇程序的介面,找到要除錯的程序(可以使用serarch搜尋程序),點選,然後點選ok,然後ida會附加到要除錯的程序,在ida右側的module哪裡顯示了所有載入的so檔案,可以左鍵點選然後Ctrl+F搜尋so檔案(我這裡so檔名為libmyJni.so,所以我搜索my就行了),找到對應的so檔案後,雙擊即可彈出so檔案對應的函式框(我這裡是add函式),然後雙擊對應的函式,ida會跳轉到這個函式中去(我這兒就是跳轉到了add函式中)。
3、經過上一步的配置,我們以及成功進入到要除錯的函式中了,現在差開始除錯了,在ADDS R0, R3, R2
處下一個斷點(滑鼠左鍵點選這行彙編程式碼,然後按F2即可下斷點),然後按F9執行,在手機上點選按鈕,即可看到程式停在了這行程式碼處,然後按F8單步除錯,在右邊暫存器處可以看到相關暫存器的16進位制值,這裡我們可以看到r0暫存器的16進位制值為34(10進製為52),可見函式返回結果所用的暫存器為r0,r2暫存器16進位制值為16(10進位制值為22),對應了我們傳進去的第一個引數22,r3暫存器的16進位制值為1E(10進製為30),對應了我們傳進去的第二個引數30。
4、經過上面的動態分析,我們已經很清楚的知道該函式彙編執行過程--將一個引數值傳入暫存器R2,第二個引數值傳入暫存器R3,相加結果返回值送入暫存器R0。現在我們需要將結果很等於0,那麼我們只需將R0復值為0返回即可。具體思路是將ADDS R0,R2,R3
這行彙編程式碼改為MOV R0,#0
即可。現在我們開啟ida匯入so檔案,找到ADDS R0,R2,R3
,我們可以點選ida的選單欄的Options->General,在彈出的視窗中,將bytes改為4,即可顯示處彙編指令對應的機器碼,現在我們只需要將對應的機器碼修改為mov R0,#0
對應的機器碼即可(可以用ApkToolBox這個工具的arm轉機器碼這個功能檢視彙編對應的機器碼)。我們可以使用patch來修改對應的機器碼,首先,滑鼠左鍵點選要修改的那行彙編程式碼,然後我們點選選單欄的Edit->Patch program->Change bytes,在彈出的視窗修改對應的機器碼(因為是Thumb模式,所以修改兩個位元組即可,這裡對應的修改為的機器碼為00 20),然後點選選單欄的Edit->Patch program->Apple patches to input file...即可儲存修改。
5、再將得到修改的so檔案複製,在AndroidKiller中替換lib目錄下所有so檔案,然後重新編譯即可,在將得到的apk檔案安裝好即可看到點選按鈕顯示結果為0。
五、結束語
相關附件連結:連結:https://pan.baidu.com/s/12a_l4JcuJj4i6nJty0xXXQ 提取碼:licr