翻译:无名侠
引言
自从IDA v6.6 开始就能够调试安卓应用程序,也包括一个源码级的调试器。这个教程将会讲解如何建立并且开始一个Dalvik调试会话。
安装Android SDK
首先,我们应该安装安卓SDK,可以通过官方网站下载 http://developer.an droid.com/sdk
我们不需要ADT Bundle,所以选择”SDK Tools Only”,只要下载它就可以了。
环境变量
IDA 需要知道 adb模块在什么地方,并且尝试各种各样的方法去在本地自动的寻找它。通常IDA通过路径去寻找adb,但是如果失败了,我们就需要定义环境变量 ANDROID_SDK_HOME或者ANDROID_HOM 来指定Android SDK的安装目录。
Android 设备
运行安卓仿真器或者通过USB来连接一个安卓设备。
关于创建AVDs(Android Virtual Devices)的信息和如何运行仿真器可以在这里找到:Using the Emulator.
关于准备一个物理设备的信息可以在这里找到:Using Hardware Devices.
检查设备是否能被计算机识别,通过adb:
$ adb devices
List of devices attached
emulator-5554 devic
安装应用程序
IDA 认为被调试的应用程序已经安装在安卓虚拟机或者安卓设备上。
请在我们的网站上下载 MyFirstApp.apk 和MyFirstApp.src.zip我们将要用这个应用程序来讲解后面的教程。
我们将要使用adb来安装应用程序:
adb –s emulator-5554 install MyFirstApp.apk
加载应用程序到IDA
我们能把apk或者dex文件拖入IDA。如果我们拖入的是apk文件,IDA会显示该文件的内容并且询问我们选择我们需要反汇编的文件。我们选择 classex.dex 文件:
Dalvik debugger options
在启动调试之前,调试器允许我们检查调试配置。 到“Debugger/Debugger Options/Set specific options”
译者补充图:
原版图:
ADB执行文件
正如上面提到的,IDA试图定位adb 的位置,如果IDA失败了,那么我们可以在这里设置adb的路径。
Fill from AndroidManifest.xml
按下这个按钮,然后给IDA指明一个APK(这个就是要调试的APK)。IDA获取包名和应用程序的activity 名字来启动。
预处理 BPTs
IDA 能帮助我们在启动调试前为activity 类的方法设置断点。
源码路径
为了 使用源码源码级调试器,我们需要设置应用程序的源码路径。我们能在Options/Sources path … 菜单项中设置。
Dalvik 调试器认为应用程序的源文件在当前目录.下。如果这不是实际的情况,我们能指定源码路径到源码的真实路径。
设置断点
在启动应用程序以前,设置一些合理的断点。我们可以依赖IDA的决定也可以自己设置断点。一个非常好的候选断点是 activity的“onCreate”方法。
我们能使用一个activity 的名称和方法的名称 “onCreate”来设置一个断点:
自然地,我们设置其他的断点可以在任何时间,比如,我们能稍后来完成它,当我们暂停应用程序的时候。
开始调试
至少我们现在可以启动调试了。检查Dalvik 调试器 被选中,通常它是IDA自动选择的:
如果调试器选择正确了,我们就准备启动调试会话。 这里有两种方式来启动:
1. 启动一个新进程(Start process)
2. 附加进程(Attach to process)
1. 启动进程
为了启动一个新的进程,只用按F9或者选择“Debugger/Start process” 菜单项。
Dalvik调试器会启动应用程序,等待直到应用程序已经准备好并且打开一个调试会话。
我们可能会等待执行程序接收到断点或者按下“Cancel”按钮来暂停应用程序
在我们的例子里,让我们等待,直到onCreate() 方法的断点停下来。
2. 附加进程
代替启动进程的是附加进程,我们能够附加一个正在运行的进程并且调试它。可以在“Debugger/Attach to process…” 找到。 IDA会显示活动进程的列表。
我们只选择我们想调试的进程
Dalvik 调试器的细节
所有传统的调试动作比如步过,步入,运行到返回和一些其他的操作都能使用。如果应用程序的源程序能被访问,IDA会自动的切换到源码级调试器。
以下是Dalvik虚拟机调试器特性:
在Dalvik中,这里没有栈,也没有SP寄存器,唯一可用的寄存器是IP寄存器。
IDA把方法框架中的寄存器 (v0,v1,v2...) 是作为局部变量。我们能够在Debugger/Debugger Windows/Locals window (见后文)中看到它们的身影。
栈跟踪可以在 “Debugger/Windows/Stack trace” 中看到,或者按下<Ctrl-Alt-S>调出。
当应用程序运行的时候,它可能执行一些系统代码。如果我们通过“Cancel”按钮打断程序的执行,经常会发现我们在应用程序的外部,在系统代码中。 在这种情况下,IP寄存器的值是0xFFFFFFFF ,并且栈跟踪器只显示了系统调用和许多的0xFFFFFFFF 。这意味着IDA不能定位程序当前的位置。我建议你多在程序中设置一些断点,重新开始执行,并且通过点击窗口,选择菜单等方式与应用程序交互。当我们步出了应用程序,这样的情况也会发生。
使用 “Run until return” 命令来返回源码级调试器,如果你不小心单步进入了一个方法,并且IP寄存器的值是0xFFFFFFFF
局部变量窗口
IDA把方法框架中的寄存器(v0.v1.v2...)当作局部变量。可以在
“Locals” window from the “Debugger/Debugger windows/Locals” 菜单功能中查看它们的值。
此时此刻,调试器暂停在程序的“onCreate”方法断点上。让我们打开“Locals”窗口,我们能够看到如下东西:
如果这个框架的信息是有用的(符号表是完整的),那么IDA会显示方法的参数,这个方法的局部变量以及一些没有符号的变量。另外,一些变量的值不会显示,因为IDA不知道它们的类型。
没有类型的变量会被标记为“Bad Type”在局部变量窗口
为了看见这些变量的值,在这种情况下请用“Watch view” 窗口(见下文)
Watch view window
为了打开“Watch view”窗口,请选择“Debugger/Debugger windows/Watch view”菜单。
在这个窗口,我们能添加任何变量来查看它的值,如图:
请注意,我们需要为变量指定类型,如果这个变量是未知的。使用C风格:
(Object*)v0
(String)v6
(char*)v17
(int)v7
我们不需要为对象变量指定真实的类型,“(Object*)”就足够了。IDA能够推导出真正的对象类型。
注意!一个错误的类型可能或造成Dalvik虚拟机崩溃
我们的建议是:不要把integer变量 设置为object类型。Dalvik虚拟机通常会崩溃,如果我们这样做。 在实际应用中,整数(int)是安全的。如果“object ID safety check”选项选中的话,IDA会防止这种情况,唯一的缺点是这个选项增加更多的开销。记住下面这句话,请不要把这些留在“Watch view” 太多时间。 在其他能改变它们类型的指令执行前删掉它们。
如果遇到一些错误
· 在“Debugger specific options”设置中检查adb的路径。
检查包名和activity 名称。
· 检查模拟器/设备 是否被adb 识别,尝试重启adb守护程序。
检查这个应用程序是否成功安装在模拟器或者设备上。
· 检查 IDA 的 output 窗口,查看所有错误和警告。
打开更多的调试输出。在启动IDA时用 -z50000 命令行开关打开