#Anroid逆向學習從編寫so到靜動態調試分析arm的一次總結 ##1、前言 最近跟着教我兄弟學逆向這篇教程學習Android逆向,在第七課後做業反覆折騰了好幾天,正好在折騰的時候對前面的學習總結一波,動態分析一下arm彙編(靜態看arm感受跟看天書沒什麼區別。。。),涉及到的東西都很簡單基礎,大神就不要浪費時間了!!!java
##2、所使用到的工具android
- Android studio v3.3
- IDA v7.0
- AndroidKiller
- ApkToolBox v1.6.4
##3、編寫所須要用到的so和apk文件 關於怎麼編寫Android應用和so文件,網上一大堆超詳細的教程,這裏就再也不細說了,只簡單說一下so文件的編寫過程。
一、新建一個java類,使用System.loadLibrary("so_name");
來加載so文件,在建立native層函數,我這裏建立的一個名爲add,形參爲兩個整數,返回值爲一個整數的native函數 二、在Android Studio的終端使用javac java_name.java
命令編譯剛纔添加的類 三、跳轉到java目錄,生成.h文件,生成命令格式爲javah -jni Android項目包名.類名
四、在main文件夾下面新建jni文件夾,而後將上一步在java文件夾下面生成好的.h文件複製到剛新建好的jni文件夾下面,並在相應函數下面編寫邏輯代碼(我這裏比較簡單,只實現了兩個整數相加並返回結果),而後新建一個util.c的空文件(不加上這個文件會報錯。。。) 五、在build.gradle文件中添加相應配置,而且在src目錄下創建CMakeLists.txt文件 [代碼]shell
ndk{ moduleName "myjni" } externalNativeBuild{ cmake { cppFlags "" abiFilters "arm64-v8a","armeabi-v7a","x86","x86_64" } } } externalNativeBuild { cmake { path "CMakeLists.txt" } }
[CMakeLists文件內容]app
\# 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} )
六、在Build->Rebuild Project
編譯好so文件,so文件位置存放在build->intermediates->cmake->debug->obj
目錄下,選取相應的so文件在main的JniLibs目錄下(該目錄須要本身創建),而後編譯好apk便可 tcp
##4、破解該apk,將結果變爲調用該so中該函數時不管參數輸入多少,返回結果恆等於0 一、將apk拖進夜神中,觀察一波(這裏結果爲52,參入參數爲22和30) ide
二、將該apk拖進AndroidKiller中反編譯,在jd中查看java代碼(這裏就再也不分析smali代碼了,直接看java),能夠看到在關鍵函數中調用myTest類的add函數,在jd中雙擊該類跟進,發現加載了so文件,而且定義了native函數int add(int,int),因此通過上面分析要修改返回值須要修改so文件(也能夠在smali層直接修改,但這篇文章主要講so,若是有興趣的能夠去smali層修改) 函數
三、使用ida靜態分析myjni這個so文件。在AndroidKiller中找到該so文件,右鍵打開文件路徑,而後拖進ida中,在export窗口(提供給外界調用的函數名集合的一個窗口)中找到add函數,雙擊進入該函數,能夠看到彙編指令就這兩條ADDS R0, R3, R2
BX LR
(由於個人函數功能過於簡單因此就2條彙編指令,做爲學習只有就不要糾結那麼多了),第一條意思很簡單就是將r3和r2寄存器的值相加複製給r0寄存器,第二條指令意思是跳轉到lr寄存器中所指地址中去執行下面的指令(lr是鏈路寄存器,用於保存函數返回地址,就是至關於存儲了函數返回後下一條指令的地址) 四、動態調試。靜態其實看着仍是挺懵逼的,做爲一個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函數中)。工具
三、通過上一步的配置,咱們以及成功進入到要調試的函數中了,如今差開始調試了,在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。學習
四、通過上面的動態分析,咱們已經很清楚的知道該函數彙編運行過程--將一個參數值傳入寄存器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...便可保存修改。gradle
五、再將獲得修改的so文件複製,在AndroidKiller中替換lib目錄下全部so文件,而後從新編譯便可,在將獲得的apk文件安裝好便可看到點擊按鈕顯示結果爲0。
##5、結束語 相關附件連接:連接:https://pan.baidu.com/s/12a_l4JcuJj4i6nJty0xXXQ 提取碼:licr 。