andfix中的java hook流程

andfix中的java hook流程:

原理是通过声明java函数为native函数,然后获取java函数在dvm中对应的method结构体指针,替换其成员数据的指针来实现java hook

基本方法:

setup 
replaceMethod(src, dest);
setFieldFlag


dalvik 模式下的java hook

1、在libdvm.so动态获取dvmDecodeIndirectRef函数指针和获取dvmThreadSelf函数指针。
2、调用dest的 Method.getDeclaringClass方法获取method的类对象clazz。
3、调用dvmDecodeIndirectRef方法,获取clazz的ClassObject*

4、通关 env->FromReflectedMethod方法获取dest的Method结构体函数的指针


5、替换method结构体的成员数据
 替换method结构体中的类对象指针clazz
 替换method结构体中的accessFlags
 替换method结构体中的方法的索引methodIndex
 替换method结构体的缓存的JNI参数jniArgInfo
 替换method结构体的insSize
 替换method结构体的方法原型描述prototype
 替换method结构体的真实代码insns
 替换method结构体的真实函数或者JNI桥接函数
6、设置成员域的访问标识
完成 Dalvik 模式下的java hook


android5.0以上。
art模式下的java hook

1、art模式中,我们直接通过 env->FromReflectedMethod获取到ArtMethod函数指针。

2、然后直接替换ArtMethod结构体的成员数据指针
替换 ArtMethod的class_loader指针
替换ArtMethod的clinit_thread_id_指针
替换ArtMethod的status_指针
替换ArtMethod的declaring_class_指针
替换ArtMethod的access_flags_指针
替换ArtMethod的method_index_指针
替换ArtMethod的ptr_sized_fields_指针
3、设置成员域的访问标识

最后完成art模式下的java hook

/*
 *
 * Copyright (c) 2015, alipay.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * 	dalvik_method_replace.cpp
 *
 * @author : [email protected]
 *
 */
#include 
#include 
#include 
#include 

#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

#include "dalvik.h"
#include "common.h"

static void* dvm_dlsym(void *hand, const char *name) {
	void* ret = dlsym(hand, name);
	char msg[1024] = { 0 };
	snprintf(msg, sizeof(msg) - 1, "0x%x", ret);
	LOGD("%s = %s\n", name, msg);
	return ret;
}

extern jboolean __attribute__ ((visibility ("hidden"))) dalvik_setup(
		JNIEnv* env, int apilevel) {
	void* dvm_hand = dlopen("libdvm.so", RTLD_NOW);
	if (dvm_hand) {
		dvmDecodeIndirectRef_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ?
						"_Z20dvmDecodeIndirectRefP6ThreadP8_jobject" :
						"dvmDecodeIndirectRef");
		if (!dvmDecodeIndirectRef_fnPtr) {
			return JNI_FALSE;
		}
		dvmThreadSelf_fnPtr = dvm_dlsym(dvm_hand,
				apilevel > 10 ? "_Z13dvmThreadSelfv" : "dvmThreadSelf");
		if (!dvmThreadSelf_fnPtr) {
			return JNI_FALSE;
		}
		jclass clazz = env->FindClass("java/lang/reflect/Method");
		jClassMethod = env->GetMethodID(clazz, "getDeclaringClass",
						"()Ljava/lang/Class;");

		return JNI_TRUE;
	} else {
		return JNI_FALSE;
	}
}

extern void __attribute__ ((visibility ("hidden"))) dalvik_replaceMethod(
		JNIEnv* env, jobject src, jobject dest) {
	jobject clazz = env->CallObjectMethod(dest, jClassMethod);
	ClassObject* clz = (ClassObject*) dvmDecodeIndirectRef_fnPtr(
			dvmThreadSelf_fnPtr(), clazz);
	clz->status = CLASS_INITIALIZED;

	Method* meth = (Method*) env->FromReflectedMethod(src);
	Method* target = (Method*) env->FromReflectedMethod(dest);
	LOGD("dalvikMethod: %s", meth->name);

	meth->clazz = target->clazz;
	meth->accessFlags |= ACC_PUBLIC;
	meth->methodIndex = target->methodIndex;
	meth->jniArgInfo = target->jniArgInfo;
	meth->registersSize = target->registersSize;
	meth->outsSize = target->outsSize;
	meth->insSize = target->insSize;

	meth->prototype = target->prototype;
	meth->insns = target->insns;
	meth->nativeFunc = target->nativeFunc;
}

extern void dalvik_setFieldFlag(JNIEnv* env, jobject field) {
	Field* dalvikField = (Field*) env->FromReflectedField(field);
	dalvikField->accessFlags = dalvikField->accessFlags & (~ACC_PRIVATE)
			| ACC_PUBLIC;
	LOGD("dalvik_setFieldFlag: %d ", dalvikField->accessFlags);
}







你可能感兴趣的:(android,ndk,java)