Android Studio Xposed模块编写(二)
阅读本文前,假设读者已经看过Android Studio Xposed模块编写(一) 相关环境已经搭建完成。本文演示案例与上文环境一致,不在赘述。
1、概述
Xposed是非常牛叉的一款hook框架,本人也是刚刚接触,在网上搜索一些资料,发现写的都不是太全面,于是搜集该框架的用法,总结出该文。如有纰漏,还请轻拍,主要内容包括
1、如何Hook静态变量
2、如何Hook构造方法
3、如何Hook复杂参数的方法
4、如何替换函数执行内容
5、如何Hook内部类中的函数
6、如何Hook匿名类的函数
7、如何获取调用对象去调用函数,或者新建新建示例去调用方法
学会这些方法,在结合逆向smail的一些知识,应该可以满足大多数java层的hook了。话不多说,上代码!
2、Hook目标程序源码
HookDemo.java
abstract class Animal{
int anonymoutInt = 500;
public abstract void eatFunc(String value);
}
public class HookDemo {
private String Tag = "HookDemo";
private static int staticInt = 100;
public int publicInt = 200;
private int privateInt = 300;
public HookDemo(){
this("NOHook");
Log.d(Tag, "HookDemo() was called|||");
}
private HookDemo(String str){
Log.d(Tag, "HookDemo(String str) was called|||" + str);
}
public void hookDemoTest(){
Log.d(Tag, "staticInt = " + staticInt);
Log.d(Tag, "PublicInt = " + publicInt);
Log.d(Tag, "privateInt = " + privateInt);
publicFunc("NOHook");
Log.d(Tag, "PublicInt = " + publicInt);
Log.d(Tag, "privateInt = " + privateInt);
privateFunc("NOHook");
staticPrivateFunc("NOHook");
String[][] str = new String[1][2];
Map map = new HashMap<String, String>();
map.put("key", "value");
ArrayList arrayList = new ArrayList();
arrayList.add("listValue");
complexParameterFunc("NOHook", str, map, arrayList);
repleaceFunc();
anonymousInner(new Animal() {
@Override
public void eatFunc(String value) {
Log.d(Tag, "eatFunc(String value) was called|||" + value);
Log.d(Tag, "anonymoutInt = " + anonymoutInt);
}
}, "NOHook");
InnerClass innerClass = new InnerClass();
innerClass.InnerFunc("NOHook");
}
public void publicFunc(String value){
Log.d(Tag, "publicFunc(String value) was called|||" + value);
}
private void privateFunc(String value){
Log.d(Tag, "privateFunc(String value) was called|||" + value);
}
static private void staticPrivateFunc(String value){
Log.d("HookDemo", "staticPrivateFunc(Strin value) was called|||" + value);
}
private void complexParameterFunc(String value, String[][] str, Map<String,String> map, ArrayList arrayList)
{
Log.d("HookDemo", "complexParameter(Strin value) was called|||" + value);
}
private void repleaceFunc(){
Log.d(Tag, "repleaceFunc will be replace|||");
}
public void anonymousInner(Animal dog, String value){
Log.d(Tag, "anonymousInner was called|||" + value);
dog.eatFunc("NOHook");
}
private void hideFunc(String value){
Log.d(Tag, "hideFunc was called|||" + value);
}
class InnerClass{
public int innerPublicInt = 10;
private int innerPrivateInt = 20;
public InnerClass(){
Log.d(Tag, "InnerClass constructed func was called");
}
public void InnerFunc(String value){
Log.d(Tag, "InnerFunc(String value) was called|||" + value);
Log.d(Tag, "innerPublicInt = " + innerPublicInt);
Log.d(Tag, "innerPrivateInt = " + innerPrivateInt);
}
}
}
3、XposedHook程序源码
public class XposedHook implements IXposedHookLoadPackage {
@Override
public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
if (loadPackageParam.packageName.equals("com.example.xposedhooktarget")) {
final Class<?> clazz = XposedHelpers.findClass("com.example.xposedhooktarget.HookDemo", loadPackageParam.classLoader);
//getClassInfo(clazz);
//不需要获取类对象,即可直接修改类中的私有静态变量staticInt
XposedHelpers.setStaticIntField(clazz, "staticInt", 99);
//Hook无参构造函数,啥也不干。。。。
XposedHelpers.findAndHookConstructor(clazz, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("Haha, HookDemo constructed was hooked" );
//大坑,此时对象还没有建立,即不能获取对象,也不能修改非静态变量的值
//XposedHelpers.setIntField(param.thisObject, "publicInt", 199);
//XposedHelpers.setIntField(param.thisObject, "privateInt", 299);
}
});
//Hook有参构造函数,修改参数
XposedHelpers.findAndHookConstructor(clazz, String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[0] = "Haha, HookDemo(str) are hooked";
}
});
//Hook有参构造函数,修改参数------不能使用XC_MethodReplacement()替换构造函数内容,
//XposedHelpers.findAndHookConstructor(clazz, String.class, new XC_MethodReplacement() {
// @Override
// protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
// Log.d("HookDemo" , "HookDemo(str) was replace");
// }
//});
//Hook公有方法publicFunc,
// 1、修改参数
// 2、修改下publicInt和privateInt的值
// 3、再顺便调用一下隐藏函数hideFunc
//XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo", clazz.getClassLoader(), "publicFunc", String.class, new XC_MethodHook()
XposedHelpers.findAndHookMethod(clazz, "publicFunc", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[0] = "Haha, publicFunc are hooked";
XposedHelpers.setIntField(param.thisObject, "publicInt", 199);
XposedHelpers.setIntField(param.thisObject, "privateInt", 299);
// 让hook的对象本身去执行流程
Method md = clazz.getDeclaredMethod("hideFunc", String.class);
md.setAccessible(true);
//md.invoke(param.thisObject, "Haha, hideFunc was hooked");
XposedHelpers.callMethod(param.thisObject, "hideFunc", "Haha, hideFunc was hooked");
//实例化对象,然后再调用HideFunc方法
//Constructor constructor = clazz.getConstructor();
//XposedHelpers.callMethod(constructor.newInstance(), "hideFunc", "Haha, hideFunc was hooked");
}
});
//Hook私有方法privateFunc,修改参数
//XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo", clazz.getClassLoader(), "privateFunc", String.class, new XC_MethodHook()
XposedHelpers.findAndHookMethod(clazz, "privateFunc", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[0] = "Haha, privateFunc are hooked";
}
});
//Hook私有静态方法staticPrivateFunc, 修改参数
XposedHelpers.findAndHookMethod(clazz, "staticPrivateFunc", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[0] = "Haha, staticPrivateFunc are hooked";
}
});
//Hook复杂参数函数complexParameterFunc
Class fclass1 = XposedHelpers.findClass("java.util.Map", loadPackageParam.classLoader);
Class fclass2 = XposedHelpers.findClass("java.util.ArrayList", loadPackageParam.classLoader);
XposedHelpers.findAndHookMethod(clazz, "complexParameterFunc", String.class,
"[[Ljava.lang.String;", fclass1, fclass2, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[0] = "Haha, complexParameterFunc are hooked";
}
});
//Hook私有方法repleaceFunc, 替换打印内容
XposedHelpers.findAndHookMethod(clazz, "repleaceFunc", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam methodHookParam) throws Throwable {
Log.d("HookDemo", "Haha, repleaceFunc are replaced");
return null;
}
});
//Hook方法, anonymousInner, 参数是抽象类,先加载所需要的类即可
Class animalClazz = loadPackageParam.classLoader.loadClass("com.example.xposedhooktarget.Animal");
XposedHelpers.findAndHookMethod(clazz, "anonymousInner", animalClazz, String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
XposedBridge.log("HookDemo This is test");
param.args[1] = "Haha, anonymousInner are hooked";
}
});
//Hook匿名类的eatFunc方法,修改参数,顺便修改类中的anonymoutInt变量
XposedHelpers.findAndHookMethod("com.example.xposedhooktarget.HookDemo$1", clazz.getClassLoader(),
"eatFunc", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[0] = "Haha, eatFunc are hooked";
XposedHelpers.setIntField(param.thisObject, "anonymoutInt", 499);
}
});
//hook内部类的构造方法失败,且会导致hook内部类的InnerFunc方法也失败,原因不明
// XposedHelpers.findAndHookConstructor(clazz1, new XC_MethodHook() {
// @Override
// protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
// XposedBridge.log("Haha, InnerClass constructed was hooked" );
// }
// });
//Hook内部类InnerClass的InnerFunc方法,修改参数,顺便修改类中的innerPublicInt和innerPrivateInt变量
final Class<?> clazz1 = XposedHelpers.findClass("com.example.xposedhooktarget.HookDemo$InnerClass", loadPackageParam.classLoader);
XposedHelpers.findAndHookMethod(clazz1, "InnerFunc", String.class, new XC_MethodHook() {
@Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
param.args[0] = "Haha, InnerFunc was hooked";
XposedHelpers.setIntField(param.thisObject, "innerPublicInt", 9);
XposedHelpers.setIntField(param.thisObject, "innerPrivateInt", 19);
}
});
}
}
private void getClassInfo(Class clazz) {
//getFields()与getDeclaredFields()区别:getFields()只能访问类中声明为公有的字段,私有的字段它无法访问,
//能访问从其它类继承来的公有方法.getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,
//不能访问从其它类继承来的方法
//getMethods()与getDeclaredMethods()区别:getMethods()只能访问类中声明为公有的方法,私有的方法它无法访问,
//能访问从其它类继承来的公有方法.getDeclaredFields()能访问类中所有的字段,与public,private,protect无关,
//不能访问从其它类继承来的方法
//getConstructors()与getDeclaredConstructors()区别:getConstructors()只能访问类中声明为public的构造函数
//getDeclaredConstructors()能访问类中所有的构造函数,与public,private,protect无关
//XposedHelpers.setStaticObjectField(clazz,"sMoney",110);
//Field sMoney = clazz.getDeclaredField("sMoney");
//sMoney.setAccessible(true);
Field[] fs;
Method[] md;
Constructor[] cl;
fs = clazz.getFields();
for (int i = 0; i < fs.length; i++) {
XposedBridge.log("HookDemo getFiled: " + Modifier.toString(fs[i].getModifiers()) + " " +
fs[i].getType().getName() + " " + fs[i].getName());
}
fs = clazz.getDeclaredFields();
for (int i = 0; i < fs.length; i++) {
XposedBridge.log("HookDemo getDeclaredFields: " + Modifier.toString(fs[i].getModifiers()) + " " +
fs[i].getType().getName() + " " + fs[i].getName());
}
md = clazz.getMethods();
for (int i = 0; i < md.length; i++) {
Class<?> returnType = md[i].getReturnType();
XposedBridge.log("HookDemo getMethods: " + Modifier.toString(md[i].getModifiers()) + " " +
returnType.getName() + " " + md[i].getName());
//获取参数
//Class<?> para[] = md[i].getParameterTypes();
//for (int j = 0; j < para.length; ++j) {
//System.out.print(para[j].getName() + " " + "arg" + j);
//if (j < para.length - 1) {
// System.out.print(",");
//}
//}
}
md = clazz.getDeclaredMethods();
for (int i = 0; i < md.length; i++) {
Class<?> returnType = md[i].getReturnType();
XposedBridge.log("HookDemo getDeclaredMethods: " + Modifier.toString(md[i].getModifiers()) + " " +
returnType.getName() + " " + md[i].getName());
}
cl = clazz.getConstructors();
for (int i = 0; i < cl.length; i++) {
XposedBridge.log("HookDemo getConstructors: " + Modifier.toString(cl[i].getModifiers()) + " " +
md[i].getName());
}
cl = clazz.getDeclaredConstructors();
for (int i = 0; i < cl.length; i++) {
XposedBridge.log("HookDemo getDeclaredConstructors: " + Modifier.toString(cl[i].getModifiers()) + " " +
md[i].getName());
}
}
}
4、Hook运行结果

5、源码地址
Hook目标程序源码https://github.com/Gordon0918/XposedHookTarget
Hook程序源码https://github.com/Gordon0918/XposedHook
Android Studio Xposed模块编写(二)的更多相关文章
- Android Studio Xposed模块编写(一)
1.环境说明 本文主要参考https://my.oschina.net/wisedream/blog/471292?fromerr=rNPFQidG的内容,自己实现了一遍,侵权请告知 已经安装xpos ...
- Android Studio 入门级教程(二):新建一个属于自己的工程并安装Genymotion模拟器
声明 生命壹号:http://www.cnblogs.com/smyhvae/ 文章来源:http://www.cnblogs.com/smyhvae/p/4392611.html [系列] Andr ...
- Android Studio使用教程(二)
以下是本次Google I/O大会发布的IDE Android Studio使用教程第二篇: 在Android Studio使用教程(一)中简要介绍了Android Studio的基本使用,包括安装. ...
- 5.1、Android Studio用Logcat编写和查看日志
Android Studio在Android Monitor中包含了一个logcat的tab,可以打印系统事件,比如垃圾回收发生时,实时打印应用消息. 为了显示需要的信息,你可以创建过滤器,更改需要显 ...
- Android的硬件抽象层模块编写规范
硬件抽象层模块编写规范 Android系统的硬件抽象层以模块的形式来管理各个硬件訪问接口.每个硬件模块都相应有一个动态链接库文件.这些动态链接库文件的命令须要符合一定的规范.同一时候,在系统内部. ...
- [Android Studio] Android Studio使用教程(二)
以下是本次Google I/O大会发布的IDE Android Studio使用教程第二篇: 在Android Studio使用教程(一)中简要介绍了Android Studio的基本使用,包括安装. ...
- Android Studio安卓学习笔记(二)Android项目结构
上一篇代码,我们学习了Android的功能以及如何用Android Studio开发第一个安卓程序.下面就要介绍Android项目结构.为日后学习打基础. 一:Android项目结构 打开MyFris ...
- Android Studio的使用(二)--Debug调试
使用Android Studio进行Debug调试,这里有一篇比较详细的介绍 http://www.2cto.com/kf/201506/408358.html 故不再重复介绍.
- Android Studio 插件开发详解二:工具类
转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/78112856 本文出自[赵彦军的博客] 在插件开发过程中,我们按照开发一个正式的项 ...
随机推荐
- LeetCode题解之Longest Continuous Increasing Subsequence
1.题目描述 2.问题分析 从每一个num[i]往前扫描即可. 3.代码 int findLengthOfLCIS(vector<int>& nums) { ){ return n ...
- Python字符串和编码
在最早的时候只有127个字符被编码到计算机里,也就是大小写英文字母.数字和一些符号,这个编码被成为ASCII编码. 但是要处理中文显然一个字节是不够的,至少需要两个字节,而且还不能和ASCII编码冲突 ...
- windows10移动热点打开后手机不能上网
电脑的win10操作系统自带有移动热点功能,可以共享上网,类似于手机的热点功能.今天在共享时遇到一些问题,现在解决了分享一下. 如果本身电脑无法上网,即wlan上网功能无效,有可能是驱动不兼容,可以在 ...
- MySQL分析函数实现
| MySQL分析函数实现还好MySQL8.0已经实现了与Oracle相同的分析函数. 1. 实现rownumSET @rn:=0;SELECT @rn:=@rn+1 AS rownum ,e.* F ...
- UNIX高级环境编程(15)进程和内存分配 < 故宫角楼 >
故宫角楼是很多摄影爱好者常去的地方,夕阳余辉下的故宫角楼平静而安详. 首先,了解一下进程的基本概念,进程在内存中布局和内容. 此外,还需要知道运行时是如何为动态数据结构(如链表和二叉树)分配额外内 ...
- Apache的权限设置与构建虚拟web主机
实验拓扑图: 实验要求: 1. 搭建WEB服务器,能访问默认站点,并使用awstats软件能监控到默认站点的访问情况. 2. 修改Apache的主配置文件,设置1.10只能访问awstats网站, ...
- unity StrangeIoc
已经很久没有写博客,主要原因还是自我荒废了太久,在学习上失去了动力.最近来新的公司实习,以前都是做项目的开发,现在被调到框架组,主要从事的是框架维护还有开发.学习了许多新的知识还有优秀的框架,今天就写 ...
- Linux第三课——目录操作
ls 列出目录下的文件及子目录 ls -l 以列表的方式显示详细信息 ls -a 显示所有的 包括隐藏文件 ls -A 显示除了 . ..以外的任何文件 ls -i 显示文件的节点号 ls --col ...
- C语言编程积累2
版权声明:本文为CSDN博主(天才2012)原创文章,未经博主同意不得转载. https://blog.csdn.net/gzzaigcn/article/details/27113957 寥寥数笔, ...
- [luogu2469] 星际竞速
题面 巨佬一眼就能看出这是最小路径覆盖, 我这个蒟蒻还是太弱了... 我们可以知道跳跃值为点权w[i], 两点之间距离为边权ww 对于每个点, 在最小路径覆盖问题中, 假设每个点都是一条路 ...