BruceFan's Blog

Stay hungry, stay foolish

0%

Android无源码调试

前几天通过从网上查阅相关资料,大体了解了一些Android无源码调试的方法,本文主要总结无源码调试的三种方法:

  • smalidea + Android Studio
  • IDA
  • 插桩(Instrumentation)

smalidea + Android Studio

1.安装

  • 下载插件smalidea
  • 进入Android Studio开始安装插件,进入Settings->Plugins点击Install plugin from disk选中下载的压缩包;
  • 点击apply

2.开启应用调试
要调试一个APK的DEX中的代码,必须满足以下两个条件:

  • APK中的AndroidManifest.xml文件中的Application标签包含属性android:debuggable=”true” (Android Studio中Build->Build APK产生的APK文件中就有这个属性);
  • /default.prop中ro.debuggable的值为1

可选方案:

  • apktool反编译app后在AndroidManifest.xml文件中插入android:debuggable=”true”
  • hook system debug(Xinstaller)
  • 修改boot.img

3.调试应用
1)使用baksmali反编译应用:

1
$ baksmali test.apk -o myapp/src

2)Android Studio导入项目:启动Android Studio->File->New->Import Project,选择上面生成的路径,选定src的上层目录myapp
3)选择Create project from existing sources,一路next;
4)导入后,将导航栏左上角的Android改为Project;
5)右键src目录,即smali的顶级目录,设定Mark Directory As->Sources Root
6)安装应用:

1
$ adb install test.apk

7)启动应用程序:

1
2
3
4
$ adb shell am start -D -n com.example.test/.MainActivity
$ adb shell ps | grep test
u0_a111 30659 181 869984 31672 ffffffff 00000000 S com.example.test
$ adb forward tcp:8700 jdwp:30659

8)在Android Studio设置远程调试:Run->Edit Configurations…,点左上角的+,选择Remote,设置如下:

9)Run->Debug,触发断点之后就可以动态调试了:

smalidea调试可以查看变量值(在右下角Watches中添加寄存器),但问题是单步调试跳的不准,不一定会跳到哪一步。

IDA

1.解压出APK的DEX文件classes.dex;
2.在IDA中加载这个DEX文件;
3.将光标移动到要下断点的行,按F2下断点;
4.打开一个Terminal:

1
$ adb shell am start -D -n com.example.test/.MainActivity

5.选择Debugger->Attach to process…将Debugger Attach到要调试的进程;

6.开始运行后按F9运行程序到断点,弹出的窗口cancel掉就行了;

7.在Debugger->Debugger windows->Locals窗口中有变量,但是无法正确显示。

IDA调试查看不了变量值,但是每一步跳的比较准,可以结合使用这两种调试方法:IDA查看运行流程,smalidea查看变量值。

Instrumentation

这个方法在之前的文章中介绍过,插桩的方法步骤比较复杂,但是实现的功能比较强大。而且可以在以前的基础上添加更多的方法,实现更多的功能,比如在一篇博客上看到的:

1
2
3
4
5
6
public static void PrintFunc()
{
Thread cur_thread = Thread.currentThread();
StackTraceElement stack[] = cur_thread.getStackTrace();
Log.d("bruce", stack[3].toString() + "[" + cur_thread.getId() + "]");
}

在需要调试的APK反编译出来的smali代码中添加一句:

1
invoke-static {}, Lcom/bruce/BFLog;->PrintFunc()V

就可以将当前执行的函数打印出来:

以后如果还有比较好用的方法,还会再来添加。
reference
http://wooyun.tangscan.cn/static/drops/tips-7181.html
http://blog.csdn.net/CharlesSimonyi/article/details/51989096
http://blog.csdn.net/charlessimonyi/article/details/52027563