TimeBook
  • Introduction
  • 1.前言
    • 前言
    • 鸣谢
  • 2.环境篇
    • 工具部署和使用
      • 团队协作工具
        • Confluence
      • 开发工具
        • Docker
          • 镜像导入导出
          • 安装
        • Docker Compose
      • 持续集成工具
        • Gerrit
        • Sonarqube
          • 分析参数设定
          • Prerequisite
          • 服务端设置
        • Ubuntu Ci Deploy
          • ubuntu使用docker部署jenkins+sonarqube
        • 持续集成部署
      • 文本编辑工具
        • Gitbook相关注意事项
        • Markdown快速入门
      • 版本控制
        • Git
          • 1.基础
            • Git基础(一)
            • Git基础(二)
            • Git基础(三)
            • Git基础(四)
            • Git基础(五)
          • 2.命令详解
            • 命令速查
          • 3.进阶技巧
            • git技巧
      • 自动化测试工具
        • Appium
          • capability参数配置
          • 安装
          • 简介
      • 项目管理工具
        • Jira
    • 开发环境配置
      • 通用
        • Homebrew安装与使用
        • Git服务器添加SSH Key
        • koroFileHeader使用
        • nodejs与npm的安装
        • npm更换国内源
        • pip使用相关
        • PostgreSQL安装与使用
        • proxychain安装与使用
        • shell配置环境变量
        • snapd安装与使用
        • terminal走代理
    • 快捷键速查
      • shell常用快捷键
  • 3.语言篇
    • C
      • 代码规范
      • 语言技巧
    • Cpp
      • 代码规范
      • 基础知识
        • 理解C++中的左值和右值
      • 语言技巧
        • 并发编程
          • 简单的线程池实现
    • Golang
      • 代码规范
        • 避免使用转义字符串
        • 避免参数语义不明确
        • 嵌套式结构体
        • 函数的分组与顺序
        • 函数命名
        • 声明一致性
        • 导入别名
        • 使用字段名初始化结构体
        • 本地变量声明
        • map初始化
        • nil用法
        • 包命名
        • 命名Printf样式的函数
        • 减少嵌套
        • 缩小变量作用域
        • struct引用初始化
        • 测试表声明
        • 顶层变量声明
        • 不必要的else
      • 环境配置
        • 代码检查格式化工具
          • Go Fmt
          • Goimports
          • Golint
          • Go Vet
        • go mod详解
        • golang安装
        • Golang开发环境
        • Troubleshooting
      • 语言技巧
        • 如何分包
    • Java
      • 代码规范
      • 语言技巧
        • 注解编程
        • 动态代理
    • Js
      • 语言技巧
        • Rollup
    • Kotlin
      • 基础知识
        • 写给开发者Kotlin指引(一)
        • 写给开发者Kotlin指引(二)
    • Python
      • 语言技巧
        • Best Practice Of Python S Project Structure
  • 4.规范篇
    • Git message规范
  • 5.技术篇
    • Android技术
      • Hook
        • EdXposed例子
        • Android 10 上安装Magisk和EdXposed
      • Tinker
        • 1.Tinker及其使用
      • 准备
        • ADB连接设备步骤及注意事项
        • adb连接设备
        • aosp编译
      • 基础
        • Binder接口调用的鉴权方法
        • Make 及 Android 编译系统介绍
        • 使用Content Provider为其他应用提供数据
      • 源码阅读
        • Framework源码分析 Looper Handler
        • Framework源码分析 启动流程 ServiceManager的初始化
        • Framework源码分析 启动流程 Zygote启动SystemServer
    • JS Bridge
      • JSBridge初探
    • Kernel技术
      • kallsyms子系统
    • Test技术
      • 软件测试
        • jnekin+sonar 部署 问题总结
        • 性能测试基础
        • 软件测试的背景
        • 测试基础
        • 测试人员的核心竞争力
    • 操作系统原理
      • 处理器如何实现原子操作
Powered by GitBook
On this page
  • 背景
  • 依赖
  • 例子说明
  • 目标APP
  • Hook App
  • Hook 结果

Was this helpful?

  1. 5.技术篇
  2. Android技术
  3. Hook

EdXposed例子

背景

"纸上得来终觉浅,绝知此事要躬行",尤其看代码的时候经常觉得都懂了,自己写得时候全忘了。所以最好的记忆还是自己写个例子。所以学习EdXposed的时候写了个例子把整个流程走一遍。

依赖

需要完成安装Magisk和EdXposed

例子说明

EdXposed完全Follow Xposed的API,所以整个开发流程完全一致。 从本质上来讲,EdXposed 模块也是一个 Android 程序。但与普通程序不同的是,想要让写出的Android程序成为一个Xposed 模块,要额外多完成以下四个硬性任务:

  1. 让手机上的xposed框架知道我们安装的这个程序是个xposed模块。

  2. 模块里要包含有xposed的API的jar包,以实现下一步的hook操作。

  3. 这个模块里面要有对目标程序进行hook操作的方法。

  4. 要让手机上的xposed框架知道,我们编写的xposed模块中,哪一个方法是实现hook操作的。

对应上面的四个步骤我们需要做的修改有:

  1. AndroidManifest.xml

  2. XposedBridgeApi-xx.jar 与 build.gradle

  3. 实现hook操作的具体代码

  4. xposed_Init

目标APP

首先我们实现一个目标App, App的功能很简单,只有一个button,点击button返回一个字符串

package com.wq.xposedtargetapp;

import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import java.util.concurrent.ExecutionException;

public class MainActivity extends AppCompatActivity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = (Button) findViewById(R.id.button);

        button.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Toast.makeText(MainActivity.this, getIpAddr(), Toast.LENGTH_SHORT).show();
            }
        });
    }

    public String getIpAddr() {
        return "192.168.180.123";
    }
}

Hook App

另外实现一个Hook App用于替换点击按钮后的返回值,我们按照上面说的四步一步一步修改:

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.wq.xpasedmodule">

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <!--表示当前app是一个xposedmodule-->
        <meta-data
            android:name="xposedmodule"
            android:value="true" />
        <!--当前module的描述-->
        <meta-data
            android:name="xposeddescription"
            android:value="edxposed test" />
        <!--edxposed 最低版本-->
        <meta-data
            android:name="xposedminversion"
            android:value="53" />
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

当修改完AndroidManifest.xml后, EdXposedManager就会显示当前模块

Xposed API build.gradle修改

dependencies {
    //指定Xposed API
    compileOnly 'de.robv.android.xposed:api:82'
    compileOnly 'de.robv.android.xposed:api:82:sources'

    implementation fileTree(dir: "libs", include: ["*.jar"])
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'

}

实现Hook具体实现代码

package com.wq.xpasedmodule;

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 EdXposedHookTest implements IXposedHookLoadPackage {
    @Override
    public void handleLoadPackage(XC_LoadPackage.LoadPackageParam loadPackageParam) throws Throwable {
        // 指定Hook目标app
        if (loadPackageParam.packageName.equals("com.wq.xposedtargetapp")) {
            // 指定Hook的目标类
            Class clazz = loadPackageParam.classLoader.loadClass("com.wq.xposedtargetapp.MainActivity");
            // 查找Hook的方法
            XposedHelpers.findAndHookMethod(clazz, "getIpAddr", new XC_MethodHook() {
                // 具体执行逻辑
                @Override
                protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
                    super.beforeHookedMethod(param);
                }

                @Override
                protected void afterHookedMethod(MethodHookParam param) throws Throwable {
                    // 替换getIpAddr方法的返回值
                    param.setResult("111.111.111.111");
                }
            });
        }
    }
}

xposed_init指定Hook模块

com.wq.xpasedmodule.EdXposedHookTest

Hook 结果

PreviousHookNextAndroid 10 上安装Magisk和EdXposed

Last updated 4 years ago

Was this helpful?

说明

上面的例子可以在上找到

Xposed API
Github
目标APP Hook前
EdXposed Manager
目标APP Hook后