文章目录
- Android Hook框架介绍
- Cydia Substrate
- 插件编写步骤
- 实例:编写Cydia修改系统字体颜色
- Xposed
- 插件编写步骤
- 实例:Hook获取手机序列号
- 准备工作
- 获取hook所需要的数据
- 编写hook代码
- 效果测试
Android Hook框架介绍
Android中比较经典的Hook框架有两个
- Cydia Substrate,闭源,从苹果开始到Android
- xposed,开源,从Android开始到苹果
Cydia Substrate
插件编写步骤
Cydia Substrate插件编写的一般步骤:
- 导入substrate-api.jar
- 设置权限和入口
- 新建一个类实现回调函数
- 使用MS.hookClassLoad用于HOOK加载类
- 使用MS.hookMethod用于HOOK方法
实例:编写Cydia修改系统字体颜色
首先新建一个空的项目
将substrate-api.jar复制到libs目录下,jar下载地址如下:
http://asdk.cydiasubstrate.com/zips/cydia_substrate-r2.zip
接着右键打开模块设置
将jar包导入到模块依赖库
接着在清单文件中添加一个自定义的权限
<uses-permission android:name="cydia.permission.SUBSTRATE"></uses-permission>
添加一个meta-data标签,并指定入口类
<meta-data name="com.saurik.substrate.main" android:value=".Main"></meta-data>
然后新建一个入口类,命名为Main
package com.example.cydiademo;
import android.content.res.Resources;
import android.util.Log;
import com.saurik.substrate.MS;
import java.lang.reflect.Method;
public class Main {
static void initialize() {
//1.hook指定的类-->android.content.res.Resources
MS.hookClassLoad("android.content.res.Resources", new MS.ClassLoadHook() {
@Override
public void classLoaded(Class<?> aClass) {
//2.1 获取老的方法对象
Method method=null;
try {
method=aClass.getMethod("getColor",int.class);
} catch (NoSuchMethodException e) {
e.printStackTrace();
}
if (method==null){
Log.d("GuiShou","method==null");
return;
}
//2.hook指定的方法-->getColor
//老的方法的指针
final MS.MethodPointer methodPointer=new MS.MethodPointer();
MS.hookMethod(aClass, method, new MS.MethodHook() {
@Override
public Object invoked(Object o, Object... objects) throws Throwable {
//hook代码
//调用老的方法,获取color
int color= (int) methodPointer.invoke(o,objects);
//修改color并返回
return color&~0x0000ff00|0x00ff0000;
}
},methodPointer);
}
});
}
}
接着实现initialize方法,修改系统字体颜色。到此插件编写完成,这个hook框架需要运行在真机环境下,所以暂时看不到效果。
Xposed
插件编写步骤
Xposed是一个开源的Hook框架,可定制性强;其提供了SDK可以写插件,轻松完成hook。基本步骤如下:
- 创建一个无Activity的工程
- 设置清单文件信息
- 导入Xposed jar包,并设置为privoder(complie only)
- 创建一个主类并实现Xposed中的接口
- 重新handleLoadPackage方法
- 建立xposed_init文件外部声明主类
- 在handleLoadPackage中完善Hook代码
实例:Hook获取手机序列号
需要HOOK的目标程序如下:
app运行之后,会显示当前的设备ID
准备工作
新建一个工程,将XposedBridge-82.jar复制到新建的lib目录下
打开模块设置,将jar包导入到模块,并设置Configuration为compileOnly
<meta-data android:name="xposedmodule" android:value="true"></meta-data>
<meta-data android:name="xposeddescription" android:value="XX神器"></meta-data>
<meta-data android:name="xposedminversion" android:value="54"></meta-data>
在清单文件中添加上面的字段
接着新建一个类,命名为Main
public class Main implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
}
}
并实现IXposedHookLoadPackage接口,然后在handleLoadPackage函数内编写Hook代码
接着指定入口类,新建assets/xposed_init文件,然后将入口类写到该文件内。准备工作就已经完成,接着开始编写hook代码。
获取hook所需要的数据
需要对app进行hook需要知道下面几个数据
- 包名
- 类名
- 方法原型
首先来查看一下需要HOOK的目标app代码
显示设备ID的代码在onCreate方法中
public void onCreate(Bundle savedInstanceState) {
IncrementalChange incrementalChange = $change;
if (incrementalChange != null) {
incrementalChange.access$dispatch("onCreate.(Landroid/os/Bundle;)V", this, savedInstanceState);
return;
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
((TextView) findViewById(R.id.textinfo)).setText("设备ID: " + ((TelephonyManager) getSystemService("phone")).getDeviceId());
}
需要Hook的类名是TelephonyManager
,方法名是getDeviceId
接着Android Studio的自动导入功能可以看到完整的类名是
android.telephony.TelephonyManager
然后进入类内搜索方法名,即可获取到完整的方法原型
public String getDeviceId()
然后查看清单文件
在清单文件中可以查看到包名为com.bluelesson.testphoneinfo
编写hook代码
接着编写hook代码如下:
public class Main implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam Param) throws Throwable {
//包名 com.bluelesson.testphoneinfo
//类名 android.telephony.TelephonyManager
//方法名 public String getDeviceId()
String packageName=Param.packageName;
if (!packageName.equals("com.bluelesson.testphoneinfo"))
return;
XposedHelpers.findAndHookMethod(TelephonyManager.class,//类类型
"getDeviceId",//方法名
new XC_MethodReplacement() { //回调
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
return "我就是序列号";
}
});
}
}
替换getDeviceId函数,直接返回序列号
效果测试
在模拟器中安卓xposed框架
第一次进入需要安装更新以激活框架
然后直接安卓app到模拟器,提示Xposed模块未激活
勾选当前模块
返回到Xposed插件主页,点击软重启
打开目标app,可以看到当前的设备ID已经被修改了