动态调试apk(Java 层)
作案工具
- Android Studio(我的版本是 4.0.1)
- Android Killer
- smalidea 插件
工具及示例下载链接:
链接:网盘
提取码:g1wi
工具安装
Android Killer
该软件集成了 apktool、dex2jar、jd-gui 等优秀安卓逆向工具,一方面方便进行 apk 的解析(目录结构、反汇编、反编译等),另一方面方便回编译、打包、签名。虽然用 baksmali、smali 的 jar 包也可以做到 dex2smali 和 smali2dex,但能用有 GUI 的集成工具为什么要用命令行呢(((
smalidea 插件
下载地址 https://bitbucket.org/JesusFreke/smali/downloads/?tab=downloads
下载 smalidea-0.0x.zip(zip 格式),无需解压
打开 AS ,选择 File -> Settings -> Plugins
点击图中的齿轮图标,选择 Install Plugin from Disk
,并指定刚才下载的 zip 压缩包,Apply 后重启 AS
不过此时仍无法在 smali 文件中下断点,因为在 AS4.0 中还绑定安装了一个 smali 语法高亮的插件——Smali Support,如图:
该插件抢占了 smalidea 对于 *.smali 文件的解析权,在 Settings 的 Editor -> File Types
中找到 Smali:
可以看到有两个,上面那个是 Smali Support 的,下面才是 smalidea,点击右边的减号去掉 Smali Support 对 *.smali 的解析,点击第二个 Smali,并点击加号添加 smalidea 对于 *.smali 的解析
Apply 一下,现在就可以愉快地在 smali 文件中下断点了(点击行号旁边的空白处)
调试 apk
现在展示如何调试一个拿到手的 apk,本例 apk 是我套着模板写的一个用户登录界面,分别生成了 release 版本(已签名)和 debug 版本(未签名,testOnly),下图是应用的界面
逻辑很简单,email 一栏是 in1t
,password 一栏是 123456
的话就会显示 welcome! in1t
下面是详细的步骤,共 6 步
使用 Andoird Killer 反编译
在 Android Killer 中打开目标 apk,等待其反编译,当弹出是否需要对当前工程进行分析的窗口时,选择“否”即可。在工程管理器中可以看到 MyApplication 反编译后的 smali 代码
这些反编译后的代码会保存在 Android Killer 根目录下的 projects
目录中
另外,点开 AndroidManifest.xml
,确认 <application>标签
中是否有 android:debuggable="true"
,如果有的话,可以直接跳到下一步
如果没有,就需要修改该文件,为其添加 debuggable 属性,不然后面附加进程的时候会找不到该 apk
修改后需要重新编译、签名,这些可以在 Android Killer 中一键完成,不过需要预先配置
首先是通过以下指令生成密钥库,其中 alias、keypass、keystore、storepass 可以根据自己的需求进行修改
1 | keytool -genkey -alias in1t -keypass 123456 -keyalg RSA -keysize 1024 -validity 3650 -keystore D:\AndroidStudioProjects\appkey.keystore -storepass 123456 |
一路回车,最后输入 y 来确定生成,在 Android Killer 中 进行配置,保证勾选上 编译完后自动签名
下方的签名处点击添加,按图填写,点击确定
来到 Android 选项卡,点击编译下面的小三角,选择刚添加的签名配置,点击编译
编译签名完成后,下方的状态栏会显示 apk 的生成路径,第 4 步安装 apk 时,请安装这个加了 debuggable 的 apk
在 AS 中导入反编译后的项目并下断点
选择 File -> New -> Import Project
,并选择刚才反编译项目的 Project 目录
,
一路 next 后,打开 Project 视窗,找到想下断点的 smali 文件双击打开,并点击行号旁边的空白处下断点
运行模拟器
我用的是在 AS 中下载的模拟器,连接第三方模拟器的方法请自行百度,在 AVD Manager 中打开模拟器
在模拟器中安装 apk
打开模拟器后,在 cmd 中输入 adb install apk路径名
来安装 release 版本的 apk,如果出现如下错误,表示该 apk 是 debug 版本,需要额外加一个 -t 选项来安装,即 adb install -t apk路径名
可以看到,应用已经成功安装
以调试模式启动 apk
在Android中,除了从界面上启动程序之外,还可以从命令行启动程序,使用的是命令行工具 am
在 cmd 中输入 adb shell am start -D -n package_name/activity_name
-D 参数表示允许调试,-n 用于指定需要启动的程序
其中,package_name 与 activity_name 在该 apk 的 AndroidManifest.xml
可以获取。在 Android Killer 中打开解析后的 AndroidManifest.xml,<manifest>标签
中有一个属性叫 package
,其值为 package_name,在本例中为 com.example.myapplication
不论是否有多个 Activity,activity_name 一般都用程序入口 Activity 的,这里为 com.example.myapplication.ui.login.LoginActivity
所以在本例中,需要在 cmd 中输入:
此时,模拟器中应有如下提示:
使用 AS 附加等待调试的 apk
点击 AS 工具栏中的 Attach Debugger to Android Process
,在弹出的窗口中选中 Show all processes
,并选择待调试的进程,点击 OK
现在已经开始调试了,在模拟器的两个输入框中输入用户名及密码,点击登录按钮,即可断在之前下断点的地方
需要注意的是,单步步过在这里不太好使,因为 java 的一行源码被编译成了多行 smali 代码,单步执行(这里更像是单行执行)一次会跳过多行 smali 代码。我更倾向于将光标放在希望调试器停下的位置,然后使用 Run to Cursor (Alt + F9)
来实现 smali 代码的单行调试
譬如此处:
源码中的 117 行代码被编译成了 4 条 smali 代码,此时程序停在调用 getText() 函数的地方,现在我想看看调用完 getText 后 v2 的值是什么,如果使用 F7 单步步入,那会进到 getText 函数,如果使用 F8 步过,那就会直接执行完这四条指令去到下面的 .line 116 处对于 login 的调用。所以这里将光标放在调用 toString 处,点击下方 Run to Cursor 按钮,再在右下角的 Watches 窗口添加 v2,即可查看此时 v2 的值