IDA 静态调试和动态调试

Fn+f5转成c语言伪代码

shift+f12 查看文件中所有常量字符串的值

ctrl+s查看so文件字段信息  

JNI函数方法名还原 选中v3 按y建 作用(类型还原)


v3 + 676 前面是一个指针 比如 *(_DWORD *)v3 + 676 表示 v3 是JNIEnv *类型
形如 *(_DWORD *)vX + YYY 皆是
可选中v3 按y键进行类型替换,替换为JNIEnv *
为伪代码添加注释 : /

g跳转到指定地址

IDA动态调试

目的:找到自毁程序的内置密码

IDA下载配置 mac需要在10.15以下版本才可以使用

首先,需要准备安卓真机,最好是pxiel 6.0的系统,

将ida文件夹里面的dbgsrv下的android_server放入真机的/data/local/tmp/下 添加777权限 chmod 777 xxx

 ./android_server运行服务并且监听端口23946 adb forward tcp:23946 tcp:23946

 后面再运行ida 32 点go打开ida new是静态调试

我们选择 debugger-->attach -remote ARMLinux/Android debugger

 

输入127.0.0.1点ok。会出来如下界面,如果说链接拒绝,请检查前面启动服务和监听端口是否正常

我们找到需要调试的进程com.yaotong.crackme点ok

稍等一会儿之后会出来如下界面

 由于我们之前说过,这个函数的验证密码的函数叫securityCheck

我们现在需要跳到这个函数的内存地址,去调试这个函数,如何找到这个函数的内存地址呢

函数运行实际内存地址=头so文件的基地址(根据实际运行情况,此基基地值app每次执行的值都不一样)  + 该函数的偏移量(固定不变.so文件可查看)

我们现在另外打开一个ida 以静态方法打开此apk的libcrackme.so文件找到securityCheck函数的偏移量为11A8

 再打开以动态方法调试的ida 按control+s(显示app中的so文件)

我们找到libcrackme.so 找到第一个标有x权限的so文件

打开

 显示的内存地址为F4395000

 我们打开电脑上的科学计算器,计算方法以16进制进行计算

用F4395000+11A8得到的就是实际的securityCheck运行的的内存地址 F43961A8

我们在动态的ida里面按下G 输入刚才得到的内存地址,跳到此内存地址

 跳转后的界面如下

 现在我们对此函数进行调试,我们需要在Java_com_yaotong_crackme_MainActivity_securityCheck函数这里进行打断点调试,右键addbreakpoint

断点后的样子

 然后我们点左上角点绿色三角形运行按钮,让程序继续运行

我们再在手机里随便输入个密码比如1111,点击输入密码,让程序进入下一步

(打上断点以后,程序需要点运行按钮才能继续运行,此时我们才能输入密码,不然程序会一直卡在那里,动不了)

 调试有两个快捷键,F7 和F8   

F7单步调试,要进入函数
F8单步调试,不进入函数

一般都是F8。进入函数步骤太多了。看不出来。我们F8尝试调试

发现报错,没关系 我们再次尝试

再次报错,一直都报错,此时 我们想到,可能是此app用了反调试

IDA调试原理 是利用Linux系统 ptrace 来实现
当应用被调试时,应用内存里的TracerPid 字段就不为0

进入设备查看ptrace字段:
//进入设备
adb shell
//获得APP的进程ID

ps | grep 包名
//打印该APP里内存状态信息
cat /proc/pid(进程ID)/status

TracerPid为 0代表 没有被调试,不为0代表在被调试。
反调试的原理,检测TracerPid是否被占用,如果被调用。阻止app继续运行

反反调试
    动态调试,找到检测TracerPid的代码,不执行此代码
方法:
  此检查代码一般在.init_arra 和 JNI_OnLoad两处。此函数都是在程序最开始运行的时候执行
  在JNI_OnLoad函数出打断点调试,找到检测TracerPid的代码,修改so文件的执行函数,不执行此代码

IDA调试反调试小经验 如何找到反调试代码:
  结合IDA静态时的代码,观察程序逻辑
  指令一般会整过执行完,直到函数末尾。
so文件在加载阶段会执行JNI_ONLoad函数。此后便不再执行。要在so文件加载阶段才能给JNI_ONLoad打断点。

分下面几个步骤:

    1.修改APP的AndroidManifest.xml文件的application字段,再后面加上一段代码android:debuggable=''ture".然后重新打包签名安装

    2.运行的时候检查是否允许debuggable项

adb shell dumpsys package com.yaotong.crackme(一定要有debuggable 没有的话会导致后面附加进程出现致命错误,无法附加的VM)

 3.以调试模式启动APP,APP此时会挂住

  adb shell am start -D -n 包名/.类名

  adb shell am start -D -n com.yaotong.crackme/.MainActivity(MainActivity是application 下的第一个activity.此activity为初始启动界面)

 挂起 的程序就像上图这样。一直等待调试,

4.我们打开ida动态调试,对此app再次进行调试

打开好找到 Debugger-->Debugger options 勾选下图红色选框内容

 再点击一下左上角对运行按钮

 5.再进入设备查看进程对PId ps |grep 包名  或者frida-ps -Ua也可以

   

6.使JDB命令使程序恢复运行

adb forward tcp:8700 jdwp:18776(APP的PID)
jdb -connect com.sun.jdi.SocketAttach:hostname=127.0.0.1,port=8700

7.so文件在被加载时。ida会停住此文件对加载,我们用control+s来一步步查看libcrackme.so文件是否被加载。并且加载对so文件需要有x权限

如果未加载。我们再点击左上角对运行按钮,来一步步对尝试,如此反复,直到出现带有x权限对libcrackme.so文件

 点进去,我们得到libcrackme.so文件本次运行的基地址,我们现在需要跳转到JNIONLOAD函数里 对此函数进行调试 G ,然后和JNI_onload内存值相加

 得到这样的图

现在我们对JNI_onload进行打断点 点左上角的运行三角形,让程序进行运行。F8进行调试

(对JNI_inload进行调试是找出此段代码中检测tracepid的代码,对检测tracepid的代码进行定位,找到 pthread_create() 的位置。后修改so文件的十六进制内容,从而让此段代码不执行)

每一步的F8调试,我们都一一都找,鼠标放上去,看到里面运行的代码,找寻 pthread_create这个函数,由于这个函数是一直不停的去检测,应该是个while循环,我们可以按照里面的箭头,线路图,是否有往回走的,来判断pthread_create大致在哪里

 如图 ,找到了 位置在BLX R7位置。现在我们到静态so文件里面 JNI_ONload函数里找到blx r7的执行命令

鼠标点在blx R7 在点hexview1   阴影的地方就是该函数的运行指令的16进制

 我们现在把37 FF 2E E1复制一下,用文本方式打开so文件,在里面搜索37 FF 2E E1 将搜到的37 FF 2E E1全部改为 00 00 00 00,

让指令变为空指令

改完以后报错,再重新打包,签名 安装

安装完成后,我们就可以重新对securityCheck进行动态调试了

继续接之前的

然后我们点左上角点绿色三角形运行按钮,让程序继续运行

我们再在手机里随便输入个密码比如1111,点击输入密码,让程序进入下一步

(打上断点以后,程序需要点运行按钮才能继续运行,此时我们才能输入密码,不然程序会一直卡在那里,动不了)

现在继续调试就不会报错了

我们一步步的F8向下走。看看程序执行,(在此之前在app上随便输入个密码)

我们试想这个密码肯定是错的。程序会判断密码是对是错,如果错了,肯定会走错的流程,对了肯定走对的流程,我们一步步的F8,发现

 发现红红色圈子的箭头一直闪,正常应该走短的哪个箭头,结果却绕过短的执行了长的,我们把鼠标放在R0上

发现寄存器里面的值正好是我们输入的1111 由此可判断这部分函数应该是判断密码和输入的是否正却,我们F5转化为伪代码进行查看

仔细看这段代码 判断v7不等于v5 break ,v7是v6赋值的。我们把鼠标放在v6上。发现v6的值为aiyou,bucuoo 前面的unsigned __int8可以上网上查下含义,大致的意识是定义类型,

我们把得到的密码输入进入尝试,发现密码正确,完成

学自猿人学

原文地址:https://www.cnblogs.com/wuxianyu/p/14276369.html