parent
60224d6613
commit
2186a78aba
@ -0,0 +1,32 @@
|
||||
cmake_minimum_required(VERSION 3.10.2)
|
||||
|
||||
|
||||
include_directories(
|
||||
src/main/jni/dobby
|
||||
)
|
||||
enable_language(C ASM)
|
||||
|
||||
|
||||
add_library(
|
||||
pmm
|
||||
SHARED
|
||||
src/main/jni/main.cpp
|
||||
)
|
||||
|
||||
include_directories(dobby)
|
||||
add_library(local_dobby STATIC IMPORTED)
|
||||
set_target_properties(local_dobby PROPERTIES IMPORTED_LOCATION ${CMAKE_CURRENT_SOURCE_DIR}/libs/${ANDROID_ABI}/libdobby.a)
|
||||
|
||||
|
||||
find_library(
|
||||
log-lib
|
||||
log
|
||||
)
|
||||
|
||||
find_library(android-lib android)
|
||||
target_link_libraries(
|
||||
pmm
|
||||
local_dobby
|
||||
${log-lib}
|
||||
${android-lib}
|
||||
)
|
Binary file not shown.
Binary file not shown.
@ -0,0 +1,152 @@
|
||||
#ifndef dobby_h
|
||||
#define dobby_h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef uintptr_t addr_t;
|
||||
typedef uint32_t addr32_t;
|
||||
typedef uint64_t addr64_t;
|
||||
|
||||
typedef void *dobby_dummy_func_t;
|
||||
typedef void *asm_func_t;
|
||||
|
||||
#if defined(__arm__)
|
||||
typedef struct {
|
||||
uint32_t dummy_0;
|
||||
uint32_t dummy_1;
|
||||
|
||||
uint32_t dummy_2;
|
||||
uint32_t sp;
|
||||
|
||||
union {
|
||||
uint32_t r[13];
|
||||
struct {
|
||||
uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10, r11, r12;
|
||||
} regs;
|
||||
} general;
|
||||
|
||||
uint32_t lr;
|
||||
} DobbyRegisterContext;
|
||||
#elif defined(__arm64__) || defined(__aarch64__)
|
||||
#define ARM64_TMP_REG_NDX_0 17
|
||||
|
||||
typedef union _FPReg {
|
||||
__int128_t q;
|
||||
struct {
|
||||
double d1;
|
||||
double d2;
|
||||
} d;
|
||||
struct {
|
||||
float f1;
|
||||
float f2;
|
||||
float f3;
|
||||
float f4;
|
||||
} f;
|
||||
} FPReg;
|
||||
|
||||
// register context
|
||||
typedef struct {
|
||||
uint64_t dmmpy_0; // dummy placeholder
|
||||
uint64_t sp;
|
||||
|
||||
uint64_t dmmpy_1; // dummy placeholder
|
||||
union {
|
||||
uint64_t x[29];
|
||||
struct {
|
||||
uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10, x11, x12, x13, x14, x15, x16, x17, x18, x19, x20, x21, x22,
|
||||
x23, x24, x25, x26, x27, x28;
|
||||
} regs;
|
||||
} general;
|
||||
|
||||
uint64_t fp;
|
||||
uint64_t lr;
|
||||
|
||||
union {
|
||||
FPReg q[32];
|
||||
struct {
|
||||
FPReg q0, q1, q2, q3, q4, q5, q6, q7;
|
||||
// [!!! READ ME !!!]
|
||||
// for Arm64, can't access q8 - q31, unless you enable full floating-point register pack
|
||||
FPReg q8, q9, q10, q11, q12, q13, q14, q15, q16, q17, q18, q19, q20, q21, q22, q23, q24, q25, q26, q27, q28, q29,
|
||||
q30, q31;
|
||||
} regs;
|
||||
} floating;
|
||||
} DobbyRegisterContext;
|
||||
#elif defined(_M_IX86) || defined(__i386__)
|
||||
typedef struct _RegisterContext {
|
||||
uint32_t dummy_0;
|
||||
uint32_t esp;
|
||||
|
||||
uint32_t dummy_1;
|
||||
uint32_t flags;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t eax, ebx, ecx, edx, ebp, esp, edi, esi;
|
||||
} regs;
|
||||
} general;
|
||||
|
||||
} DobbyRegisterContext;
|
||||
#elif defined(_M_X64) || defined(__x86_64__)
|
||||
typedef struct {
|
||||
uint64_t dummy_0;
|
||||
uint64_t rsp;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint64_t rax, rbx, rcx, rdx, rbp, rsp, rdi, rsi, r8, r9, r10, r11, r12, r13, r14, r15;
|
||||
} regs;
|
||||
} general;
|
||||
|
||||
uint64_t dummy_1;
|
||||
uint64_t flags;
|
||||
} DobbyRegisterContext;
|
||||
#endif
|
||||
|
||||
#define install_hook_name(name, fn_ret_t, fn_args_t...) \
|
||||
static fn_ret_t fake_##name(fn_args_t); \
|
||||
static fn_ret_t (*orig_##name)(fn_args_t); \
|
||||
/* __attribute__((constructor)) */ static void install_hook_##name(void *sym_addr) { \
|
||||
DobbyHook(sym_addr, (dobby_dummy_func_t)fake_##name, (dobby_dummy_func_t *)&orig_##name); \
|
||||
return; \
|
||||
} \
|
||||
fn_ret_t fake_##name(fn_args_t)
|
||||
|
||||
// memory code patch
|
||||
int DobbyCodePatch(void *address, uint8_t *buffer, uint32_t buffer_size);
|
||||
|
||||
// function inline hook
|
||||
int DobbyHook(void *address, dobby_dummy_func_t replace_func, dobby_dummy_func_t *origin_func);
|
||||
|
||||
// dynamic binary instruction instrument
|
||||
// for Arm64, can't access q8 - q31, unless enable full floating-point register pack
|
||||
typedef void (*dobby_instrument_callback_t)(void *address, DobbyRegisterContext *ctx);
|
||||
int DobbyInstrument(void *address, dobby_instrument_callback_t pre_handler);
|
||||
|
||||
// destroy and restore code patch
|
||||
int DobbyDestroy(void *address);
|
||||
|
||||
const char *DobbyGetVersion();
|
||||
|
||||
// symbol resolver
|
||||
void *DobbySymbolResolver(const char *image_name, const char *symbol_name);
|
||||
|
||||
// import table replace
|
||||
int DobbyImportTableReplace(char *image_name, char *symbol_name, dobby_dummy_func_t fake_func,
|
||||
dobby_dummy_func_t *orig_func);
|
||||
|
||||
// for arm, Arm64, try use b xxx instead of ldr absolute indirect branch
|
||||
// for x86, x64, always use absolute indirect jump
|
||||
void dobby_enable_near_branch_trampoline();
|
||||
void dobby_disable_near_branch_trampoline();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
@ -0,0 +1,83 @@
|
||||
|
||||
#include "main.h"
|
||||
#include <dobby.h>
|
||||
|
||||
char buff[30];
|
||||
char pmm_str[30];
|
||||
char target_pmm[8] = {0x00, 0xf1, 0x00, 0x00, 0x00, 0x01, 0x43, 0x00};
|
||||
|
||||
void *new_func(u_int8_t a1, u_int8_t *a2, int a3) {
|
||||
|
||||
__android_log_print(6, "AICEmu-pmmtool", "hook _Z23nfa_dm_check_set_confighPhb arg0->%x arg1->%x", a1, a2);
|
||||
|
||||
// if (a1 == 0x1d) { // hardcoded arg pattern
|
||||
// 40 0a [syscode] [IDm] 53 02 01 00 55 01 01 51 08 [PMm]
|
||||
// if (a1 == 0x1b) { // another type hardcoded arg pattern
|
||||
// 40 12 [syscode] [IDm] [PMm] 53 02 01 00 55 01 01
|
||||
|
||||
// handmade hexdump
|
||||
for (int i = 0x0; i < 0x10; ++i)
|
||||
sprintf(buff + i * 3, "%02x ", *(char *)(a2 + i));
|
||||
__android_log_print(6, "AICEmu-pmmtool", "[%x]: %s", a2, buff);
|
||||
for (int i = 0x0; i < 0x10; ++i)
|
||||
sprintf(buff + i * 3, "%02x ", *(char *)(a2 + 0x10 + i));
|
||||
__android_log_print(6, "AICEmu-pmmtool", "[%x]: %s", a2 + 0x10, buff);
|
||||
|
||||
// look for 51 08 (set pmm command) for type 0x1d
|
||||
for (int i = 0x0; i < 0x20; ++i) {
|
||||
if (*(char *)(a2 + i) == 0x51 && *(char *)(a2 + i + 1) == 0x08) {
|
||||
|
||||
for (int j = 0; j < 8; ++j)
|
||||
sprintf(pmm_str + j * 3, "%02x ", *(char *)(a2 + i + 2 + j));
|
||||
__android_log_print(6, "AICEmu-pmmtool", "[1] old PMm: %s", pmm_str);
|
||||
|
||||
// set
|
||||
for (int j = 0; j < 8; ++j)
|
||||
*(char *)(a2 + i + 2 + j) = target_pmm[j];
|
||||
|
||||
for (int j = 0; j < 8; ++j)
|
||||
sprintf(pmm_str + j * 3, "%02x ", *(char *)(a2 + i + 2 + j));
|
||||
__android_log_print(6, "AICEmu-pmmtool", "[1] new PMm: %s", pmm_str);
|
||||
}
|
||||
}
|
||||
|
||||
// look for FF FF FF FF FF FF FF FF (pmm itself)
|
||||
for (int i = 0x0; i < 0x20; ++i) {
|
||||
if (*(char *)(a2 + i) == 0xff && *(char *)(a2 + i + 1) == 0xff
|
||||
&& *(char *)(a2 + i + 2) == 0xff && *(char *)(a2 + i + 3) == 0xff
|
||||
&& *(char *)(a2 + i + 4) == 0xff && *(char *)(a2 + i + 5) == 0xff
|
||||
&& *(char *)(a2 + i + 6) == 0xff && *(char *)(a2 + i + 7) == 0xff) {
|
||||
|
||||
for (int j = 0; j < 8; ++j)
|
||||
sprintf(pmm_str + j * 3, "%02x ", *(char *)(a2 + i + j));
|
||||
__android_log_print(6, "AICEmu-pmmtool", "[2] old PMm: %s", pmm_str);
|
||||
|
||||
// set
|
||||
for (int j = 0; j < 8; ++j)
|
||||
*(char *)(a2 + i + j) = target_pmm[j];
|
||||
|
||||
for (int j = 0; j < 8; ++j)
|
||||
sprintf(pmm_str + j * 3, "%02x ", *(char *)(a2 + i + j));
|
||||
__android_log_print(6, "AICEmu-pmmtool", "[2] new PMm: %s", pmm_str);
|
||||
}
|
||||
}
|
||||
//}
|
||||
//__android_log_print(6, "pmmtool", "load old func");
|
||||
void *result = old_func(a1, a2, a3);
|
||||
//__android_log_print(6, "pmmtool", "hook result -> %x", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {
|
||||
__android_log_print(6, "AICEmu-pmmtool", "Inside JNI_OnLoad");
|
||||
JNIEnv *env = nullptr;
|
||||
if (vm->GetEnv((void **) &env, JNI_VERSION_1_6) == JNI_OK) {
|
||||
//void *func_addr = DobbySymbolResolver("libnfc-nci.so", "_Z23nfa_dm_check_set_confighPhb");
|
||||
void *func_addr = DobbySymbolResolver(NULL, "_Z23nfa_dm_check_set_confighPhb");
|
||||
__android_log_print(6, "AICEmu-pmmtool", "_Z23nfa_dm_check_set_confighPhb addr->%x", func_addr);
|
||||
DobbyHook(func_addr, (void *) new_func, (void **) &old_func);
|
||||
__android_log_print(6, "AICEmu-pmmtool", "Dobby hooked");
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
return 0;
|
||||
}
|
@ -0,0 +1,18 @@
|
||||
#ifndef MAIN_H
|
||||
#define MAIN_H
|
||||
|
||||
#include <jni.h>
|
||||
#include <android/log.h>
|
||||
#include <string.h>
|
||||
#include <malloc.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <dlfcn.h>
|
||||
#include <link.h>
|
||||
#include <inttypes.h>
|
||||
#include <unistd.h>
|
||||
|
||||
void *(*old_func)(u_int8_t, u_int8_t *, int) = nullptr;
|
||||
#endif //MAIN_H
|
||||
|
Loading…
Reference in new issue