2023年7月4日首发
WalxPlugin框架(以下简称WP框架)是一个不需要root权限就能使用的插件化模块,能够轻松实现在非root设备hook其它应用的调用和访问进程数据等功能。目前该框架已发布测试版。
一.WP框架工具包提供了以下几个模块:
1.WP管理器:用于管理插件模块的授权和使用,插件由开发者设计,经用户确认后即可由目标应用(宿主)加载。
2.加载器:对用户和开发者不可见,而是由WP管理器加载到目标应用。
3.开发sdk用到的jar包:walxpluginsdk.jar,开发者需要将该jar包导入到项目中去。
4.核心模块:该模块由WP自身提供,为程序自带的插件,用于开发调试,基本功能有:
(1)AMS监听,也就是监听目标应用对ActivityManagerService服务的接口调用;
(2)Activity监听,这个其实是把AMS启动Activity的功能单独拿出来了;
(3)查看应用View:用来查看Activity和Window中的所有View列表及其信息;
(4)查看应用组件:用来查看四大组件的数据,包括创建的所有对象信息;
(5)导出应用数据:用来提取应用/data/data/包名下的私有目录中的文件。
二.WP框架能做什么
WP主要提供一套简单的开发标准,由开发者自行设计功能,比如开发者自身需求,像监听应用调用等,当然也可以监听网络请求,但由于时间仓促框架自身模块未实现。然后就是用户的需求,比如应用个性定制等,在宿主应用启动后拦截api调用,修改应用的界面,替换自己的数据等,或者能够实现类似于微信抢红包的功能,但不能进行全局hook,只能通过代理修改简单的接口调用,以及获取对象数据。所以它不像某些调试工具只能应用于开发阶段,它可以完全用于实践,对应用做出持久性的改变。
实现原理:开发好的模块也就是apk里面的核心代码会和目标应用位于同一进程,相当于hook注入技术,或者叫dex注入技术,所以它们能相互访问数据,WP管理器会向目标应用注入一个dex文件,用于获取启动控制权,并加载经用户授权的模块,然后对目标应用重新签名。需要注意的是:某些应用会做签名验证,所以可能无法启动,至于如何绕过验证机制这个需要后续实现,可能要针对具体应用分析,甚至要用到ida反汇编,毕竟很多应用底层代码都工作在c层。
大概功能讲完了,下面讲一下如何使用。
先上几张图:
下面是获取到微信数据:
微信ams监听数据:
微信登录界面数据,手机号是我随便填写的:
首先需要到文章最后提供的地址中下载WP开发工具,然后安装其中的WP管理器应用,下面的例子中介绍了如何修改微信欢迎界面按钮颜色。
主要代码截图:
现在打开Android Studio创建一个模块,填写包名,然后导入jar包,同步项目,新建一个启动入口类,比如叫Main,然后实现IWalxPluginMain接口,重写onLoadModule和onMenuItemClick两个方法,
然后在onLoadModule中加入以下代码,用于监听Activity生命周期:
WalxHelper.registerActivityListener(context, this);
在onMenuItemClick中添加自己的实现代码:
switch (itemId) {
case 1000:
Toast.makeText(context, "点击了1000", Toast.LENGTH_SHORT).show();
break;
}
最后在onActivityResumed方法中加入下列代码,用来监听微信欢迎登录界面,并修改登录按钮颜色:
if(activity.getClass().getSimpleName().equals("WelcomeActivity")){
Button loginButton = (Button) WalxHelper.findViewById(activity, 2131312425); //登录按钮id
if (loginButton != null) {
loginButton.setBackgroundColor(Color.RED); //将登录按钮的颜色改成红色
}
}
完整代码如下:
public class Main implements IWalxPluginMain, Application.ActivityLifecycleCallbacks {
@Override
public void onLoadModule(Context context, ClassLoader classLoader, String modulePackage) {
Toast.makeText(context, modulePackage, Toast.LENGTH_SHORT).show();
WalxHelper.registerActivityListener(context, this);
}
@Override
public void onMenuItemClick(Context context, ClassLoader classLoader, int itemId) {
switch (itemId) {
case 1000:
Toast.makeText(context, "点击了1000", Toast.LENGTH_SHORT).show();
break;
}
}
@Override
public void onActivityCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) {
}
@Override
public void onActivityStarted(@NonNull Activity activity) {
}
@Override
public void onActivityResumed(@NonNull Activity activity) {
Button loginButton = (Button) WalxHelper.findViewById(activity, 2131312425); //登录按钮id
if (loginButton != null) {
loginButton.setBackgroundColor(Color.RED); //将登录按钮的颜色改成红色
}
}
@Override
public void onActivityPaused(@NonNull Activity activity) {
}
@Override
public void onActivityStopped(@NonNull Activity activity) {
}
@Override
public void onActivitySaveInstanceState(@NonNull Activity activity, @NonNull Bundle outState) {
}
@Override
public void onActivityDestroyed(@NonNull Activity activity) {
}
}
最后在src/main下创建一个assets目录,在目录里创建一个walxplugin.json文件,文件格式如下:
{
"desc":"测试模块",
"targetPackages":"com.tencent.mm",
"mainClass":"com.zwxuf.myplugin.Main",
"menu":[
{
"id":1000,
"name":"测试菜单项"
}
]
}
字段含义:
desc:模块描述;
targetPackages:模块要注入的目标应用,即要修改的应用包名,多个包名用英文,隔开,如果要注入所有应用,填写*即可;
mainClass:主类,应用启动后会回调该方法,在该方法中添加自己的初始化代码;
menu:菜单项,数组格式,在WP管理器中点击应用时会显示本菜单;
如图示例:
最终运行效果图:
以后每次启动微信,它的登录按钮始终是红色的。
注意:由于是编写的是模块,所以应用里面的资源是无法加载的,所以请不要使用R.*开头资源引用方式,而使用WalxHelper工具类提供的方法来实现,
比如WalxHelper.getLayout方法用来获取一个布局,WalxHelper.getDrawable用来获取一张图片。
使用Activity:
创建一个类,继承WalxPluginUI类,然后在类中使用Activity的所有方法,启动时不要用系统的startActivity,而要使用WalxHelper中的startPluginUI方法。
在Activity类中不要使用如setContentView(R.layout.activity_main)这样的方法,而用以下代码代替:
View mContentView = WalxHelper.getLayout(this, R.layout.activity_main);
setContentView(mContentView);
最后导出模块apk,手动安装或者通过WP管理器安装,然后授权开启模块,如果模块显示未认证则代表该模块未被用户授权,是无法使用的,此时需要点击开启授权,另外,卸载WP管理器后所有模块将全部变成未认证,需要重新授权。
安装完模块,接下来需要安装要修改的应用,首次安装需要先卸载应用,要使用微信模块,就要重装微信,请先做好数据备份。
WalxHelper工具类使用方法:
//获取应用所有Activity
WalxHelper.getActivities(context);
//获取Activity中的所有View,不包括窗口中的view
WalxHelper.getAllChildViews(activity);
//获取所有根View,根view包含窗口的View和Dialog以及PopupWindow中的view
WalxHelper.getAllRootViews();
其余功能可自行研究。
注意事项:
1.由于重新进行了签名,个别应用可能签名失败,此进可进入文件管理器,找到内部存储下的singed.apk文件,在电脑上用apksigner临时签名解决,签名文件可以用自己的keystore,后续会完善签名方式。
2.有些应用是系统自带的预装应用, 这些应用可能会签名失败或安装失败,所以请不要用这些版本,而建议从网上重新下载原版进行安装。
3.有些应用安装成功,但无法启动,或者有闪退现象,此时可重新用WP安装应用,并分别取消“创建新入口”和“禁用原入口”两个选项再试。
创建新入口含义:即再为应用分配一个启动图标,在桌面上会显示两个应用图标,但名称不一样,一个是原名称,另一个叫模块入口,启动时点击模块入口启动应用,而不要点击原应用图标启动。如果不勾选此选项,启动应用时只能通过WP启动才能激活插件,在桌面上点击是无法加载插件的。
禁用原入口含义:即删除应用原来的启动界面声明,用新入口代替,勾选这个选项后,在桌面上只会生成一个图标,此时正常点击启动应用即可。
为什么WP不使用service方式启动代码?因为service在应用停止后无法启动,此时应用具有FLAG_STOPPED标志。
百度网盘临时下载地址:
https://pan.baidu.com/s/1D_jwnmSpwv4Kd19TrqZvHQ
提取码:1234