将hook单独作为库引入

This commit is contained in:
董宏宇
2020-12-31 16:43:05 +08:00
parent 789d983021
commit d582bc3c41
9 changed files with 10 additions and 339 deletions

1
.idea/gradle.xml generated
View File

@@ -85,7 +85,6 @@
</set>
</option>
<option name="resolveModulePerSourceSet" value="false" />
<option name="useQualifiedModuleNames" value="true" />
</GradleProjectSettings>
</option>
</component>

View File

@@ -99,8 +99,14 @@ class CustomMapApiBuilder implements IMogoMapApiBuilder {
.setZoom( 16 )
.setPointToCenter( 0.734375f, 0.5f )
.setStyleMode( MapParams.MAP_STYLE_NIGHT ), NavParams.Companion.init() );
MapAutoView mapAutoView = new MapAutoView( context );
IMogoMapView mapView = new AMapViewWrapper( mapAutoView );
MapAutoView mapAutoView = new MapAutoView(context);
Logger.w(TAG, "mapAutoView==" + mapAutoView);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
IMogoMapView mapView = new AMapViewWrapper(mapAutoView);
return mapView;
}

View File

@@ -1,33 +0,0 @@
# 更多关于在Android Studio中使用CMake的信息请阅读文档
# https://d.android.com/studio/projects/add-native-code.html
# 设置构建本机库所需的CMake的最小版本。
cmake_minimum_required(VERSION 3.4.1)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -frtti -fexceptions")
# 指定的源文件生成链接文件,然后添加到工程中去
add_library(
# 设置库的名称。对应 System.loadLibrary("native-lib"); 使用的名称
method-hook-lib
# 将库设置为共享库。
SHARED
# 提供了到源文件的相对路径。
src/main/cpp/method-hook-lib.cpp)
# 搜索指定的预构建库并将路径存储为变量。
# 因为CMake在搜索路径中默认包含系统库
# 所以你只需要指定你想要添加的公共NDK库的名称
# CMake在完成它的构建之前会验证这个库是否存在。
find_library(
# 设置path变量的名称。
log-lib
# 指定你想要CMake定位的NDK库的名称。
log)
# 为native-lib添加ffmpeg编译连接库
target_link_libraries(
# 指定目标库。
method-hook-lib
# 将目标库链接到包含在NDK中的日志库。
${log-lib})

View File

@@ -11,17 +11,6 @@ android {
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles 'consumer-rules.pro'
externalNativeBuild {
cmake {
cppFlags ""
}
}
}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
buildTypes {
release {
@@ -44,6 +33,7 @@ dependencies {
implementation rootProject.ext.dependencies.androidxconstraintlayout
implementation rootProject.ext.dependencies.arouter
implementation rootProject.ext.dependencies.callchatprovider
api "com.mogo.libs:hook:1.0"
if (Boolean.valueOf(RELEASE)) {
api rootProject.ext.dependencies.mogomap
api rootProject.ext.dependencies.mogomapapi

View File

@@ -1,16 +0,0 @@
//
// Created by on 2020-05-08.
//
#ifndef API_H
#define API_H
#include <android/log.h>
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,"Native_RtmpPusher",__VA_ARGS__)
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,"Native_RtmpPusher",__VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,"Native_RtmpPusher",__VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,"Native_RtmpPusher",__VA_ARGS__)
#endif //API_H

View File

@@ -1,108 +0,0 @@
#include <jni.h>
#include <string.h>
#include "Api.h"
// Created by donghongyu on 12/10/20 1:34 PM.
// 源码地址 https://github.com/pqpo/methodhook
// 方法hook jni类
static const char *kClassMethodHookChar = "com/mogo/module/common/hook/MethodHook";
static struct {
jmethodID m1;
jmethodID m2;
size_t methodSize;
} methodHookClassInfo;
/**
* 替换指定类中的方法
* @param env
* @param type
* @param srcMethodObj 目标方法对象
* @param destMethodObj 替换的方法对象
* @return
*/
static jlong methodHook(JNIEnv *env,
jclass type,
jobject srcMethodObj,
jobject destMethodObj) {
// 反射获取了Java对象的在native层的 ArtMethod指针
void *srcMethod = reinterpret_cast<void *>(env->FromReflectedMethod(srcMethodObj));
void *destMethod = reinterpret_cast<void *>(env->FromReflectedMethod(destMethodObj));
// 定义存储方法ID的数组
int *backupMethod = new int[methodHookClassInfo.methodSize];
// 使用的内存拷贝函数
// 将旧方法ID拷贝到数组中
memcpy(backupMethod, srcMethod, methodHookClassInfo.methodSize);
// 将新方法替换到旧方法地址上
memcpy(srcMethod, destMethod, methodHookClassInfo.methodSize);
// 将旧方法ID返回给java层用来做方法还原使用
return reinterpret_cast<long>(backupMethod);
}
/**
* 恢复指定类中的方法
* @param env
* @param type
* @param srcMethod 目标方法对象
* @param methodPtr
* @return
*/
static jobject methodRestore(JNIEnv *env,
jclass type,
jobject srcMethod,
jlong methodPtr) {
// 要还原的旧方法 指针
int *backupMethod = reinterpret_cast<int *>(methodPtr);
// 获取了Java对象的在native层的 ArtMethod指针
void *artMethodSrc = reinterpret_cast<void *>(env->FromReflectedMethod(srcMethod));
// 将旧方法指针,替换到 artMethodSrc 中
memcpy(artMethodSrc, backupMethod, methodHookClassInfo.methodSize);
// 删除旧方法备份指针
delete[]backupMethod;
// 返回旧方法
return srcMethod;
}
// 定义要注册的方法
static JNINativeMethod gMethods[] = {
{
"hook_native",
"(Ljava/lang/reflect/Method;Ljava/lang/reflect/Method;)J",
(void *) methodHook
},
{
"restore_native",
"(Ljava/lang/reflect/Method;J)Ljava/lang/reflect/Method;",
(void *) methodRestore
}
};
extern "C"
JNIEXPORT jint JNICALL
/**
* 在jni加载的时候进行方法参数获取
* @param vm
* @param reserved
* @return
*/
JNI_OnLoad(JavaVM *vm, void *reserved) {
JNIEnv *env = nullptr;
if (vm->GetEnv((void **) &env, JNI_VERSION_1_4) != JNI_OK) {
return JNI_FALSE;
}
// 加载指定java class
jclass classEvaluateUtil = env->FindClass(kClassMethodHookChar);
// 注册
if (env->RegisterNatives(classEvaluateUtil, gMethods, sizeof(gMethods) / sizeof(gMethods[0])) <
0) {
return JNI_FALSE;
}
// 获取 MethodHook m1、m2 的方法ID
methodHookClassInfo.m1 = env->GetStaticMethodID(classEvaluateUtil, "m1", "()V");
methodHookClassInfo.m2 = env->GetStaticMethodID(classEvaluateUtil, "m2", "()V");
// 获取artMethod的大小
methodHookClassInfo.methodSize = reinterpret_cast<size_t>(methodHookClassInfo.m2) -
reinterpret_cast<size_t>(methodHookClassInfo.m1);
return JNI_VERSION_1_4;
}

View File

@@ -1,67 +0,0 @@
package com.mogo.module.common.hook;
import android.util.Pair;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
/**
* 替换管理
* Created by donghongyu on 12/29/20 1:34 PM
*/
public final class HookManager {
private HookManager() {
}
public static HookManager get() {
return InstanceHolder.sInstance;
}
private static class InstanceHolder {
private static HookManager sInstance = new HookManager();
}
private Map<Pair<String, String>, MethodHook> methodHookMap = new ConcurrentHashMap<>();
/**
* 替换方法
*
* @param originMethod 原始方法
* @param hookMethod 替换方法
*/
public void hookMethod(Method originMethod, Method hookMethod) {
if (originMethod == null || hookMethod == null) {
throw new IllegalArgumentException("argument cannot be null");
}
Pair<String, String> key = Pair.create(hookMethod.getDeclaringClass().getName(), hookMethod.getName());
if (methodHookMap.containsKey(key)) {
MethodHook methodHook = methodHookMap.get(key);
methodHook.restore();
}
MethodHook methodHook = new MethodHook(originMethod, hookMethod);
methodHookMap.put(key, methodHook);
methodHook.hook();
}
public void callOrigin(Object receiver, Object... args) {
StackTraceElement stackTrace = Thread.currentThread().getStackTrace()[3];
String className = stackTrace.getClassName();
String methodName = stackTrace.getMethodName();
MethodHook methodHook = methodHookMap.get(Pair.create(className, methodName));
if (methodHook != null) {
try {
methodHook.callOrigin(receiver, args);
} catch (InvocationTargetException e) {
e.printStackTrace();
} catch (IllegalAccessException e) {
e.printStackTrace();
}
}
}
}

View File

@@ -1,100 +0,0 @@
package com.mogo.module.common.hook;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* 替换类与c++代码对应
* Created by donghongyu on 12/29/20 1:34 PM
*/
public class MethodHook {
public static void m1() {
}
public static void m2() {
}
// 目标方法
private Method srcMethod;
// 要替换的方法
private Method hookMethod;
// 备份目标替换方法ID
private long backupMethodPtr;
/**
* hook方法
*
* @param src 要替换的方法对象
* @param dest 被替换的方法对象
*/
public MethodHook(Method src, Method dest) {
srcMethod = src;
hookMethod = dest;
srcMethod.setAccessible(true);
hookMethod.setAccessible(true);
}
/**
* 调用 native 层,完成替换
*/
public void hook() {
if (backupMethodPtr == 0) {
backupMethodPtr = hook_native(srcMethod, hookMethod);
}
}
/**
* 调用 native 层,完成方法还原
*/
public void restore() {
if (backupMethodPtr != 0) {
restore_native(srcMethod, backupMethodPtr);
backupMethodPtr = 0;
}
}
/**
* 调用原来class 对象中的方法
*
* @param receiver 接受对象
* @param args 方法列表
* @throws InvocationTargetException
* @throws IllegalAccessException
*/
public void callOrigin(Object receiver, Object... args)
throws InvocationTargetException, IllegalAccessException {
if (backupMethodPtr != 0) {
restore();
srcMethod.invoke(receiver, args);
hook();
} else {
srcMethod.invoke(receiver, args);
}
}
/**
* 调用 native 方法完成 方法替换
*
* @param src 旧方法
* @param dest 新方法
* @return 就方法ID
*/
private static native long hook_native(Method src, Method dest);
/**
* 调用 native 方法完成 方法还原
*
* @param src
* @param methodPtr
* @return
*/
private static native Method restore_native(Method src, long methodPtr);
static {
// 加载本地方法 so
System.loadLibrary("method-hook-lib");
}
}

View File

@@ -14,8 +14,8 @@ import androidx.fragment.app.Fragment;
import com.alibaba.android.arouter.facade.annotation.Route;
import com.amap.api.col.n3.lg;
import com.amap.api.col.n3.lg2;
import com.mogo.hook.HookManager;
import com.mogo.module.common.MogoApisHandler;
import com.mogo.module.common.hook.HookManager;
import com.mogo.module.common.wm.WindowManagerView;
import com.mogo.service.MogoServicePaths;
import com.mogo.service.map.IMogoSmallMapProvider;