### 简介:
通过attach agent来实现对debuggable app(release app需root)的动态代码注入,无需依赖额外工具。
<br/>
### 博客详情: 敬请期待。。。
<br/>
### 姊妹篇:
[jdwp-injector-for-android](https://github.com/wuyr/jdwp-injector-for-android)(借助Android 11以上自带的无线adb,给普通手机(无root)提供一个对debuggable app进行动态代码注入的能力)
<br/>
### 效果预览:
**将要注入的代码:**
```kotlin
fun showDialog() {
thread {
Handler(Looper.getMainLooper()).post {
runningActivities.forEach {
if (!it.isDestroyed) {
AlertDialog.Builder(it).setMessage("Hello Agent from $application")
.setPositiveButton("close", null).show()
}
}
Toast.makeText(application, "dialog has been showed", Toast.LENGTH_LONG).show()
}
}
}
```
>完整代码请移步: [Drug.kt](https://github.com/wuyr/agent-injector-for-android/blob/master/app/src/main/java/com/wuyr/agent_injector_test/Drug.kt)
<br/>
**运行效果:(需要科学上网)**
![preview](https://github.com/wuyr/agent-injector-for-android/raw/main/previews/1.gif)
![preview](https://github.com/wuyr/agent-injector-for-android/raw/main/previews/2.gif)
>注:如果要注入release版的app,必须开启全局调试(`ro.debuggable=1`)或者当前系统类型是userdebug或eng(`ro.build.type=userdebug|eng`)才可以。
>
> **android 14之后改了判定机制,原来的`ro.debuggable`属性已经没用了,新的全局调试条件改成了`ro.build.type=eng`或者`ro.build.type=userdebug`并且`persist.debug.dalvik.vm.jdwp.enabled=1`**
<br/>
### Demo下载: [app-debug.apk](https://github.com/wuyr/agent-injector-for-android/raw/main/app-debug.apk)
<br/>
### Demo使用方法 (请科学上网以查看图片):
首次运行app,请先按照指引,进行无线配对:
![preview](https://github.com/wuyr/agent-injector-for-android/raw/main/previews/3.png)
配对完成,加载出app列表之后,可以对列表里的app进行代码注入——你可以尝试在目标app里显示一个dialog,或者显示一个toast。
通常情况下,如果你的手机没有开启全局调试,它只能对debug包进行注入,如果你想要注入release版app,可以点击页面上方的 "设为全局可调试" 按钮开启全局调试(有安装magisk的设备才会显示此按钮):
![preview](https://github.com/wuyr/agent-injector-for-android/raw/main/previews/4.png)
等待自动重启之后,重新打开app,你会发现,release版app也能够注入了。
**注意:** 一些系统app,可能会通过selinux禁掉data目录的执行权限(如果你注入系统app没有任何反应并且app没有闪退的话,多半是被selinux拦截了),针对这种情况,需要先关闭selinux才能正常注入,可通过页面上方的 "关闭SELINUX" 按钮进行关闭(需要root权限)。
当然,这只是一个功能演示,你完全可以clone之后按照你的想法去改造成你想要的样子。
<br/>
### 诞生背景:
之前在写android端debugger的时候,忽然想到了一个问题:**debugger在设置断点之后,怎样才可以让它主动触发呢?** 因为我要做的是通过debugger来实现代码自动化注入,这个过程中如果需要用户去干预,那就不算自动化了,而且这个触发的时机必须尽量早,不然会影响整体效率。<br/>
第一个想到的方案是,**模拟一个屏幕触摸事件:**<br/>
很多时候确实可以用这个方法,但这个方法有个弊端:因为你无法保证每次的触摸事件都能完美避开一些功能性的按钮,比如这个事件的坐标值刚好落在一个跳转界面的按钮上,那么在vm恢复运行的时候,会自动跳转界面,站在用户角度来看,就会觉得莫名其妙。<br/>
就算是一个*ACTION_UP*事件,也可能当时用户正在拖拽一样东西,你一个*ACTION_UP*把人家拖拽的东西放下了,所以这个方法还是不太友好,无法保证无感触发。<br/>
还有一个就是,要知道被debug的app不一定是运行在前台,现在模拟触摸事件都是通过[InputManager.injectInputEvent()](http://aosp.app/android-11.0.0_r1/xref/frameworks/base/core/java/android/hardware/input/InputManager.java#896)来传入一个InputEvent,这个方法对应的是display,无法只针对某个应用进行分派,如果此时目标应用运行在后台的话,就接收不到事件了,进一步导致断点不能及时触发。<br/>
提到"后台运行","及时触发",我突然想到了ActivityThread里的Handler.`handleMessage`,这个方法回调频率非常高,Activity的生命周期变化,都要经过这里:比如当app从后台切换到前台,AMS会调用IApplicationThread的`scheduleTransaction`方法,把即将要发生的事件(ResumeActivityItem)通过binder告诉ActivityThread的`mAppThread`,接着`mAppThread`就会向Handler发一条消息。<br/>
目前看来,把断点打在Handler.`handleMessage`是比较合适的。不过,根据我们平时debug的经验可以得知,如果把断点打在方法上,是会大大影响app的运行效率的,但又不能按行号来打断点,因为各个系统版本的行号都可能有变化。这样排除下来,就只有变量断点(Field Watchpoint)能用了。<br/>
想一下,**Handler.`handleMessage`一定会访问哪个类的哪个成员变量?** <br/>
没错!就是MessageQueue里面的`mMessages`! watch这个变量之后,只要Handler有消息要处理,就一定会触发。<br/>
但是,Handler总会有空闲的时候,如果在注入时Handler刚好处于空闲状态,断点就不能及时触发,这又回到了刚开始的问题了! 所以必须在设置好Watchpoint之后,让目标进程的Handler忙起来:<br/>
刚刚提到,Activity每当生命周期发生变化时,都是由AMS跨进程通知ApplicationThread,然后ApplicationThread向Handler发一条消息。<br/>
那么,我们能不能用shell命令模拟键盘事件,比如发送HOME键之类的,间接使目标进程的Activity的生命周期发生变化,而从让ActivityThread的Handler收到消息,进一步触发断点呢?!<br/>
问题又来了,一个正在运行的进程,不一定会启动activity!人家可能只启动了一个service! 而且,你通过这些命令强行改变了activity的生命周期,比刚开始的模拟触摸事件方案更不友好。<br/>
退一步,**那还有没有其他的命令可以让AMS给ApplicationThread发通知呢?** <br/>
翻了一下源码还真有:
- [am crash \<package\>](https://aosp.app/android-11.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#1220);
- [am trace-ipc start](https://aosp.app/android-11.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#1689);
- [am trace-ipc stop --dump-file \<output path\>](https://aosp.app/android-11.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#1694);
- [am profile start \<package\> \<output path\>](https://aosp.app/android-11.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#1170);
- [am profile stop \<package\>](https://aosp.app/android-11.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#1170);
- [am dumpheap \<package\>](https://aosp.app/android-11.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#1175);
- [am attach-agent \<package\> \<agent path\>](https://aosp.app/android-11.0.0_r1/xref/frameworks/base/core/java/android/app/ActivityThread.java#1196);
`am crash`就太暴力了,Handler收到这个消息,会直接抛出一个RemoteServiceException来结束进程。<br/>
中间这几个: `trace-ipc`、`profile`、`dumpheap`都是跟内存/性能分析有关,最后一个`attach-agent`是什么鬼? 看下处理消息的代码:
```j
没有合适的资源?快使用搜索试试~ 我知道了~
基于JVMTI实现的Android端动态代码注入工具.zip
共70个文件
kt:18个
xml:14个
webp:10个
0 下载量 38 浏览量
2024-08-20
10:42:39
上传
评论
收藏 8.95MB ZIP 举报
温馨提示
项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松copy复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全栈开发),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助 【资源内容】:项目具体内容可查看/点击本页面下方的*资源详情*,包含完整源码+工程文件+说明(若有)等。【若无VIP,此资源可私信获取】 【本人专注IT领域】:有任何使用问题欢迎随时与我联系,我会及时解答,第一时间为您提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【适合场景】:相关项目设计中,皆可应用在项目开发、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面中 可借鉴此优质项目实现复刻,也可基于此项目来扩展开发出更多功能 #注 1. 本资源仅用于开源学习和技术交流。不可商用等,一切后果由使用者承担 2. 部分字体及插图等来自网络,若是侵权请联系删除,本人不对所涉及的版权问题或内容负法律责任。收取的费用仅用于整理和收集资料耗费时间的酬劳 3. 积分资源不提供使用问题指导/解答
资源推荐
资源详情
资源评论
收起资源包目录
基于JVMTI实现的Android端动态代码注入工具.zip (70个子文件)
DSandroidffv1
gradle.properties 1KB
gradle
wrapper
gradle-wrapper.jar 58KB
gradle-wrapper.properties 230B
libs.versions.toml 1KB
agent-injector
src
main
java
com
wuyr
agent_injector
adb
AdbWirelessPairing.kt 6KB
AdbClient.kt 34KB
AdbWirelessPortResolver.kt 4KB
Spake2.kt 1KB
utils
HiddenApiExemptions.kt 2KB
AgentInjector.kt 7KB
exception
ProcessNotFoundException.kt 257B
RootNotDetectedException.kt 240B
UidSwitchingException.kt 244B
AgentAttachException.kt 267B
PairingException.kt 239B
AdbCommunicationException.kt 248B
cpp
CMakeLists.txt 382B
log.h 475B
jvmti.h 94KB
agent_injector.cpp 3KB
spake2.cpp 3KB
AndroidManifest.xml 62B
proguard-rules.pro 750B
consumer-rules.pro 0B
.gitignore 6B
build.gradle.kts 974B
previews
3.png 51KB
2.gif 1.95MB
4.png 85KB
1.gif 1.3MB
app
src
main
java
com
wuyr
agent_injector_test
adapter
SingleTypeAdapter.kt 6KB
AppListAdapter.kt 2KB
activity
MainActivity.kt 19KB
BaseActivity.kt 918B
Drug.kt 3KB
log
ConsoleLogUtil.kt 2KB
res
mipmap-xxhdpi
ic_launcher_round.webp 6KB
ic_launcher.webp 3KB
mipmap-hdpi
ic_launcher_round.webp 3KB
ic_launcher.webp 1KB
mipmap-mdpi
ic_launcher_round.webp 2KB
ic_launcher.webp 982B
values-zh-rCN
strings.xml 3KB
mipmap-xxxhdpi
ic_launcher_round.webp 8KB
ic_launcher.webp 4KB
mipmap-anydpi
ic_launcher.xml 343B
ic_launcher_round.xml 343B
mipmap-xhdpi
ic_launcher_round.webp 4KB
ic_launcher.webp 2KB
xml
data_extraction_rules.xml 551B
backup_rules.xml 478B
values
colors.xml 378B
strings.xml 3KB
themes.xml 859B
layout
item_app.xml 4KB
activity_main.xml 4KB
drawable
ic_launcher_background.xml 5KB
ic_launcher_foreground.xml 2KB
AndroidManifest.xml 1KB
proguard-rules.pro 750B
.gitignore 6B
build.gradle.kts 1KB
app-debug.apk 15.32MB
LICENSE 11KB
gradlew.bat 3KB
gradlew 6KB
.gitignore 432B
README.md 10KB
settings.gradle.kts 577B
build.gradle.kts 276B
共 70 条
- 1
资源评论
热爱技术。
- 粉丝: 2425
- 资源: 7862
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
最新资源
资源上传下载、课程学习等过程中有任何疑问或建议,欢迎提出宝贵意见哦~我们会及时处理!
点击此处反馈
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功