Xposed框架详解

        最近接触了Android开发中用到的比较火的一个框架——Xposed框架。那么什么是Xposed框架呢?

     (文章参考了http://blog.csdn.net/zhangmiaoping23/article/details/52572447

1、什么是Xposed框架?

        百度百科上给出的定义是:Xposed是一款可以在不修改APK的情况下影响程序运行(修改系统)的框架服务,基于Xposed可以制作出许多功能强大的模块,且在功能不冲突的情况下同时运作。

        优点:Xposed是基于AOSP(android open source project)开发的,对源代码改动不大的ROM兼容性比较好,这也就使得某一功能可以借助Xposed移植到不同的ROM上。例如:现在你的手机上所拥有的功能你已经很喜欢了,但是又羡慕其他系统所独特拥有的功能,那么我们就可以通过Xpose框架将另一系统上的某些功能模块移植到我们自己的android系统上。如果想要恢复系统的原状的话,只需要在Xposed里取消对其他功能的勾选就可以了。

        注意:Xposed的安装需要root权限。

2、Xposed框架如何配置在eclipse上,进行模块的开发?

        首先准备好eclipse、XposedBridge.jar包、SDK、JDK。将XposedBridge.jar包放在新建项目的lib/libs下面,然后右键buildpath 

3、Xposed框架的核心思想?

        Xposed的核心思想是将Java层的普通的函数注册成本地的JNI(Java native interface)方法,以此来变相实现hook机制。

        Java native interface:它提供了若干的API,实现了Java和其他语言的通信(主要是C/C++)

3.1 Android程序是在Dalvik虚拟机上运行的,那么Dalvik在执行Java层代码时,是如何识别JNI方法的?首先来看一下类的的加载过程:(类第一次被使用)——>(类的字节码被加载到内存)——>(字节码的入口维持着该类所有方法描述符的list)      这些描述符包含着:(方法代码存于何处)(有哪些参数)如果一个方法描述符内有native,这些描述符快将有一个指向该方法的实现的指针。

一个类执行之前会先被装载,之后需要字节码验证,检验完成之后,虚拟机会紧接着调用findClass()来查找并装载main的方法类,然后再调用类中的成员函数.CallStaticVoidMethod执行main方法,程序开始运行。

3.2那么我们如何将Java层的普通的方法注册成JNI方法呢?

(1)SET_METHOD_FLAG(method,ACC_NATIVE):将方法描述符中的accessFlags修改为NATIVE方法
(2)method->nativeFunc=&xposedCallHandler:存储该方法实际调用的本地方法的执行位置,将要hook的Java层方法注册成本地方法。Native层方法统一的入口点设置为xposedCallHandler
(3)method->insns=(const  u2*)hookInfo:insns存储该方法没被native之前的位置
(4)method->registersSize=method->size:为注册的nativeFunc方法参数列表分配内存空间,与Java自带方法的等大小即可

3.3xposed框架在其中做了些什么呢?

        xposed修改了app_process,在执行第一个Java程序之前进行截获,改变程序的执行流程,进入到自身的main函数里面。main函数的执行体内主要完成了下面四个功能:
(1)initNative():——>是本地的方法,完成了xposed框架的初始化工作
(2)initXbridgeZygote():——>主要hook了几个涉及到应用程序创建、启动的关键类。新的应用进程创建时会调用这几个类的特定方法,xposed框架通过截获应用进程创建时的相关信息来决定对其处理逻辑。
(3)loadModules():——>读取系统中放置的hook模块。简单地说就是把hook模块随便找个地方丢进去,然后把该模块的路径写进conf/modules.list中就可以了。
         1)读取conf/modules.list文件中写入的apk的名称
         2)从每一个apk中读取其/assets/xposed_init文件中声明的hook主模块的类的名称
         3)classLoader加载各hook主模块类
         4)判断加载的类属于哪一种类别
(4)执行原com.android.internal.os.ZygotelInit的main函数,完成zygote的初始化工作
xposed框架加载完毕后,将执行权交给com.Android.interbal.os.ZygoteInit,完成正常的系统启动流程
总结:
——创建新的应用,获取包名  等信息
——调用XC_LoadPackage.callAll,依次执行各hook模块的代码,如果有包名匹配的hook模块,则注册模块中要hook的方法为本地Native方法
——当该方法被调用的时候,转移到本地的xposedCallHandler
—— XposedCallHandler回调上层handlerHookedMethod
——handlerHookedMethod执行加载的各hook模块     

4、微信运动   

    微信运动是想获取到我们走了多少步。Android机会有自带的计数传感器。当应用程序想要知道我们走了多少步的时候,需要去询问计数传感器;计数传感器得到请求
之后,会把步数返回给应用程序,这样的话,应用程序就可以通过页面向我们展示我们走的步数了。所以,如果我们想要在不知不觉的情况下,修改步数的话,我们就需要在计
数传感器向应用程序返回数据的时候,进行拦截,然后修改处理逻辑,再将数据返回。
        因为是第一次真正的接触android,所以下面的代码是参考着http://blog.csdn.net/chenhao0428/article/details/51436837写的:
	
 
 
package com.example.xposedandriod;
import static de.robv.android.xposed.XposedHelpers.findClass;

import java.lang.reflect.Field;

import android.app.Activity;
import android.hardware.Sensor;
import android.util.Log;
import android.util.SparseArray;

import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.callbacks.XC_LoadPackage;

public class WeiXinSport extends Activity implements IXposedHookLoadPackage  {

	/**
	 * @param args
	 */
	private static int stepCount = 1;
	@Override
	public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable{
		if(!loadPackageParam.packageName.equals("com.tencent.mm")){//过滤来自微信的请求
			return;
		}
		//hook了andriod.hardware.SystemSensorManager$SensorEventQueue这个类中的dispatchSensorEvent这个方法
		final Class
    
     sensorEL = findClass("android.hardware.SystemSensorManager$SensorEventQueue",loadPackageParam.classLoader);
		XposedBridge.hookAllMethods(sensorEL,"dispatchSensorEvent", new XC_MethodHook(){
			@SuppressWarnings("unchecked")
			@Override
			protected void beforeHookedMethod(MethodHookParam param) throws Throwable{
				((float[]) param.args[1])[0] = ((float[]) param.args[1])[0] + 1200*stepCount;//计数传感器将步数返回微信运动之前被修改
				stepCount++;
				XposedBridge.log("stepCount"+stepCount);
				Field field = param.thisObject.getClass().getDeclaringClass().getDeclaredField("sHandleToSensor");
				field.setAccessible(true);
				
				//便于调试,将传感器的一些数据打印了出来
				int handle = (Integer)param.args[0];
				Sensor sensor = ((SparseArray
    
    
     
     ) field.get(0)).get(handle);
				XposedBridge.log("sensor = " + sensor);
			}
		});
	
	}
}

    
    
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值