安卓底层 native 代码的调试

4,679 阅读4分钟

吕元江,2019年1月加入去哪儿网,现负责app的分析和设备指纹反爬事项,对app脱壳,java/nativec层加解密算法分析还原有丰富经验。


1. 背景

用于熟悉了解 dalvik 虚拟机中类的加载流程(native层)

  1. 有 APP 源码情况如何配置,可以在 Android studio 实现图形化调试(IDE 自带功能)。
  2. 无 APP 源码的情况下如何实现图形化调试。

2. 环境要求配置

  1. Android Studio版本:2.2以上(低版本不支持 native 调试)
  2. 安装插件:LLDB 调试器 ( lldb.llvm.org/ )

image.png

  1. 一份编译好的安卓系统源码(Android4.4.4)

3. 有 APP 源码的情况

  1. 创建一个 Android 工程(作为调试的目标进程)

  2. 带调试符号文件的替换

    包含调试符号的文件都保存在编译后的 symbols 目录下

    手机中原有的/system/lib/libdvm.so 替换成带调试符号信息的 libdvm.so (编译后的安卓系统源码out/target/product/hammerhead/symbols/system/lib/libdvm.so)

  3. 为目标进程-配置调试模式

    选择调试模式-Native 模式,在工具栏中-选择点击运行下面的按钮 Edit Configuration:配置好后名字为 APP

image.png

  1. 配置之后,直接以 debug 模式运行 APP\

  2. 手机出现 Wating for Debuger 界面后点击 Android studio 调试器中的暂停按钮 如下有三个窗口:Frames,Variables,LLDB,分别用于查看函数调用堆栈,变量查看,LLDB 交互。

image.png

  1. 在 LLDB 交互界面通过命令下断点,然后运行,触发断点后如下图:

可以使用 F7 F8 F9 等命令,进行可视化调试。但是不能在 IDE 中直接下断点,只能通过 LLDB 命令下断点,其中为了方便可视化调试有两个下断点的命令比较实用:

A #根据函数名下断点

br s -n DalvikdalviksystemDexFiledefineClassNative

B #根据文件名配合行号下断点

br set --file dalviksystemDexFile.cpp --line 387 或者 br s -f dalviksystemDexFile.cpp -l 387

image.png

  1. 可通过单步调试对感兴趣的其他模块进行调试,如 libdvm.so 等

4. 无 APP 源码的情况调试 libdvm.so

场景:在修改 dalvik 重新编译后,想对修改后的代码进行调试,自定义的 libdvm.so 运行过程中遇到崩溃定位。

在没有 APP 源码的情况下无法在 Android studio 上实现可视化调试,常见的是通过 gdb,或者IDA。

本次说说用 LLDB 如何进行远程调试。

LLDB 常用命令:

命令功能作用
p *(Type *)addr打印结构体
po 对象.属性查看某个结构体或对象中的属性
br s -n 函数名对函数名下断点
b **.m:NUM对某文件设置行断点
br del 断点编号删除断点
ta v查看全局变量
ta v baz//某个具体全局变量 baz
fr v查看本地变量
fr v bar//查看某个具体变量,其中 bar 为变量名
s步入
n步过
c继续运行
wa s v b将变量 b 设置为观察点
watchpoint l查看观察点
watch del 观察点编号删除观察点

前提条件:

****目标 APP 必须为可调试-我们编译的 rom 为 debug 版本,可以实现调试任意 APP 功能。

LLDB 使用比较简单具体步骤如下:

  1. 将lldb-server push 到手机 /data/local/tmp 目录下 lldb-server 位于 Android/Sdk/lldb/3.1/android/armeabi 目录下 image.png

  2. 在手机上给 lldb-server 赋予可执行权限

chmod 777 lldb-server

3. 运行手机中的 lldb-server

./lldb-server platform --server --listen unix-abstract:///data/local/tmp/debug.sock

4. 在电脑另起一个终端输入 lldb

       lldb 支持多种插件可通过 platform list 查看

(lldb) platform list
Available platforms:
host: Local Linux user platform plug-in.
remote-freebsd: Remote FreeBSD user platform plug-in.
remote-linux: Remote Linux user platform plug-in.
remote-netbsd: Remote NetBSD user platform plug-in.
remote-windows: Remote Windows user platform plug-in.
kalimba: Kalimba user platform plug-in.
remote-android: Remote Android user platform plug-in.
remote-ios: Remote iOS platform plug-in.
remote-macosx: Remote Mac OS X user platform plug-in.
remote-gdb-server: A platform that uses the GDB remote protocol as the communication transport.(lldb) 

我们选择使用 Android 调试插件

platform select remote-android

连接 lldb-server

platform connect unix-abstract-connect:///data/local/tmp/debug.sock

attach 目标进程

process attach -p 目标app进程id
  1. 通过 lldb 命令下断点,对 libdvm.so 进行调试

image.png