那些年的Xposed开发经验记录

news2025/2/13 0:13:24

把之前写的Xposed相关文章合并到一块,方便查阅

目录

  • 多进程App的Hook问题
    • XposedHelper中的静态变量
    • demo的AndroidManifest.xml的测试核心代码
    • 结论
    • 限制handleLoadPackage被单个进程多次执行的问题
  • 多dex Hook问题
  • 为应用增加权限
    • 利用Xposed删除权限
    • 参考
  • Hook框架集锦
    • 原始思维导图文件下载

多进程App的Hook问题

以及App中单个方法被多个模块Hook时的Hook代码优先级问题

XposedHelper中的静态变量

在这里插入图片描述

demo的AndroidManifest.xml的测试核心代码

        <activity
            android:name=".ProcessActivity"
            android:process=":process"></activity>//私有进程
        <activity
            android:name=".PublicProcessActivity"
            android:process="com.publicProcess">//公共进程

        </activity>

结论

以下"所有进程"都包括应用内创建的私有进程和公共进程
经过测试[测试代码过多就不贴了],得出结论:
1.所有进程的创建都会执行而且会多次执行handleLoadPackage函数;
2.每个进程都会重新创建一个fieldCache,methodCache,constructorCache静态变量;
3.若两个模块Hook了当前App的同一个函数则beforeHookedMethod执行顺序是按Xposed框架私有目录下conf/modules.list的顺序执行的,afterHookedMethod则与beforeHookedMethod执行顺序相反[测试数据是这样的,具体真实情况就不太想探究了,应该90%正确],举个例子:

模块A和模块B同时Hook了应用C的方法D,modules.list中模块A比模块B的顺序靠前,则Hook代码执行顺序为:
A->beforeHookedMethod,B->beforeHookedMethod,D,B->afterHookedMethod,A->afterHookedMethod

4.lpparam.isFirstApplication并不是仅仅在主进程执行handleLoadPackage函数时才会置为true,在所有进程执行该函数时都会置为true[测试数据是这样的,具体真实情况就不太想探究了,应该90%正确];
5.在App的一个进程A中对某函数进行Hook只会影响进程A执行该函数,不会影响该App其它未被Hook的进程执行该函数。

限制handleLoadPackage被单个进程多次执行的问题

    /**
     *防止重复执行Hook代码
     * @param flag 判断标识,针对不同Hook代码分别进行判断
     * @return 是否已经注入Hook代码
     */
    private boolean isInjecter(String flag) {
        try {
            if (TextUtils.isEmpty(flag)) return false;
            Field methodCacheField = XposedHelpers.class.getDeclaredField("methodCache");
            methodCacheField.setAccessible(true);
            HashMap<String, Method> methodCache = (HashMap<String, Method>) methodCacheField.get(null);
            Method method=XposedHelpers.findMethodBestMatch(Application.class,"onCreate");
            String key=String.format("%s#%s",flag,method.getName());
            if (methodCache.containsKey(key)) return true;
            methodCache.put(key, method);
            return false;
        } catch (Throwable e) {
            e.printStackTrace();
        }
        return false;
    }

在handleLoadPackage做判断


    @Keep
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) {
            if (isInjecter(this.getClass().getName())) {
                return;
            }
            //hook代码
}

多dex Hook问题

//解决多dex问题
    public static void findHideDex(final OnFindDexListener listener) {
        XposedBridge.hookAllMethods(ContextWrapper.class, "attachBaseContext", new XC_MethodHook() {

            public void beforeHookedMethod(MethodHookParam param) {
                ClassLoader classLoader = ((Context) param.args[0]).getClassLoader();
                if (classLoader == null) return;
                if (listener != null) listener.onFind(classLoader);
            }
        });
        XposedBridge.hookAllConstructors(ClassLoader.class, new XC_MethodHook() {
            public void beforeHookedMethod(MethodHookParam param) {
                ClassLoader classLoader = (ClassLoader) param.args[0];
                if (classLoader == null) return;
                if (listener != null) listener.onFind(classLoader);
            }
        });
    }
public interface OnFindDexListener {
        void onFind(ClassLoader classLoader);
    }

为应用增加权限

利用Xposed删除权限

这个已经有人实现了,就是Xposed的作者,我们就先来研究研究他是怎么实现的,先上他的实现代码

public class PackagePermissions extends BroadcastReceiver {
	private final Object pmSvc;
	private final Map<String, Object> mPackages;
	private final Object mSettings;

	@SuppressWarnings("unchecked")
	public PackagePermissions(Object pmSvc) {
		this.pmSvc = pmSvc;
		this.mPackages = (Map<String, Object>) getObjectField(pmSvc, "mPackages");
		this.mSettings = getObjectField(pmSvc, "mSettings");
	}

/*这个函数主要hook了 PackageManager 服务(负责系统中Package的管理,应用程序的安装、卸载、信息查询),实现了通过监听我们自己发出的广播,拦截权限授予功能来进行修改apk的权限的*/
	public static void initHooks() {
		try {
			final Class<?> clsPMS = findClass("com.android.server.pm.PackageManagerService", XposedMod.class.getClassLoader());//获取这个PackageManager类

			//注册监听广播,监听我们的设置更改,以实现立即应用设置
			findAndHookMethod(clsPMS, "systemReady", new XC_MethodHook() {
				@Override
				protected void afterHookedMethod(MethodHookParam param)
						throws Throwable {
					Context mContext = (Context) getObjectField(param.thisObject, "mContext");//这个应该是系统的上下文,具体待研究
					mContext.registerReceiver(new PackagePermissions(param.thisObject),
							new IntentFilter(Common.MY_PACKAGE_NAME + ".UPDATE_PERMISSIONS"),
							Common.MY_PACKAGE_NAME + ".BROADCAST_PERMISSION",
							null);//注册广播
				}
			});

//拦截PackageManager类中的grantPermissionsLPw函数
			findAndHookMethod(clsPMS, "grantPermissionsLPw", "android.content.pm.PackageParser$Package", boolean.class,
					new XC_MethodHook() {
				@SuppressWarnings("unchecked")
				@Override
				protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
					String pkgName = (String) getObjectField(param.args[0], "packageName");
					if (!XposedMod.isActive(pkgName) || !XposedMod.prefs.getBoolean(pkgName + Common.PREF_REVOKEPERMS, false))
						return;

					Set<String> disabledPermissions = XposedMod.prefs.getStringSet(pkgName + Common.PREF_REVOKELIST, null);
					if (disabledPermissions == null || disabledPermissions.isEmpty())
						return;

					ArrayList<String> origRequestedPermissions = (ArrayList<String>) getObjectField(param.args[0], "requestedPermissions");
					param.setObjectExtra("orig_requested_permissions", origRequestedPermissions);

					ArrayList<String> newRequestedPermissions = new ArrayList<String>(origRequestedPermissions.size());
					for (String perm: origRequestedPermissions) {
						if (!disabledPermissions.contains(perm))
							newRequestedPermissions.add(perm);
						else
							// you requested those internet permissions? I didn't read that, sorry
							Log.w(Common.TAG, "Not granting permission " + perm
									+ " to package " + pkgName
									+ " because you think it should not have it");
					}

					setObjectField(param.args[0], "requestedPermissions", newRequestedPermissions);
				}

				@SuppressWarnings("unchecked")
				@Override
				protected void afterHookedMethod(MethodHookParam param) throws Throwable {
					// restore requested permissions if they were modified
					ArrayList<String> origRequestedPermissions = (ArrayList<String>) param.getObjectExtra("orig_requested_permissions");
					if (origRequestedPermissions != null)
						setObjectField(param.args[0], "requestedPermissions", origRequestedPermissions);
				}
			});
		} catch (Throwable e) {
			XposedBridge.log(e);
		}
	}

	@Override
	public void onReceive(Context context, Intent intent) {
		try {
			// The app broadcasted a request to update settings for a running app

			// Validate the action being requested
			if (!Common.ACTION_PERMISSIONS.equals(intent.getExtras().getString("action")))
				return;

			String pkgName = intent.getExtras().getString("Package");
			boolean killApp = intent.getExtras().getBoolean("Kill", false);

			XposedMod.prefs.reload();

			Object pkgInfo;
			synchronized (mPackages) {
				pkgInfo = mPackages.get(pkgName);
				callMethod(pmSvc, "grantPermissionsLPw", pkgInfo, true);
				callMethod(mSettings, "writeLPr");
			}

			// Apply new permissions if needed
			if (killApp) {
				try {
					ApplicationInfo appInfo = (ApplicationInfo) getObjectField(pkgInfo, "applicationInfo");
					if (Build.VERSION.SDK_INT <= 18)
						callMethod(pmSvc, "killApplication", pkgName, appInfo.uid);
					else
						callMethod(pmSvc, "killApplication", pkgName, appInfo.uid, "apply App Settings");
				} catch (Throwable t) {
					XposedBridge.log(t);
				}
			}
		} catch (Throwable t) {
			XposedBridge.log(t);
		}
	}
}

这段代码的地址

参考

1.AppSettingshook权限代码
2.Android5.1.1源码 - 添加应用权限

Hook框架集锦

在这里插入图片描述

原始思维导图文件下载

ProcessOn:Android-Hook框架集锦.pos

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/864078.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《漫画算法:小灰的算法之旅》——赠书活动

我想应该有很多人对我今天推荐的书籍不陌生&#xff0c;《漫画算法&#xff1a;小灰的算法之旅》已经是圈内人熟知的“红人”了&#xff0c;但也存在不断有新人入坑&#xff0c;这里就好好介绍一下这本包上“糖衣”的算法“炮弹”吧&#xff0c;整个过程如同本书形象“Q弾可爱&…

热成像技术创新,助力人工智能炼就黑夜中的火眼金睛

原创 | 文 BFT机器人 普渡大学&#xff08;Purdue University&#xff09;的研究人员利用他们正在申请专利的方法来改进传统的机器视觉和感知&#xff0c;从而推动机器人技术和自动控制领域的发展。 埃尔莫尔家族电气与计算机工程学院&#xff08;Elmore Family School of Ele…

Git使用教程(看完会了也懂了)

本文简单的记录一下Git的一些基本的概念和基础的操作&#xff0c;主要是弄懂基本的东西&#xff0c;能够快速的上手并开始使用&#xff1b;但是更多深层的原理和应用还是需要另外去进一步学习的。 创建版本库 我们先整一个git仓库&#xff0c;再来看看基本概念&#xff1b; 新…

免费插件-illustrator-Ai插件-印刷功能-二维码生成

文章目录 1.介绍2.安装3.通过窗口>扩展>知了插件4.功能解释5.示例5.1.QR常用二维码5.2.PDF4175.3.EAN13 6.总结 1.介绍 本文介绍一款免费插件&#xff0c;加强illustrator使用人员工作效率&#xff0c;进行二维码生成。首先从下载网址下载这款插件 https://download.csd…

国际顶级学术会议ISSTA召开,中山大学与微众银行联合发表区块链最新研究成果

美国当地时间7月17日&#xff0c;软件工程领域顶级会议ISSTA 2023在西雅图正式召开。ISSTA &#xff08;The 32nd ACM SIGSOFT International Symposium on Software Testing and Analysis &#xff09;是软件测试与分析方面最著名的国际会议之一&#xff0c;也是中国计算机学会…

中国钢铁工业协会 :2022年钢铁行业经济运行报告(附下载)

关于报告的所有内容&#xff0c;公众【营销人星球】获取下载查看 核心观点 2022年&#xff0c;我国粗钢产量10.18亿吨&#xff0c;比上年下降1.7%&#xff0c;连续两年下降&#xff0c;降幅比上年收窄。2022年&#xff0c;出口钢材 6732万吃&#xff0c;比上年增长0.9%;进口钢…

RabbitMQ:可靠消息传递的强大消息中间件

消息中间件在现代分布式系统中起着关键作用&#xff0c;它们提供了一种可靠且高效的方法来进行异步通信和解耦。在这篇博客中&#xff0c;我们将重点介绍 RabbitMQ&#xff0c;一个广泛使用的开源消息中间件。我们将深入探讨 RabbitMQ 的特性、工作原理以及如何在应用程序中使用…

javaScript:文档流写入和元素写入

目录 前言 文档流写入 把元素直接写入到文档流 注意​编辑 注意 元素写入 注意 innerHTML 特点&#xff1a; 设置内容 获取内容 innerText 特点&#xff1a; 注意 相关代码 前言 在JavaScript中&#xff0c;文档流写入是指将内容直接写入到DOM&#xff08;文档对…

用户生成内容(UGC)与海外网红营销:激活品牌传播的力量

互联网和社交媒体的迅速发展为品牌营销带来了前所未有的机遇。用户生成内容&#xff08;UGC&#xff09;是指由普通用户自发创作、分享和发布的各种内容&#xff0c;而海外网红是指在海外社交平台上拥有大量粉丝和影响力的人物。这两者结合&#xff0c;为品牌传播带来了强大的推…

【C++11】类的新功能 | 可变参数模板

文章目录 一.类的新功能1.默认成员函数2.类成员变量初始化3.强制生成默认函数的关键字default4.禁止生成默认函数的关键字delete5.继承和多态中final与override关键字 二.可变参数模板1.可变参数模板的概念2.可变参数模板的定义方式3.参数包的展开方式①递归展开参数包②逗号表…

虚拟展览馆有哪些优势?如何打造自己的虚拟展览馆

引言&#xff1a; 随着科技的不断创新与发展&#xff0c;虚拟展览馆作为一种全新的文化体验方式&#xff0c;正逐渐引起人们的关注。虚拟展览馆以其便捷、创新、可定制的特点&#xff0c;为参观者提供了前所未有的沉浸式体验。 一&#xff0e;什么是虚拟展览馆&#xff1f; 虚…

MongoDB【无敌详细,建议收藏】

"探索MongoDB的无边之境&#xff1a;沉浸式数据库之旅" 欢迎来到MongoDB的精彩世界&#xff01;在这个博客中&#xff0c;我们将带您进入一个充满创新和无限潜力的数据库领域。无论您是开发者、数据工程师还是技术爱好者&#xff0c;MongoDB都将为您带来一场令人心动…

修改element-plus主题色

修改element-plus主题色 前提&#xff1a;要安装按需引入和自动导入插件 ​npm install -D unplugin-vue-components unplugin-auto-import文章目录 修改element-plus主题色一、安装插件二、新建一个element的覆盖scss文件三、配置 一、安装插件 npm install -D unplugin-vu…

重启服务器引发的Docker异常

公司使用云服务器需要硬盘扩容&#xff0c;服务器重启才生效。 重启以后发现拉取远程镜像的命令登录失败了&#xff01; 然后发现找不到容器和镜像列表了&#xff0c;但是容器都启动了。 查看docker运行状态都是正常的 systemctl is-active docker systemctl status docker.…

原生JS手写扫雷小游戏

场景 实现一个完整的扫雷游戏需要一些复杂的逻辑和界面交互。我将为你提供一个简化版的扫雷游戏示例&#xff0c;帮助你入门。请注意&#xff0c;这只是一个基本示例&#xff0c;你可以根据自己的需求进行扩展和改进。 思路 创建游戏板&#xff08;Grid&#xff09;&#xff1…

Vue [Day7] 综合案例

核心概念回顾 state&#xff1a;提供数据 getters&#xff1a;提供与state相关的计算属性 mutations&#xff1a;提供方法&#xff0c;用于修改state actions&#xff1a;存放异步操作 modules&#xff1a;存模块 功能分析 https://www.npmjs.com/package/json-server#ge…

企业运单管理教程

随着电子面单的普及&#xff0c;以及商务寄件稳步增加&#xff0c;快递公司为了留住商企客户&#xff0c;推出了月结协议模式寄件。企业可以根据寄件量大小&#xff0c;和快递公司签订月结协议&#xff0c;运费每月结算一次&#xff0c;还能根据自身的寄件量&#xff0c;向快递…

评述6种室内定位技术的底层原理及未来展望

从古至今&#xff0c;人类始终关心一个颇具哲学意味的问题——“我在哪里”。从千年前的人类在夜空下遥望星河&#xff0c;到依靠经验和模糊的观测绘制的初具现代化意味的地图&#xff0c;再到近现代人类在计算机技术、无线通信技术甚至空间技术的帮助下&#xff0c;不断探索更…

ORA-04031

ORA-04031&#xff1a;unable to allocate 3264 bytes of shared memory 1、问题背景 修改SGA重启数据库后报错系统内存&#xff1a;8G 原SGA大小&#xff1a;3G 修改后SGA大小&#xff1a;5G数据库可以正常重启&#xff0c;但是trance日志一直在报错 2、解决办法 调整shared…

湘大 XTU OJ 1148 三角形 题解(非常详细):根据题意朴素模拟+观察样例分析需要计算几轮 具体到一般

一、链接 1148 三角形 二、题目 题目描述 给一个序列&#xff0c;按下面的方式进行三角形累加&#xff0c;求其和值。 比如序列为 1,2,3,4,5 1 2 3 4 53 5 7 98 12 1620 2848输入 有多组样例。每个样例的第一行是一个整数N(1≤N≤100),表示序列的大小&…