Android apk动态调式以及UI定位

工具

Android Studio,后面的内容简称AS.

Android Studio 是谷歌推出的一个Android集成开发工具,基于IntelliJ IDEA. 类似 Eclipse ADT,Android Studio 提供了集成的 Android 开发工具用于开发和调试。

系统app调试

开发系统app的时候,大多数基于makefile的,并且签名是platform的,因此不能直接通过源码进行调试。本文不打算拿系统app来讲解如何调试,不过会使用这里的调式技巧,那么调试系统app也很简单了(系统app的源码大都涉密,不方便拿来举例,AOSP的源码例外)。

这里主要是Java层的调试,native层的调试在后续文章中会讲解。

应用程序

源码很简单,主要包括一个MainActivity,部分代码如下:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        password_et = (EditText) this.findViewById(R.id.password);
        username_et = (EditText) this.findViewById(R.id.username);
        message_tv = ((TextView) findViewById(R.id.textView));
        registerReceiver(new MyReceiver(), new IntentFilter("send"));
        ...
 }

通过objection查看安装目录,关于objection的使用在Frida进阶之内存漫游及简单抓包有所介绍。通过env命令可以查看安装目录。
在这里插入图片描述使用adb pull 导出apk.

使用AS进行debug

点击File->Profile or Debug APK,选择导出的apk。
在这里插入图片描述在右上角有Attach Kotlin/Java Source…,选择源代码路径,这时候相应的smali就编程源代码了。在这里插入图片描述选择Attach debugger to Android Process,选择相应的进程,在需要的地方下断点就可以正常调式了。
在这里插入图片描述这就和和正常的app的调试是一样的了。

当然也可以通过Run->Debug来调试,这种和普通app的调试就一样了。注意:在debug配置的时候选择Java Only。

JDB调试Android程序

App动态调试(1)-Radare2和lldb 中对JDB调试进行了简单的介绍,通过jdb调试来跟踪指定的动态库加载完成。

JDWP 协议

首先让我们认识一下什么是 JDWP(Java Debug Wire Protocol),说白了就是 JVM 或者类 JVM 的虚拟机都支持一种协议,通过该协议,Debugger 端可以和目标 VM 通信,可以获取目标 VM 的包括类、对象、线程等信息。

在调试 Android 应用程序这一场景,Debugger 一般是指你的 develop machine 的某一支持 JDWP 协议的工具例如 Android Studio 或者 JDB,而 Target JVM 是指运行在你 mobile 设备当中的各个 App(因为它们都是一个个虚拟机 Dalvik 或者 ART)

JDWP Agent一般负责监听某一个端口,当有 Debugger 向这一个端口发起请求的时候,Agent 就转发该请求给 Target JVM 并最终由该 JVM 来处理请求,并把 reply 信息返回给 Debugger 端。

在这里插入图片描述针对Android设备,可参考下面这个图, JDWP Agent 在 Android 手机上应该是指 adbd 进程。
在这里插入图片描述 JDWP 协议的报文格式,JDWP 协议中主要有两种报文:Command packet 和 Reply packet,command packet 就是我们上面所说的请求报文,reply 自然就是对 command 的回答。

如果想深入了解JDWP协议,可参考https://docs.oracle.com/javase/8/docs/technotes/guides/troubleshoot/introclientissues005.html。

关于JDWP曾经存在过远程命令执行漏洞,有兴趣可参考https://blog.csdn.net/wanzt123/article/details/82793023。

JDB命令列表

这个除了step、stop,其他的用的不太多,除非要自己开发调试器。

命令作用
connectors列出此 VM 中可用的连接器和传输
run [class [args]]开始执行应用程序的主类
threads [threadgroup]列出线程
suspend [thread id(s)]挂起线程 (默认值: all)
resume [thread id(s)]恢复线程 (默认值: all)
where [ | all]转储线程的堆栈
wherei [ | all]转储线程的堆栈, 以及 pc 信息
up [n frames]上移线程的堆栈
down [n frames]下移线程的堆栈
kill终止具有给定的异常错误对象的线程
interrupt中断线程
print输出表达式的值
dump输出所有对象信息
eval对表达式求值 (与 print 相同)
set向字段/变量/数组元素分配新值
locals输出当前堆栈帧中的所有本地变量
classes列出当前已知的类
class显示已命名类的详细资料
methods列出类的方法
fields列出类的字段
threadgroups列出线程组
threadgroup设置当前线程组
stop in .[(argument_type,…)]在方法中设置断点
stop at :在行中设置断点
clear .[(argument_type,…)]清除方法中的断点
clear :清除行中的断点
clear列出断点
catch [uncaught caught all]出现指定的异常错误时中断
ignore [uncaught caught all]对于指定的异常错误, 取消 ‘catch’
watch [access all] .监视对字段的访问/修改
unwatch [access all] .停止监视对字段的访问/修改
trace [go] methods [thread]跟踪方法进入和退出。
trace [go] method exit exits [thread]跟踪当前方法的退出, 或者所有方法的退出
untrace [methods]停止跟踪方法进入和/或退出
step执行当前行
step up一直执行, 直到当前方法返回到其调用方
stepi执行当前指令
cont从断点处继续执行
list [line number method]输出源代码
use (或 sourcepath) [source file path]显示或更改源路径
exclude [, …“none”]
classpath从目标 VM 输出类路径信息
monitor每次程序停止时执行命令
monitor列出监视器
unmonitor <monitor#>删除监视器
read读取并执行命令文件
lock输出对象的锁信息
threadlocks [thread id]输出线程的锁信息
pop通过当前帧出栈, 且包含当前帧
reenter与 pop 相同, 但重新进入当前帧
redefine重新定义类的代码
disablegc禁止对象的垃圾收集
enablegc允许对象的垃圾收集

调试程序

使用JDB调试上面的apk程序。
(1) 查看进程 adb shell ps | grep com.example.myapplication
(2) 端口转发 adb forward tcp:12345 jdwp:15513(进程PID)
(3)JDB和app之间建立联系 jdb -attach localhost:12345

在这里插入图片描述(4)设置断点 stop in com.example.myapplication.MainActivity.onCreate(android.os.Bundle)

由于这个这个方法已经运行了,因此这里是不能够出发断点的,如果在改方法调用之前能够suspend进程就能解决这个问题了。在App动态调试(1)-Radare2和lldb 通过R2frida的spawan模式使得进程suspend的。

进入Debug模式

添加这段代码android.os.Debug.waitForDebugger() 是能够实现的。
也可以通过命令来以Debug方式启动:

adb shell am start –D  包名/类名

拿上面的apk举例,相应的命令就是:(本文基于的是Android 11)

adb shell am start  -D  com.example.myapplication/com.example.myapplication.MainActivity

当绑定debugger的时候会使得app恢复所与的线程,这是我门不希望的。要阻止线程恢复,需要将suspend命令发送给jdb。

 { echo "suspend"; cat; }  | jdb -attach localhost:12345

在这里插入图片描述

UI定位

记录AS中的一个错误

记录AS中的一个错误,由于移除插件导致再次启动AS的时候出现了下面的错误:

missing essential plugin org.jetbrains.android please reinstall android studio from scratch

这个错误是和用户有关的,因此可以通过用户切换来解决。

在Ubuntu上的解决办法:

rm -rf ./.config/Google/AndroidStudio4.1/disabled_plugins.txt

在其他平台也类似,找到用户目录,搜索disabled_plugins.txt,然后删除就OK了。

布局探测

以某多多为例,根据这个关键字就能基本确定代码的位置了。
在这里插入图片描述

写在最后

Android中涉及的调试有很多,包括framework层的调试以及native层的调试,后续会持续更新调试相关的文章。熟练使用调试对阅读代码和定位问题都有很大的帮助。

公众号

更多内容,欢迎关注我的微信公众号: 无情剑客。
在这里插入图片描述

相关推荐
©️2020 CSDN 皮肤主题: 编程工作室 设计师:CSDN官方博客 返回首页
实付 49.90元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值