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");來加載so文件,在創建native層函數,我這里創建的一個名為add,形參為兩個整數,返回值為一個整數的native函數
創建java類
2、在Android Studio的終端使用javac java_name.java命令編譯剛才添加的類
編譯java文件
3、跳轉到java目錄,生成.h文件,生成命令格式為javah -jni Android項目包名.類名
生成.h文件
4、在main文件夾下面新建jni文件夾,然后將上一步在java文件夾下面生成好的.h文件復制到剛新建好的jni文件夾下面,並在相應函數下面編寫邏輯代碼(我這里比較簡單,只實現了兩個整數相加並返回結果),然后新建一個util.c的空文件(不加上這個文件會報錯。。。)
新建jni文件夾
編寫函數邏輯代碼
5、在build.gradle文件中添加相應配置,並且在src目錄下建立CMakeLists.txt文件
添加ndk配置
[代碼]

 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即可
編譯so


四、破解該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層修改)
1
2
3

3、使用ida靜態分析myjni這個so文件。在AndroidKiller中找到該so文件,右鍵打開文件路徑,然后拖進ida中,在export窗口(提供給外界調用的函數名集合的一個窗口)中找到add函數,雙擊進入該函數,可以看到匯編指令就這兩條ADDS R0, R3, R2
BX LR (因為我的函數功能過於簡單所以就2條匯編指令,作為學習只有就不要糾結那么多了),第一條意思很簡單就是將r3和r2寄存器的值相加復制給r0寄存器,第二條指令意思是跳轉到lr寄存器中所指地址中去執行下面的指令(lr是鏈路寄存器,用於保存函數返回地址,就是相當於存儲了函數返回后下一條指令的地址)

4
5
6
7
arm
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的默認端口,因為木有反調試所以懶得改了)。
20
21
(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函數中)。

22
23
24
25
26
27
29
28
30
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。

31
32
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...即可保存修改。

37
38
3
33
34
35
5、再將得到修改的so文件復制,在AndroidKiller中替換lib目錄下所有so文件,然后重新編譯即可,在將得到的apk文件安裝好即可看到點擊按鈕顯示結果為0。

36
1


五、結束語

相關附件鏈接:鏈接:https://pan.baidu.com/s/12a_l4JcuJj4i6nJty0xXXQ 提取碼:licr 。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM