0%

记录IDA动态调试APP

本文主要记录如何通过IDA动态调试SO层存在反调试的APK。

前言

最近在实践文章[原创]分析一个安卓简单CrackMe的过程中,当IDADebugger->attach进程后,APP就崩溃退出了。后来作者回复说是因为JNI_OnLoad中存在反调试。

自己查阅了相关资料,其中定位反调试位置主要参考[原创]Android APP漏洞之战(10)——调试与反调试详解中的so层过反调。

本机环境:MacOS Catalina、IDA Pro 7.0、pixel xl android 8.1.0

定位反调试

  1. 启动android_server

    1
    2
    3
    4
    5
    6
    7
    adb push android_server /data/local/tmp/android_server
    adb shell
    su
    cd /data/local/tmp
    mv android_server as
    chmod +x as
    ./as -p12344
  2. 端口转发

    1
    adb forward tcp:12344 tcp:12344
  3. 挂起程序,此时处于Waiting for Debugger状态

    1
    adb shell am start -D -n com.yaotong.crackme/.MainActivity
  4. 通过Android sdk工具Android Device Monitor查看端口

    1
    2
    cd ~/Library/Android/sdk/tools/
    ./monitor
  5. 打开IDA,点击菜单栏Debugger->attach->Remote ARMLinux/Android debuggerHostname填写localhost代表本机,Port填写12344。点击Debug options,勾选Suspend on process entry pointSuspend on thread start/exitSuspend on library load/unload三项,点击OK。attach进程com.yaotong.crackme,点击OK。点击菜单栏Debugger-Debugger options,再次确认勾选Suspend on process entry pointSuspend on thread start/exitSuspend on library load/unload。不然后续调试会出现异常退出的情况。

  6. jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8602,其中端口为步骤4的端口。

  7. 按F9调试,同时查看Output indow中目标SOlibcrackme.so是否加载。当目标SO加载后,在Path窗口搜索JNI_OnLoad函数,下断点,进行单步调试。定位具体反调试位置。以下来自文章[原创]Android APP漏洞之战(10)——调试与反调试详解下面使用F8开始单步调试了,发现每次到达BLX R7这条指令执行完之后,JNI_OnLoad函数就退出了,这个地方存在问题,可能就是反调试的地方了。我们再次进入调试,看见BLX跳转的地方R7寄存器中是pthread_create函数,到了这里我们就找到了出问题的地方,接下来我们只需要修改对应的位置就可以了。可以把BLX R7这条指令给nop掉,也就是把这条指令变成空指令(相当于删除这条指令)这样apk就不会新建线程去执行检测代码了。

Patch program

定位到反调试的位置后,有两种方式可以nop掉指令。

  1. Hex View视图右键Edit修改成00 00 00 00,然后再右键选择Apply changes
  2. 菜单栏Edit->Patch program->Patch Bytes,然后同目录再选择Apply patchs to input file保存更改。

这样就过掉一个简单的反调试了。

回编译

主要使用工具apktool,官网:https://ibotpeaches.github.io/Apktool/

  1. 反编译

    1
    apktool d com.yaotong.crackme.apk -o com.yaotong.crackme

将上一步patch掉反调试的SO放到com.yaotong.crackme/lib目录下再进行回编译。

  1. 回编译

    1
    apktool b com.yaotong.crackme -o com.yaotong.crackme_unsigned.apk

签名

要想把上一步回编译好的apk安装到手机上,还需要一步:签名。

  1. 生成keystore证书

    1
    keytool -genkey -v -keystore myApp.keystore -alias myApp.keystore -keyalg RSA -validity 3000
  2. 签名

    1
    jarsigner -verbose -keystore myApp.keystore -signedjar com.yaotong.crackme_signed.apk com.yaotong.crackme_unsigned.apk  myApp.keystore

具体参数选项含义可以通过keytool -genkey -hjarsigner -h来查看。

经过patch掉反调试以及重新签名的apk就可以愉快地进行IDA动态调试了。

其它知识

反调试检测

现在很多应用防止别的进程调试或者注入,通常会自我检测。原理就是:循环检测/proc/[mypid]/status文件,查看TracerPid是否为0,如果不为0,表示被其它进程trace了。那么这时候就直接退出程序。因为现在的IDA调试时需要进程的注入。进程注入现在都是使用Linux中的ptrace机制。那么这里的TracerPid就可以记录trace的pid,就可以发现程序被哪个进程注入了。或者是被它调试,进而采取一些措施。

IDA调试的整体原理

首先需要在被调试端放一个程序,用于IDA端和调试设备通信,这个程序就是android_server。因为要附加进程,所以这个程序必须要用root身份运行。这个程序起来之后,会开一个端口23946(默认端口)。使用adb forward进行端口转发到远程调试端,这时候IDA就可以和调试端的android_server进行通信了。后面获取设备的进程列表、附加进程、传递调试信息,都可以使用这个通信机制完成。IDA可以获取被调试进程的内存数据,一般是在/proc/[pid]/maps文件中,所以在使用ctrl+s可以查看所有SO文件的基地址,可以遍历maps文件即可做到。

参考文章:

  1. [原创]分析一个安卓简单CrackMe
  2. [原创]Android APP漏洞之战(10)——调试与反调试详解
  3. Android逆向之旅---动态方式破解apk进阶篇(IDA调试so源码)
  4. Android APK生成证书并签名方法
您的支持将鼓励我继续创作!