查找和定位Android应用的按钮点击事件的代码位置基于Xposed Hook实现
本文博客地址:https://blog.csdn.net/QQ1084283172/article/details/80956455
在进行Android程序的逆向分析的时候,经常需要通过Android应用程序的界面UI来定位代码的位置,比较常见的例子就是分析Android应用的网络协议时,用户点击登录按钮,实现客户端程序的登录,将用户的账号信息发送给服务器端进行验证,那么我们分析这个网络数据传输的流程中,首先要定位用户点击登录按钮的事件响应代码在哪里,当然了基于特征字符串的搜索和smali字节码的搜索都可以实现,感觉比较费时间或者效果不好,这里介绍一种基于Xposed Hook实现查找和定位Android应用的按钮点击事件的代码位置的方法,Xposed Hook的代码如下:
package com.xposed.enumeratorClassHook;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import android.view.View;
import android.widget.Button;
import de.robv.android.xposed.IXposedHookLoadPackage;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage.LoadPackageParam;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
// 自定义的回调函数接口
public class Module implements IXposedHookLoadPackage {
static String strClassName = "";
@Override
public void handleLoadPackage(final LoadPackageParam lpparam) throws Throwable {
// 被Hook操作的目标Android应用的包名,进行Hook操作的过滤
String strPackageName = "com.guji.loveparty";
if (lpparam.packageName.equals(strPackageName)) {
XposedBridge.log("Loaded App:" + lpparam.packageName);
// 不在Android应用默认的classes.dex文件中的类方法的Hook操作,例如:
// 1.MultiDex情况下的,多dex文件中的类方法的Hook操作,例如:classes1.dex中的类方法
// 2.主dex加载的jar(包含dex)情况下的,类方法的的Hook操作
// Hook类方法ClassLoader#loadClass(String)
findAndHookMethod(ClassLoader.class, "loadClass", String.class, new XC_MethodHook() {
// 在类方法loadClass执行之后执行的代码
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 参数的检查
if (param.hasThrowable()) {
return;
}
// 获取指定名称的类加载之后的Class<?>
Class<?> clazz = (Class<?>) param.getResult();
// 获取加载的指定类的名称
String strClazz = clazz.getName();
XposedBridge.log("LoadClass : "+strClazz);
// 所有的类都是通过loadClass方法加载的
// 过滤掉Android系统的类以及一些常见的java类库
if (!strClazz.contains("xposed")) {
// 或者只Hook加密算法类、网络数据传输类、按钮事件类等协议分析的重要类
// 同步处理一下
synchronized (this.getClass()) {
// 获取被Hook的目标类的名称
strClassName = strClazz;
//XposedBridge.log("HookedClass : "+strClazz);
// 获取到指定名称类声明的所有方法的信息
Method[] m = clazz.getDeclaredMethods();
// 打印获取到的所有的类方法的信息
for (int i = 0; i < m.length; i++) {
//XposedBridge.log("HOOKED CLASS-METHOD: "+strClazz+"-"+m[i].toString());
if (!Modifier.isAbstract(m[i].getModifiers()) // 过滤掉指定名称类中声明的抽象方法
&& !Modifier.isNative(m[i].getModifiers()) // 过滤掉指定名称类中声明的Native方法
&& !Modifier.isInterface(m[i].getModifiers()) // 过滤掉指定名称类中声明的接口方法
) {
// Hook处理类方法findViewById
// public final View findViewById(int id)
if ((m[i].getName()).contains("findViewById")) {
// 对指定名称类中声明的非抽象方法进行java Hook处理
XposedBridge.hookMethod(m[i], new XC_MethodHook() {
// 被java Hook的类方法执行完毕之后,打印log日志
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 打印被java Hook的类方法的名称和参数类型等信息
XposedBridge.log("HOOKED METHOD: "+strClassName+"-"+param.method.toString()+"findViewById: "+param.args[0].toString());
// View view = (View)param.getResult();
// XposedBridge.log("View-id: "+view.getId()+ "findViewById: "+param.args[0].toString());
}
});
}
// public void setText(CharSequence text)
if ((m[i].getName()).contains("setText")) {
// 对指定名称类中声明的非抽象方法进行java Hook处理
XposedBridge.hookMethod(m[i], new XC_MethodHook() {
// 被java Hook的类方法执行完毕之后,打印log日志
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 打印被java Hook的类方法的名称和参数类型等信息
XposedBridge.log("HOOKED METHOD: "+strClassName+"-"+param.method.toString()+ "setText: "+param.args[0].toString());
// View view = (View)param.thisObject;
// XposedBridge.log("View-id: "+view.getId()+ "setText: "+param.args[0].toString());
}
});
}
// Hook处理类方法setOnClickListener
// public void setOnClickListener(OnClickListener l)
if ((m[i].getName()).contains("setOnClickListener")) {
// 对指定名称类中声明的非抽象方法进行java Hook处理
XposedBridge.hookMethod(m[i], new XC_MethodHook() {
// 被java Hook的类方法执行完毕之后,打印log日志
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 打印被java Hook的类方法的名称和参数类型等信息
XposedBridge.log("HOOKED METHOD: "+strClassName+"-"+param.method.toString()+ "setOnClickListener: "+param.args[0].toString());
// View view = (View)param.thisObject;
// XposedBridge.log("View-id: "+view.getId()+ "setOnClickListener: "+param.args[0].toString());
}
});
}
// Hook处理类方法onClick
// public void onClick(View v)
if ((m[i].getName()).contains("onClick")) {
// 对指定名称类中声明的非抽象方法进行java Hook处理
XposedBridge.hookMethod(m[i], new XC_MethodHook() {
// 被java Hook的类方法执行完毕之后,打印log日志
@Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
// 打印被java Hook的类方法的名称和参数类型等信息
XposedBridge.log("HOOKED METHOD: "+strClassName+"-"+param.method.toString()+"onClick: "+param.args[0].toString());
// View view = (View)param.thisObject;
// XposedBridge.log("View-id: "+view.getId()+ "onClick: "+param.args[0].toString());
}
});
}
}
}
}
}
}
});
}
}
// 获取指定名称的类声明的类成员变量、类方法、内部类的信息
public void dumpClass(Class<?> actions) {
XposedBridge.log("Dump class " + actions.getName());
XposedBridge.log("Methods");
// 获取到指定名称类声明的所有方法的信息
Method[] m = actions.getDeclaredMethods();
// 打印获取到的所有的类方法的信息
for (int i = 0; i < m.length; i++) {
XposedBridge.log(m[i].toString());
}
XposedBridge.log("Fields");
// 获取到指定名称类声明的所有变量的信息
Field[] f = actions.getDeclaredFields();
// 打印获取到的所有变量的信息
for (int j = 0; j < f.length; j++) {
XposedBridge.log(f[j].toString());
}
XposedBridge.log("Classes");
// 获取到指定名称类中声明的所有内部类的信息
Class<?>[] c = actions.getDeclaredClasses();
// 打印获取到的所有内部类的信息
for (int k = 0; k < c.length; k++) {
XposedBridge.log(c[k].toString());
}
}
}
/**
* Look up a method and place a hook on it. The last argument must be the callback for the hook.
* @see #findMethodExact(Class, String, Object...)
*/
/* 目标java方法的Hook
public static XC_MethodHook.Unhook findAndHookMethod(Class<?> clazz, String methodName, Object... parameterTypesAndCallback) {
if (parameterTypesAndCallback.length == 0 || !(parameterTypesAndCallback[parameterTypesAndCallback.length-1] instanceof XC_MethodHook))
throw new IllegalArgumentException("no callback defined");
XC_MethodHook callback = (XC_MethodHook) parameterTypesAndCallback[parameterTypesAndCallback.length-1];
Method m = findMethodExact(clazz, methodName, getParameterClasses(clazz.getClassLoader(), parameterTypesAndCallback));
return XposedBridge.hookMethod(m, callback);
}*/
/** @see #findAndHookMethod(Class, String, Object...) */
/* 目标java方法的Hook
public static XC_MethodHook.Unhook findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback) {
return findAndHookMethod(findClass(className, classLoader), methodName, parameterTypesAndCallback);
}*/
/**
* Loads the class with the specified name. Invoking this method is
* equivalent to calling {@code loadClass(className, false)}.
* <p>
* <strong>Note:</strong> In the Android reference implementation, the
* second parameter of {@link #loadClass(String, boolean)} is ignored
* anyway.
* </p>
*
* @return the {@code Class} object.
* @param className
* the name of the class to look for.
* @throws ClassNotFoundException
* if the class can not be found.
*/
//public Class<?> loadClass(String className) throws ClassNotFoundException {
// return loadClass(className, false);
// }
基于Xposed Hook框架查找和定位Android应用的按钮点击事件的代码位置的效果如下图所示:
说明:Xposed Hook的代码写的比较简单,还有很多需要优化和改进的地方,比如怎么提高Xposed Hook框架的Hook效率,怎么防止这种低效的Hook操作导致的Android应用的无响应或者崩溃。
查找和定位Android应用的按钮点击事件的代码位置基于Xposed Hook实现的更多相关文章
- 【转】Android开发20——单个监听器监听多个按钮点击事件
原文网址:http://woshixy.blog.51cto.com/5637578/1093936 原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律 ...
- 【Android】按钮点击事件的常用写法
学习总结: 最近学习了Android点击事件的常用写法.点击事件会触发监听对象身上的回调,常用写法有以下四种: 方法一:使用匿名内部类. public class MainActivity exten ...
- Android Listview中Button按钮点击事件冲突解决办法
今天做项目时,ListView中含有了Button组件,心里一早就知道肯定会有冲突,因为以前就遇到过,并解决过,可惜当时没有记录下来. 今天在做的时候,继续被这个问题郁闷了一把,后来解决后,赶紧来记录 ...
- js触发按钮点击事件
js触发按钮点击事件 博客分类: javascript 模拟JS触发按钮点击功能 <html> <head> <title>usually function&l ...
- 按钮点击事件,打开新的Activity
按钮点击事件,打开新Activity, 打开网页 findViewById(R.id.btnStartBAty).setOnClickListener(new View.OnClickListener ...
- Objective-C:模拟按钮点击事件理解代理模式
OC中的协议(Protocol)和和.NET中的接口(Interface)类似,简单来讲,就是一系列方法的列表,其中声明的方法可以被任何类实现.不同的是,在.NET中,如果某个类实现了一个接口,就必须 ...
- Javascript之三种按钮点击事件
学习Javascript必须要先掌握基本的事件方法和语法,这些都是我们学过的也是最基本的.以前忘了总结,所以现在回顾,综合地总结一下,温故而知新. Javascript有三种按钮点击事件,分别为ale ...
- Android Button四种点击事件和长按事件
项目XML代码 <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:andr ...
- ButtonAddListener监听按钮点击事件
ButtonAddListener监听按钮点击事件 using UnityEngine; using System.Collections; using UnityEngine.UI; using U ...
随机推荐
- POJ-2349(kruskal算法+最小生成树中最大边的长度)
Arctic POJ-2349 这题是最小生成树的变形题目.题目的意思是已经有s个卫星频道,这几个卫星频道可以构成一部分的网络,而且不用费用,剩下的需要靠d的卫星接收器.题目要求的就是最小生成树中,最 ...
- 元数据管理—动态表单设计器在crudapi系统中完整实现
表单设计 在前面文章中,我们通过一系列案例介绍了表单设计的一些基本功能,表单设计起到非常重要作用,也是crudapi核心,所以本文会详细介绍表单设计中一些其它功能. 概要 表单字段column属性 列 ...
- CRLF注入漏洞 -配置错误
漏洞分析参考 https://i-beta.cnblogs.com/posts/edit 什么是CRLF? CRLF 指的是回车符(CR,ASCII 13,\r,%0d) 和换行符(LF,ASCII ...
- 【海思】Hi3516A 运行sample_venc的demo内核奔溃(DDR问题)
作者:李春港 出处:https://www.cnblogs.com/lcgbk/p/14514297.html 目录 一.前言 二.使用memtester对ddr进行压力测试 三.修改uboot的DD ...
- 目标检测入门论文YOLOV1精读以及pytorch源码复现(yolov1)
结果展示 其中绿线是我绘制的图像划分网格. 这里的loss是我训练的 0.77 ,由于损失函数是我自己写的,所以可能跟大家的不太一样,这个不重要,重要的是学习思路. 重点提示 yolov1是一个目标检 ...
- MySQL入门(3)——数据类型
MySQL入门(3)--数据类型 数字类型 整数数据类型: 数据类型 取值范围 说明 单位 TINYINT 符号值:-127~127无符号值:0~255 最小的整数 1字节 BIT 符号值:-127~ ...
- Fishing Master HDU - 6709
题目链接:https://vjudge.net/problem/HDU-6709 题意:给出n条鱼的抓捕时间k和煮鱼时间a[i],你要在最短时间把所有鱼都煮了.(注意你只有一口锅) 思路:首先我们必须 ...
- 图像Resize方式对深度学习模型效果的影响
在基于卷积神经网络的应用过程中,图像Resize是必不可少的一个步骤.通常原始图像尺寸比较大,比如常见监控摄像机出来的是1080P高清或者720P准高清画面,而网络模型输入一般没有这么大,像Yolo系 ...
- 打造云原生大型分布式监控系统系列文章-腾讯工程师roc
附上本系列文章链接 打造云原生大型分布式监控系统(一): 大规模场景下 Prometheus 的优化手段 打造云原生大型分布式监控系统(二): Thanos 架构详解 打造云原生大型分布式监控系统(二 ...
- [图论]最短网络:prim
最短网络 目录 最短网络 Description Input Output Sample Input Sample Output 解析 代码 Description 农民约翰被选为他们镇的镇长!他其中 ...