Hook GetOatQuickMethodHeader

This commit is contained in:
kotori0 2020-12-19 21:42:14 +08:00
parent c3e46819f0
commit c22e8a60fc
8 changed files with 74 additions and 24 deletions

View File

@ -1,4 +1,4 @@
version: '0.5.1.1_{build}-{branch}'
version: '0.5.1.2_{build}-{branch}'
environment:
ANDROID_HOME: C:\android-sdk-windows

View File

@ -14,7 +14,7 @@ static def calcSha256(file) {
}
// Values set here will be overriden by AppVeyor, feel free to modify during development.
def buildVersionName = 'v0.5.1.1'
def buildVersionName = 'v0.5.1.2'
def buildVersionCode = 233
if (System.env.APPVEYOR_BUILD_VERSION != null) {

View File

@ -30,5 +30,8 @@ void *getArtMethod(JNIEnv *env, jobject jmethod);
// TODO: move to common utils instead of in YAHFA's code
void *getEntryPoint(void* method);
// get original entrypoint from target ArtMethod
void *getOriginalEntryPointFromTargetMethod(void* method);
#endif // HOOK_MAIN_H

View File

@ -17,7 +17,7 @@ static uint32_t OFFSET_access_flags_in_ArtMethod;
static uint32_t kAccCompileDontBother = 0x01000000;
static jfieldID fieldArtMethod = nullptr;
//static std::unordered_map<void*, void*> replaced_entrypoint;
static std::unordered_map<void*, void*> replaced_entrypoint;
static inline uint32_t read32(void *addr) {
return *((uint32_t *) addr);
@ -136,7 +136,7 @@ static int replaceMethod(void *fromMethod, void *toMethod, int isBackup) {
}
void* fromEntrypoint = (char *) fromMethod + OFFSET_entry_point_from_quick_compiled_code_in_ArtMethod;
//replaced_entrypoint[fromEntrypoint] = newEntrypoint;
replaced_entrypoint[fromMethod] = newEntrypoint;
LOGI("replace entry point from %p to %p",
readAddr(fromEntrypoint),
@ -248,3 +248,7 @@ extern "C" jboolean Java_lab_galaxy_yahfa_HookMain_backupAndHookNative(JNIEnv *e
return JNI_FALSE;
}
}
void *getOriginalEntryPointFromTargetMethod(void* method) {
return replaced_entrypoint[method];
}

View File

@ -131,25 +131,7 @@ void *genTrampoline(void *toMethod, void *entrypoint) {
size_t size = entrypoint == NULL ? sizeof(trampoline) : sizeof(trampolineForBackup);
// TODO: make use of thread_local to avoid frequent memory allocate
size_t oatHeaderLen;
switch (SDKVersion) {
case __ANDROID_API_O__:
case __ANDROID_API_O_MR1__:
case __ANDROID_API_P__:
oatHeaderLen = 12 + 12; // 3*u32 + QuickMethodFrameInfo(3*u32)
break;
default:
LOGW("No valid offset in SDK %d for oatHeaderLen, using Android R", SDKVersion);
case __ANDROID_API_Q__:
case __ANDROID_API_R__:
oatHeaderLen = 8; // 2*u32
break;
}
char *targetAddr = doInitHookCap(size + oatHeaderLen);
// 4 bytes for AOT header, then copy code_size_.
memcpy(targetAddr, toMethod - oatHeaderLen, oatHeaderLen);
targetAddr += oatHeaderLen;
char *targetAddr = doInitHookCap(size);
if (targetAddr == NULL) return NULL;
if (entrypoint != NULL) {

View File

@ -0,0 +1,60 @@
//
// Created by 双草酸酯 on 12/19/20.
//
#ifndef EDXPOSED_ART_METHOD_H
#define EDXPOSED_ART_METHOD_H
#include "jni/edxp_pending_hooks.h"
#include <HookMain.h>
namespace art {
class ArtMethod : public edxp::HookedObject {
private:
inline static size_t oat_header_length;
inline static int32_t oat_header_code_length_offset;
CREATE_HOOK_STUB_ENTRIES(void *, GetOatQuickMethodHeader, void *thiz, uintptr_t pc) {
LOGD("GetOatQuickMethodHeader called");
// This is a partial copy from AOSP. We only touch them if they are hooked.
if (LIKELY(edxp::isHooked(thiz))) {
LOGD("GetOatQuickMethodHeader: isHooked=true, thiz=%p", thiz);
char* thiz_ = static_cast<char *>(thiz);
char* code_length_loc = thiz_ + oat_header_code_length_offset;
uint32_t code_length = *reinterpret_cast<uint32_t *>(code_length_loc);
uintptr_t original_ep = reinterpret_cast<uintptr_t>(
getOriginalEntryPointFromTargetMethod(thiz));
if (original_ep <= pc <= original_ep + code_length) return thiz_ - oat_header_length;
// If PC is not in range, we mark it as not found.
LOGD("GetOatQuickMethodHeader: PC not found in current method.");
return nullptr;
}
return GetOatQuickMethodHeaderBackup(thiz, pc);
}
public:
// @ApiSensitive(Level.MIDDLE)
static void Setup(void *handle, HookFunType hook_func) {
LOGD("Classlinker hook setup, handle=%p", handle);
int api_level = edxp::GetAndroidApiLevel();
switch (api_level) {
case __ANDROID_API_O__:
case __ANDROID_API_O_MR1__:
case __ANDROID_API_P__:
oat_header_length = 24;
oat_header_code_length_offset = -4;
break;
default:
LOGW("No valid offset in SDK %d for oatHeaderLen, using offset from Android R", api_level);
case __ANDROID_API_Q__:
case __ANDROID_API_R__:
oat_header_length = 8;
oat_header_code_length_offset = -4;
break;
}
HOOK_FUNC(GetOatQuickMethodHeader, "_ZN3art9ArtMethod23GetOatQuickMethodHeaderEj");
}
};
}
#endif //EDXPOSED_ART_METHOD_H

View File

@ -71,7 +71,6 @@ namespace art {
// @ApiSensitive(Level.MIDDLE)
static void Setup(void *handle, HookFunType hook_func) {
LOGD("Classlinker hook setup, handle=%p", handle);
// TODO: Maybe not compatible with Android 10-
int api_level = edxp::GetAndroidApiLevel();
size_t OFFSET_classlinker; // Get offset from art::Runtime::RunRootClinits() call in IDA
switch (api_level) {

View File

@ -13,6 +13,7 @@
#include "native_hook.h"
#include "riru_hook.h"
#include "art/runtime/mirror/class.h"
#include "art/runtime/art_method.h"
#include "art/runtime/class_linker.h"
#include "art/runtime/gc/heap.h"
#include "art/runtime/hidden_api.h"
@ -75,6 +76,7 @@ namespace edxp {
art::hidden_api::DisableHiddenApi(art_handle, hook_func);
art::Runtime::Setup(art_handle, hook_func);
art::gc::Heap::Setup(art_handle, hook_func);
art::ArtMethod::Setup(art_handle, hook_func);
art::ClassLinker::Setup(art_handle, hook_func);
art::mirror::Class::Setup(art_handle, hook_func);
art::JNIEnvExt::Setup(art_handle, hook_func);