Xposed常用逆向函数

1. 创建Xposed工程

在Android Studio中新建一个app工程,修改其中的 AndroidManifest.xml 文件,在<application></application>标签中增加如下代码

<meta-dataandroid:name="xposedmodule"android:value="true" />
<meta-dataandroid:name="xposeddescription"android:value="hello xposed" />
<meta-dataandroid:name="xposedminversion"android:value="82" />

在 app/libs 目录下添加Xposed的依赖库,api-82.jar, api-82-sources.jar(网上自行搜索)

修改 app 目录下的 build.gradle 文件,将以上的两个依赖库添加到 dependencies{} 中,如下

dependencies {compileOnly 'de.robv.android.xposed:api:82'compileOnly 'de.robv.android.xposed:api:82:sources'// other content......
}

在 mian 目录下创建一个assets文件夹,并在assets目录下创建一个 xposed_init 文件,文件中写入实现了 IXposedHookLoadPackage 接口的类名及包名;例如我当前新建了一个类 TestReverse 实现了 IXposedHookLoadPackage 接口,且当前包名为 com.test.xposed,则 xposed_init 中的内容应为

com.test.xposed.TestReverse

2. 相关API介绍

Xposed 模块API用法:XposedHelpers | Xposed Framework API

a.IXposedHookLoadPackage 接口,实现hook逻辑的类必须实现该接口,APP被加载的时候会调用该接口中的 handleLoadPackage(final XC_LoadPackage.LoadPackageParam lpparam) 方法,所以我们需要重写该函数,并在其中实现我们的hook逻辑

b.XC_LoadPackage.LoadPackageParam,该类下包含与正在加载的应用程序的有关信息。入下,其中packageName可以用于判断当前hook住的APP名称,processName表示当前APP所在的进程,classLoader表示当前APP使用的ClassLoader。

 c.XposedHelpers类

        1.findClass(String className, ClassLoader classLoader),使用特定的ClassLoader查找指定类,返回值为指定类的class;使用如下

final Class<?> callContextClass = XposedHelpers.findClass("com.alibaba.ariver.engine.api.bridge.model.NativeCallContext",lpparam.classLoader);

        2.XposedHelpers.findAndHookMethod(String className, ClassLoader classLoader, String methodName, Object... parameterTypesAndCallback),hook指定的方法。

        其中 Object... parameterTypesAndCallback是java中的范式,可以传递多个参数;当使用XposedHelpers.findAndHookMethod()方法时,需要传递被hook的函数所需要的全部参数的字节码,这些字节码可以通过.class获取到,或者findClass反射获取;java自带的类型比如String,就可以用String.class获取到。

        回调对象XC_MethodHook()需重写两个方法 beforeHookedMethod(MethodHookParam param):这个方法中的代码逻辑会在hook住的方法调用前执行 ;afterHookedMethod(MethodHookParam param) 方法中的代码逻辑则会在hook住的方法调用完成后执行。

        使用如下,以下代码逻辑表示,在com.baidu.swan.apps.jsbridge.SwanAppGlobalJsBridge 类下的 dispatchOnUiThread() 函数已经被hook住,在这个函数执行前后,beforeHookedMethod() 和 afterHookedMethod() 中的逻辑会分别执行。

XposedHelpers.findAndHookMethod("com.baidu.swan.apps.jsbridge.SwanAppGlobalJsBridge", lpparam.classLoader, "dispatchOnUiThread", String.class, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {super.beforeHookedMethod(param);XposedBridge.log("Baidu: dispatchOnUiThread 的线程:" + Thread.currentThread().getName());XposedBridge.log("Baidu:dispatchOnUiThread 入参:" + java.net.URLDecoder.decode(param.args[0].toString()) + "返回值:" + param.getResult());}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);Field mCallbackHandler = jsbridge_a.getDeclaredField("mCallbackHandler");Object mmCallbackHandler = (Object) mCallbackHandler.get(param.thisObject);//com.baidu.swan.apps.core.slave.SwanAppWebViewWidgetXposedBridge.log("Baidu: mCallbackHandler在webview里调用API时的实现类:" + mmCallbackHandler.getClass().getName());});

        3. XposedHelpers.findAndHookConstructor(String className, ClassLoader classLoader, Object... parameterTypesAndCallback),参数含义同上findAndHookMethod()。

        使用如下,以下代码逻辑表示,当 com.baidu.swan.apps.jsbridge.SwanAppNativeSwanJsBridge 类的构造函数被调用时,在构造函数执行前后,beforeHookedMethod() 和 afterHookedMethod() 中的逻辑会分别执行。

XposedHelpers.findAndHookConstructor("com.baidu.swan.apps.jsbridge.SwanAppNativeSwanJsBridge", lpparam.classLoader, container_a, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {super.beforeHookedMethod(param);Log.d("Baidu:", "SwanAppNativeSwanJsBridge()构造函数参数: " + param.args[0].getClass().getName());}@Overrideprotected void afterHookedMethod(MethodHookParam param) throws Throwable {super.afterHookedMethod(param);}});

d. XposedBridge类

  1. XposedBridge.log(String text),将消息写入Xposed错误日志。用于打印想要了解的信息

  2. XposedBridge.hookMethod(Member hookMethod, XC_MethodHook callback),用特定的回调方法hook任意的方法或构造函数;用这种方法不需要像XposedHelpers.findAndHookMethod() 构造那么多参数,使用如下,以下代码逻辑表示先从一个类中获取到对应的method实例,然后将该method对象传递给XposedBridge.hookMethod()方法,即可直接hook住该方法

            for(final Method method: TestClass.getDeclaredMethods()){XposedBridge.hookMethod(method, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {super.beforeHookedMethod(param);XposedBridge.log("Baidu:share中的" + method.getName() + "被调用了");printStack();}});}

3. 打印函数调用栈

在逆向APP的框架逻辑时,当hook住一个被成功触发的函数,往往需要查看其调用栈,也就是该函数的上层调用函数,这些信息会对我们逆向APP框架有很大的帮助。

private void printStack() {// 获取线程的StackTraceElement[]Throwable ex = new Throwable();StackTraceElement[] stackElements = ex.getStackTrace();if (stackElements != null) {for (int i = 0; i < stackElements.length; i++) {XposedBridge.log("Baidu: Dump Stack" + i + ": " + stackElements[i].getClassName()+ "----" + stackElements[i].getFileName()+ "----" + stackElements[i].getLineNumber()+ "----" + stackElements[i].getMethodName());}}XposedBridge.log("Baidu: Dump Stack: ---------------over----------------");}

4. 修改hook住函数的参数

        1. 修改基础数据类型和String类型的参数

        直接赋值即可,如下

param.args[0] = 5; // int类型
param.args[1] = "hello"; //String类型

        2.  修改基础数据类型和String类型的参数

        先获取引用,再修改;例如

Map<String, String> target = (Map<String, String>) param.args[0]; // Map
target.put("name", "tnoy"); //向Map中添加数据

        3. 修改类的实例中的成员变量

        先用Field获取到相应的成员变量,再用Field.set(类的实例,修改后的值)进行修改;例如

final Class<?> model_d = XposedHelpers.findClass("com.alipay.android.phone.globalsearch.model.d", lpparam.classLoader);
Object dVar = param.args[0];
Field b = model_d.getDeclaredField("b"); // b是model类中的public的String类型的变量
b.set(dVar, "search_auto");

        4. 修改Object[]类型的数组

        针对Object数组中的某一个元素,先使用.getClass().getName()获取元素的类型,然后去类里面看要修改的对应的Field,然后进行上述第三点的操作,最后封装成一个新的Object[],再把这个Object[]赋值给param.args[i]。例如

Object[] obj = (Object[]) param.args[2];
for(Object o: obj){
if(o != null){// 判断当前Object的类是不是我们需要的那个类if(o.getClass().getName().equals("com.alipay.mobile.aompfavorite.base.rpc.request.MiniAppHistoryRequestPB")){// 在jadx中源码为:List<MiniAppHistoryReqItemPB> miniAppItems;Field miniAppItems = MiniAppHistoryRequestPB.getDeclaredField("miniAppItems");// 先用List<Object>反射拿到List<MiniAppHistoryReqItemPB>列表List<Object> item = (List<Object>) miniAppItems.get(o);// 获取List列表的第一个值Object item_1 =  item.get(0);Log.d("Mini 修改前", o.toString());Log.d("Mini List[0]", item_1.toString());// MiniAppHistoryReqItemPB类中的成员变量appIdField appId = MiniAppHistoryReqItemPB.getDeclaredField("appId");String AppId = (String) appId.get(item_1);Log.d("Mini appid", AppId);appId.set(item_1, "2018112262208014");Log.d("Mini 修改后", o.toString());}Log.d("Mini handler_1.1", o.getClass().getName() + " " + o.toString());}
}

5. hook动态加载进来的类

        在APP框架中有些代码是动态加载进来的,比如插件化开发。使用以下代码,可以hook住动态加载进来的函数

XposedBridge.hookAllMethods(ClassLoader.class, "loadClass", new XC_MethodHook() {@Overrideprotected void afterHookedMethod(XC_MethodHook.MethodHookParam param) throws Throwable {if (param.hasThrowable()) return;if (param.args.length != 1) return;Class<?> cls = (Class<?>) param.getResult();String name = cls.getName();// 判断是否是我要hook的动态加载的类if ("com.bytedance.webview.chromium.ContentSettingsAdapter".equals(name)) {// 指定要hook的methodXposedBridge.hookAllMethods(cls,"setJavaScriptEnabled",new XC_MethodHook() {protected void beforeHookedMethod(MethodHookParam param) throws Throwable {try {XposedBridge.log("commonRe: setJavaScriptEnabled被调用了: " + param.args[0]);printStack();} catch (Exception e) {XposedBridge.log("commonRe: hook error!");}}});}}});

 6. 打印动态加载进来的类的存储位置(获取插件apk)

final Class<?> DexPathList = XposedHelpers.findClass("dalvik.system.DexPathList", lpparam.classLoader);for (final Method method: DexPathList.getDeclaredMethods()){XposedBridge.hookMethod(method, new XC_MethodHook() {@Overrideprotected void beforeHookedMethod(MethodHookParam param) throws Throwable {super.beforeHookedMethod(param);// splitPaths()方法传入的是动态加载进来的类在手机中的路径if(method.getName().equals("splitPaths")){XposedBridge.log("Baidu: DexPathList中的" + method.getName() + "被调用了,传参为" + param.args[0]+" " + param.args[1]);}}}) ;}

 7. 自动化hook方法脚本

在某些情况下,我们拥有一系列需要hook的方法的signature,而且需要hook住这些方法获取某些信息时,我们可以通过自动化脚来实现将这些方法一一hook住,就不需要手工挨个写hook每一个方法的脚本。

代码举例实现如下

StaticInfo.java:用于从json文件中读取要hook方法的signature,并通过反射获取到对应的method对象
package com.example.ttest;import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage;public class StaticInfo {public static HashMap<PoolHook.normalHandlerHook, Method> HookMethods = new HashMap<>();public XC_LoadPackage.LoadPackageParam lpparam;public StaticInfo(XC_LoadPackage.LoadPackageParam lpparam) throws NoSuchFieldException {this.lpparam = lpparam;// read from filetry{InputStream is = new FileInputStream(new File("/sdcard/tmp/static_info.json"));init(is);is.close();}catch (Exception e){XposedBridge.log("AMZ: read json error! " + e.toString());}}public void init(InputStream in) throws IOException, NoSuchFieldException {BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));StringBuilder sb = new StringBuilder();String line;String ls = System.getProperty("line.separator");while ((line = bufferedReader.readLine()) != null){sb.append(line);sb.append(ls);}String text = sb.toString();XposedBridge.log("AMZ: 读取json文件成功!");JSONArray jsonArray = JSON.parseArray(text);for (int i=0; i<jsonArray.size(); i++){JSONObject jsonObject = jsonArray.getJSONObject(i);String signature = jsonObject.getString("signature");String filedName = jsonObject.getString("field");String type = jsonObject.getString("type");String declaringClass = jsonObject.getString("declaringClass");reflectMethod(signature, filedName, type, declaringClass);}}public void init(String text) throws NoSuchFieldException {JSONArray jsonArray = JSON.parseArray(text);for (int i=0; i<jsonArray.size(); i++){JSONObject jsonObject = jsonArray.getJSONObject(i);String signature = jsonObject.getString("signature");String filedName = jsonObject.getString("field");String type = jsonObject.getString("type");String declaringClass = jsonObject.getString("declaringClass");reflectMethod(signature, filedName, type, declaringClass);}}// init HashMap for Method and Field due to json filepublic void reflectMethod(String signature, String fieldName, String type, String declaringClass) throws NoSuchFieldException {XposedBridge.log("AMZ: 正在反射获取Method:"+ signature  + " " + fieldName + " " + type);Field field = XposedHelpers.findClass(declaringClass, lpparam.classLoader).getDeclaredField(fieldName);PoolHook.normalHandlerHook hook = new PoolHook.normalHandlerHook(fieldName,type, signature, field);String className = signature.split(" ")[0].substring(1,signature.split(" ")[0].length()-1);XposedBridge.log("AMZ: parse classname: " + className);try {Class<?> clazz = XposedHelpers.findClass(className, this.lpparam.classLoader);String methodName = signature.split(" ")[2].split("\\(")[0];ArrayList<String> paramTypes = new ArrayList(Arrays.asList(signature.split(" ")[2].split("\\(")[1].substring(0,signature.split(" ")[2].split("\\(")[1].length()-2).split(",")));XposedBridge.log("AMZ: 要找的方法的参数为 " + paramTypes.toString());for (Method method: clazz.getDeclaredMethods()){XposedBridge.log("AMZ: 正在匹配方法:" + method.getName() + " ==> " + methodName);XposedBridge.log("AMZ: 当前方法参数个数:" + method.getParameterTypes().length + " 目标方法的参数个数:" + paramTypes.size());if (method.getName().equals(methodName)){if (method.getParameterTypes().length == paramTypes.size()){XposedBridge.log("AMZ: 方法名和参数个数匹配上了");ArrayList<String> paramTypesCopy = (ArrayList<String>) paramTypes.clone();for (Class paramType: method.getParameterTypes()){XposedBridge.log("AMZ: 当前方法的参数类型:" + paramType.getName());if (paramTypes.contains(paramType.getName())){paramTypesCopy.remove(paramType.getName());}}if (paramTypesCopy.size() == 0 && !HookMethods.containsKey(hook)){XposedBridge.log("AMZ: find target method: " + method.toString() + " target_field: " + field);HookMethods.put(hook, method);}}else if (method.getParameterTypes().length == 0 && paramTypes.size() ==1 && paramTypes.get(0).length() == 0){XposedBridge.log("AMZ: 目标方法没有参数,匹配成功");if (!HookMethods.containsKey(hook)){XposedBridge.log("AMZ: find target method: " + method.toString() + " target_field: " + field);HookMethods.put(hook, method);}}}}}catch (Exception e){XposedBridge.log("AMZ: " + e.toString());}}
}

PoolHook.java: 继承 IXposedHookLoadPackage 接口,编写hook逻辑

package com.example.ttest;import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;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;public class PoolHook implements IXposedHookLoadPackage{public void handleLoadPackage(XC_LoadPackage.LoadPackageParam lpparam) throws Throwable{new StaticInfo(lpparam);if (lpparam.packageName.equals("com.eg.android.AlipayGphone")){XposedBridge.log("AMZ: hook start!!");hookPackage(lpparam);}}private void hookPackage(XC_LoadPackage.LoadPackageParam lpparam){if (StaticInfo.HookMethods.isEmpty()){XposedBridge.log("AMZ: HashMap is empty");}else {XposedBridge.log("AMZ: HashMap is not empty");}for (Map.Entry<normalHandlerHook, Method> entry: StaticInfo.HookMethods.entrySet()){XposedBridge.hookMethod(entry.getValue(), entry.getKey());}}static class normalHandlerHook extends XC_MethodHook{private String fieldName;private String type;private Field field;private String signature;public normalHandlerHook(String fieldName, String type, String signature, Field field){this.fieldName = fieldName;this.type = type;this.signature = signature;this.field = field;}protected void beforeHookedMethod(MethodHookParam param) throws Throwable{System.out.println("AMZ: current method: " + param.method);XposedBridge.log("AMZ: hook field right now:" + field.toString());XposedBridge.log("AMZ: pool type:" + this.type);this.field.setAccessible(true);if (this.type.equals("HashMap")){XposedBridge.log("AMZ: this is HashMap");HashMap<Object, Object> mmap = (HashMap<Object, Object>) this.field.get(param.thisObject);for (Map.Entry<Object, Object> entry: mmap.entrySet()){Object key = entry.getKey();Object value = entry.getValue();XposedBridge.log("AMZ: signature=" + this.signature +" key=" + key + " value=" + value);}}else if(this.type.equals("Map") || this.type.equals("ConcurrentHashMap") || this.type.equals("LinkedHashMap")){XposedBridge.log("AMZ: this is Map or ConcurrentHashMap");Map<Object, Object> mmap_1 = (Map<Object, Object>) field.get(param.thisObject);for (Map.Entry<Object, Object> entry: mmap_1.entrySet()){Object key = entry.getKey();Object value = entry.getValue();XposedBridge.log("AMZ: signature=" + this.signature +" key=" + key + " value=" + value);}}}}
}

8. Xposed hook 原理

Java虚拟机JVM在加载了dex后,会将整个dex文件的内容mmap(一种内存映射文件的方法)到内存中。JVM在load一个class的时候,根据类的描述符,在内存的dex区域,查询到对应的数据,构建出ClassObject对象,以及这个ClassObject关联的Method。

Method分为directMethod和nativeMethod,分别是Java里实现的方法和C/C++里面实现的方法。Method里面有两个重要的指针:

const u2* insns;
DalvikBridgeFunc nativeFunc;

对于directMethod,insns存放了该方法在内存中的字节码指针;对于nativeMethod,会根据方法描述符,通过特定的映射关系得到一个native层的函数名(JNI method),然后去查找对应的函数,得到了函数指针后,再将这个指针赋值给insns。在nativeFunc这个桥接函数中,将insns解析为函数指针,然后进行调用。

Xposed在对java方法进行hook的时候,会先将JVM里面的这个方法的Method属性改为nativeMethod(也就是修改一个表示字段),然后将该方法的nativeFunc指向自己实现的一个native方法。于是当被hook的方法被调用到时,就会实际去调用自己实现的这个native方法。

在自己实现的native方法中,xposed直接调用了一个java方法,这个java方法里面对原方法进行了调用,并在调用前后插入了钩子,于是就hook住了这个方法。

Android所有的APP进程都是由Zygote进程启动的,所以Zygote进程中加载的代码,在后续所有fork出来的子进程中都有。Xposed替换了Zygote进程对应的可执行文件/system/bin/app_process,并用于加载xposed相关代码。

总的来说,Xposed将要hook的JAVA方法变成了native方法,在beforeMethodHook()和afterMethodHook()方法中的逻辑实现在native方法中,并将原被hook函数插在这两个函数之间正常调用,示意图如下。

 

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

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

相关文章

Xposed环境安装

一、Xposed 框架实现 Hook 的原理介绍 Zygote是Android的核心&#xff0c;每运行一个app&#xff0c;Zygote就会fork一个虚拟机实例来运行app&#xff0c; Xposed Framework深入到了Android核心机制中&#xff0c;通过改造Zygote来实现一些很牛逼的 功能。Zygote的启动配置在i…

Xposed 使用教程

Xposed作为Android开发中的神器&#xff0c;功能强大之处就不做过多介绍了&#xff0c;本文主要讲解一些常用的API&#xff0c;基本包含常用的Hook操作。 Hook静态变量 Class cla XposedHelpers.findClass(claName, loadPackageParam.classLoader); XposedHelpers.setStatic…

xposed android 4.4.2,xposed新版54

xposed新版54是一款好用的系统工具&#xff0c;软件安全&#xff0c;无需root权限&#xff0c;下载相对应功能板块即可在应用内实现应用多开、虚拟步数、以及qq&#xff0c;微信等多种功能&#xff0c;方便又实用&#xff01; 软件介绍 系统功能增强&#xff0c;如后台管制&…

Xposed安装

记录一下自己安装xposed的过程。网上很多xposed的安装教程&#xff0c;里面各种都是直接跳转到官网地址下载Xposed&#xff0c;但国内打不开&#xff0c;提示如下&#xff1a; 因此只能下载对应版本zip包进行本地安装&#xff0c;下载对应zip包放到“ /sdcard/Android/data/de…

android8 检测xposed,Xposed检测与自定义Xposed

Xposed检测与自定义Xposed 前言: Xposed检测 1、遍历App安装列表检测 2、自造异常检测堆栈信息。 3、检查关键Java方法是否变为native方法 4、反射XposedHelper类和XposedBridge类 5、检测Xposed相关文件 6、Root检测 7、安全建议 自定义Xposed 一、修改XposedBridge.jar包名 …

xposed android4.4,应用管理Xposed

应用管理Xposed是一款安卓应用管理xposed模块&#xff0c;可以帮助你更好的管理自己手机的各种应用的权限&#xff0c;应用使用需要先阅读了解一下使用的方法&#xff0c;非常强大的一款插件&#xff0c;欢迎大家前来下载。 新版特性 1. 为部分列表也添加基本筛选。 2. 在主页显…

android xposed 简书,Xposed 入坑篇

device-2018-04-12-101001.png 接下来开始敲代码了 美滋滋(皮一下很开心) 上一张整个工程的图 QQ截图20180412102021.png 以下是Test和Tutorial的代码 package com.zed.xposed.demo; import de.robv.android.xposed.IXposedHookLoadPackage; import de.robv.android.xposed.Xpo…

Xposed 入门

Xposed的原理 Android基于Linux&#xff0c;第一个启动的进程自然是init进程&#xff0c;该进程会 启动所有Android进程的父进程——Zygote(孵化)进程&#xff0c;该进程的启动配置在 /init.rc脚本中&#xff0c;而Zygote进程对应的执行文件是/system/bin/app_process&#xf…

Xposed

[Xposed framework] (概述) 记录学习文章&#xff0c;这里介绍一下Xposed framework&#xff0c;它可以让你修改ROM&#xff0c;无需修改任何APK或flashing.快速入门&#xff0c;请看Xposed上XDA 之android basic 101&#xff1a; http://www.youtube.com/watch?vuRR0Flqx9M8 …

Xposed安装与使用

xposed是什么&#xff1f; 一个很牛逼的框架&#xff0c;可以在不修改APK的情况下影响程序的运行&#xff0c;比如&#xff1a; 直接把APP的界面改成自己想要的样去掉界面里不喜欢的东西&#xff0c;自动抢红包消息防撤回步数修改等等 Xposed的工作原理 在开始修改之前&…

【Android】Xposed 框架解析

前言 Xposed这位老兄大家可能不认识&#xff0c;微信自动抢红包大家听过吧、微信记录器作弊大家听过吧、地理位置模拟大家听过吧&#xff0c;我很负责任的告诉大家&#xff0c;这些都是Xposed干的&#xff0c;对的&#xff0c;就是它&#xff0c;相信大家充着“谁抢我红包”的…

Android之Xposed框架完全使用指南

文章目录 Xposed环境搭建Xposed简介Xposed原理Xposed的安装 Xposed插件开发Xposed插件编写流程Xposed开发之Hook构造函数相关API无参构造函数的hook有参构造函数的hook实际效果 Xposed开发之修改属性相关API修改静态字段和成员字段实际效果 Xposed开发之hook一般函数相关APIhoo…

深入理解Android(三):Xposed详解

编者按&#xff1a;随着移动设备硬件能力的提升&#xff0c;Android系统开放的特质开始显现&#xff0c;各种开发的奇技淫巧、黑科技不断涌现&#xff0c;InfoQ特联合《深入理解Android》系列图书作者邓凡平&#xff0c;开设深入理解Android专栏&#xff0c;探索Android从框架到…

Xposed入门教程

2019年8月27日16时51分47秒以前一直没机会接触Android Hook方式的逆向今天有空试了下&#xff0c;以前也很少写这种东西&#xff0c;今天第一次&#xff0c;认真写下&#xff0c;记录一下?准备 准备搞太极的&#xff0c;但是Xposed都不会&#xff0c;不好搞&#xff0c;所以就…

RabbitMQ---订阅模型-Topic

订阅模型-Topic • Topic类型的Exchange与Direct相比&#xff0c;都是可以根据RoutingKey把消息路由到不同的队列。只不过Topic类型Exchange可以让队列在绑定Routing key 的时候使用通配符&#xff01; • Routingkey 一般都是有一个或多个单词组成&#xff0c;多个单词之间以…

PostgreSQL命令行工具psql常用命令

1. 概述 通常情况下操作数据库使用图形化客户端工具&#xff0c;在实际工作中&#xff0c;生产环境是不允许直接连接数据库主机&#xff0c;只能在跳板机上登录到Linux服务器才能连接数据库服务器&#xff0c;此时就需要使用到命令行工具。psql是PostgreSQL中的一个命令行交互…

pyreverse+Graphviz 快速理清整个项目中的代码结构

作用 &#xff1a; 分析代码中的调用关系&#xff0c;帮助快速理清代码。 安装方法&#xff1a;以windows为例 • 从官网下载 https://www.graphviz.org/download/ 安装• 记得将其添加到系统路径• 运行下面命令来检查安装是否完成&#xff1a; dot -V• 安装Pyreverse&…

配置web服务

Web服务器又称为WWW服务器&#xff0c;它是放置一般网站的服务器。一台Web服务器上可以建立多个网站&#xff0c;各网站的拥有者只需要把做好的网页和相关文件放置在Web服务器的网站中&#xff0c;其它用户就可以用浏览器访问网站中的网页了。 LAMP是Linux, Apache, MySQL, PH…

Web Service(Web服务)

什么是webservice&#xff1f; 一句话概括&#xff1a;WebService是一种跨编程语言和跨操作系统平台的远程调用技术。 所谓跨编程语言和跨操作平台&#xff0c;就是说服务端程序采用Java编写&#xff0c;客户端程序则可以采用其他编程语言编写&#xff0c;反之亦然&#xff01…

什么是Web 服务?

Web 服务是一种可以用来解决跨网络应用集成问题的开发模式&#xff0c;这种模式为实现“软件作为服务”提供了技术保障。而“软件作为服务”实质上是一种提供软件服务的机制&#xff0c;这种机制可以在网络上暴露可编程接口&#xff0c;并通过这些接口来共享站点开放出来的功能…