Удаление лишних комментариев /* loaded from: classes.dex */
This commit is contained in:
@@ -9,4 +9,4 @@ add_library(${CMAKE_PROJECT_NAME} SHARED
|
||||
|
||||
target_link_libraries(${CMAKE_PROJECT_NAME}
|
||||
android
|
||||
log)
|
||||
log)
|
||||
|
||||
@@ -2,32 +2,82 @@
|
||||
#include <cstdio>
|
||||
#include <android/log.h>
|
||||
#include <jni.h>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include "main.h"
|
||||
#include "util/util.h"
|
||||
#include <link.h>
|
||||
#include <unistd.h>
|
||||
#include <unwind.h>
|
||||
#include <dlfcn.h>
|
||||
#include <execinfo.h>
|
||||
#include <link.h>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <iomanip>
|
||||
#include "util/armhook.h"
|
||||
#include "util/armhooks.h"
|
||||
|
||||
// Callback для dl_iterate_phdr
|
||||
static int find_libapp_callback(struct dl_phdr_info *info, size_t size, void *data) {
|
||||
void* libapp_base = NULL;
|
||||
|
||||
static int find_lib_callback(struct dl_phdr_info* info, size_t size, void* data) {
|
||||
if (strstr(info->dlpi_name, "libapp.so")) {
|
||||
libapp = (void *) info->dlpi_addr;
|
||||
libapp_base = (void*)info->dlpi_addr;
|
||||
LOGD("Found libapp.so at base: 0x%08X", (uintptr_t)libapp_base);
|
||||
return 1; // Останавливаем перебор
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
// Ищем libapp.so
|
||||
dl_iterate_phdr(find_libapp_callback, NULL);
|
||||
bool get_libapp_base() {
|
||||
dl_iterate_phdr(find_lib_callback, NULL);
|
||||
if (!libapp_base) {
|
||||
Log("libapp.so not found in memory!");
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
int (*sub_4087CC)() = nullptr;
|
||||
int HOOK_sub_4087CC() {
|
||||
Log("Its hooked sub_4087CC()!");
|
||||
return sub_4087CC();
|
||||
}
|
||||
|
||||
if (libapp) {
|
||||
__android_log_print(ANDROID_LOG_INFO, "MyLib", "libapp.so base: %p", libapp);
|
||||
} else {
|
||||
__android_log_print(ANDROID_LOG_ERROR, "MyLib", "libapp.so not found!");
|
||||
return JNI_ERR;
|
||||
uintptr_t get_library_base(const char* lib_name) {
|
||||
FILE* maps = fopen("/proc/self/maps", "r");
|
||||
if (!maps) return 0;
|
||||
|
||||
char line[512];
|
||||
uintptr_t base = 0;
|
||||
|
||||
while (fgets(line, sizeof(line), maps)) {
|
||||
if (strstr(line, lib_name)) {
|
||||
base = (uintptr_t)strtoul(strtok(line, "-"), NULL, 16);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
fclose(maps);
|
||||
return base;
|
||||
}
|
||||
|
||||
bool is_address_executable(void* addr) {
|
||||
uintptr_t page = (uintptr_t)addr & ~(getpagesize() - 1);
|
||||
return msync((void*)page, getpagesize(), MS_ASYNC) == 0;
|
||||
}
|
||||
|
||||
bool is_memory_writable(void* addr, size_t size) {
|
||||
uintptr_t page_start = (uintptr_t)addr & ~(getpagesize() - 1);
|
||||
return mprotect((void*)page_start, size, PROT_READ | PROT_WRITE | PROT_EXEC) == 0;
|
||||
}
|
||||
|
||||
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved) {
|
||||
|
||||
get_libapp_base();
|
||||
|
||||
|
||||
return JNI_VERSION_1_6;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_nfs_mod_mpcore_MultiplayerCore_bumpBackTraceToLogcat(JNIEnv *env, jobject thiz) {
|
||||
//backtraceToLogcat();
|
||||
}
|
||||
@@ -1,198 +1,99 @@
|
||||
#include <unistd.h> // system api
|
||||
#include <assert.h> // assert()
|
||||
#include <dlfcn.h> // dlopen
|
||||
#include <cerrno>
|
||||
#include <sys/mman.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <cstring>
|
||||
#include <exception>
|
||||
#include <cstdint>
|
||||
#include "armhook.h"
|
||||
#include "util.h"
|
||||
#include "../main.h"
|
||||
|
||||
uintptr_t mmap_start = 0;
|
||||
uintptr_t mmap_end = 0;
|
||||
uintptr_t memlib_start = 0;
|
||||
uintptr_t memlib_end = 0;
|
||||
// Получаем реальный размер страницы
|
||||
#define PAGE_SIZE sysconf(_SC_PAGESIZE)
|
||||
|
||||
//#define PAGE_SIZE 0x8124
|
||||
MemoryRegion hook_region;
|
||||
MemoryRegion mmap_region;
|
||||
|
||||
#define HOOK_PROC "\x01\xB4\x01\xB4\x01\x48\x01\x90\x01\xBD\x00\xBF\x00\x00\x00\x00"
|
||||
// Универсальная функция изменения защиты памяти
|
||||
bool setMemoryProtection(uintptr_t address, size_t size, int prot) {
|
||||
uintptr_t page_start = address & ~(PAGE_SIZE - 1);
|
||||
size_t protect_size = (address - page_start) + size;
|
||||
|
||||
if (mprotect(reinterpret_cast<void*>(page_start),
|
||||
(protect_size + PAGE_SIZE - 1) & ~(PAGE_SIZE - 1),
|
||||
prot) == -1) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void unProtect(uintptr_t ptr, size_t dwSize)
|
||||
{
|
||||
if(mprotect(reinterpret_cast<void*>(ptr & 0xFFFFF000), PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC) == -1)
|
||||
{
|
||||
const auto err = errno;
|
||||
// Проверка режима (Thumb/ARM)
|
||||
bool isThumbMode(uintptr_t address) {
|
||||
return (address & 1);
|
||||
}
|
||||
|
||||
if(err == EACCES)
|
||||
{
|
||||
mprotect(reinterpret_cast<void*>(ptr & 0xFFFFF000), PAGE_SIZE, PROT_WRITE | PROT_READ);
|
||||
return;
|
||||
uintptr_t makeThumbPtr(uintptr_t address) {
|
||||
return address | 1;
|
||||
}
|
||||
|
||||
// Создание Thumb-перехода (4-байтовая версия)
|
||||
void makeThumbJump(uintptr_t from, uintptr_t to) {
|
||||
// Корректируем адрес для Thumb-режима
|
||||
from &= ~1;
|
||||
to &= ~1;
|
||||
|
||||
uint32_t offset = (to - from - 4) >> 1;
|
||||
|
||||
// Формируем инструкцию B.W
|
||||
uint32_t instr = 0xF000 | ((offset >> 11) & 0x7FF);
|
||||
instr |= 0xB800 | ((offset & 0x7FF) << 16);
|
||||
|
||||
setMemoryProtection(from, 4, PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
*reinterpret_cast<uint32_t*>(from) = instr;
|
||||
__builtin___clear_cache(reinterpret_cast<char*>(from),
|
||||
reinterpret_cast<char*>(from + 4));
|
||||
}
|
||||
|
||||
// Универсальная установка хука
|
||||
bool installHook(uintptr_t target, uintptr_t hook, uintptr_t* original) {
|
||||
// Проверяем режим
|
||||
bool thumb_mode = isThumbMode(target);
|
||||
target &= ~1;
|
||||
hook &= ~1;
|
||||
|
||||
// Выделяем память для оригинальной функции если нужно
|
||||
if (original) {
|
||||
if (mmap_region.start == 0) {
|
||||
mmap_region.start = reinterpret_cast<uintptr_t>(
|
||||
mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0));
|
||||
mmap_region.end = mmap_region.start + PAGE_SIZE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (mmap_region.end - mmap_region.start < 32) {
|
||||
return false; // Недостаточно памяти
|
||||
}
|
||||
|
||||
void makeNOP(uintptr_t addr, unsigned int count)
|
||||
{
|
||||
Log("Hello from makeNOP!");
|
||||
unProtect(addr);
|
||||
// Копируем оригинальные инструкции
|
||||
*original = mmap_region.start + 1; // +1 для Thumb-режима
|
||||
memcpy(reinterpret_cast<void*>(mmap_region.start),
|
||||
reinterpret_cast<void*>(target), 4);
|
||||
|
||||
for(uintptr_t ptr = addr; ptr != (addr+(count * 2)); ptr += 2)
|
||||
{
|
||||
Log("Hello from loop makeNOP!");
|
||||
*(char*)ptr = 0x00;
|
||||
*(char*)(ptr+1) = 0x46;
|
||||
// Добавляем переход обратно
|
||||
makeThumbJump(mmap_region.start + 4, target + 4);
|
||||
mmap_region.start += 32;
|
||||
}
|
||||
|
||||
//cacheflush(addr, (uintptr_t)(addr + count * 2), 0);
|
||||
// Устанавливаем переход к хуку
|
||||
makeThumbJump(target, hook);
|
||||
return true;
|
||||
}
|
||||
|
||||
void WriteMemory(uintptr_t dest, uintptr_t src, size_t size)
|
||||
{
|
||||
unProtect(dest);
|
||||
memcpy((void*)dest, (void*)src, size);
|
||||
//cacheflush(dest, dest+size, 0);
|
||||
}
|
||||
void WriteMemory(uintptr_t dest, void* src, size_t size)
|
||||
{
|
||||
unProtect(dest);
|
||||
memcpy((void*)dest, src, size);
|
||||
//cacheflush(dest, dest+size, 0);
|
||||
}
|
||||
void SetPointer(uintptr_t addr, void* value)
|
||||
{
|
||||
WriteMemory(addr, &value, sizeof(value));
|
||||
}
|
||||
void ReadMemory(uintptr_t dest, uintptr_t src, size_t size)
|
||||
{
|
||||
unProtect(src);
|
||||
memcpy((void*)dest, (void*)src, size);
|
||||
}
|
||||
// Инициализация системы хуков
|
||||
void initHookSystem() {
|
||||
// Можно добавить автоматическое выделение регионов памяти
|
||||
mmap_region = MemoryRegion(reinterpret_cast<uintptr_t>(
|
||||
mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)), PAGE_SIZE);
|
||||
|
||||
|
||||
void InitHookStuff()
|
||||
{
|
||||
memlib_start = APP_ADDR(0x000A1B44);
|
||||
memlib_end = memlib_start + 0x1A36;
|
||||
|
||||
mmap_start = (uintptr_t)mmap(0, PAGE_SIZE, PROT_WRITE | PROT_READ | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
|
||||
int code = mprotect((void*)(mmap_start & 0xFFFFF000), PAGE_SIZE, PROT_READ | PROT_EXEC | PROT_WRITE);
|
||||
mmap_end = (mmap_start + PAGE_SIZE);
|
||||
|
||||
/*const auto err = errno;
|
||||
|
||||
Log("Status is %d && %d", err, code);
|
||||
|
||||
Log("mmap_stat = 0x%08x", mmap_start);
|
||||
Log("mmap_end = 0x%08x", mmap_end);
|
||||
|
||||
Log("memlib_start = 0x%08x", memlib_start);
|
||||
Log("memlib_end = 0x%08x", memlib_end);*/
|
||||
|
||||
//unProtect(APP_ADDR(0x1800AC));
|
||||
|
||||
}
|
||||
|
||||
void makeJMP(uintptr_t func, uintptr_t addr)
|
||||
{
|
||||
uint32_t code = ((addr - func - 4) >> 12) & 0x7FF | 0xF000 | ((((addr - func - 4) >> 1) & 0x7FF | 0xB800) << 16);
|
||||
WriteMemory(func, (uintptr_t)&code, 4);
|
||||
}
|
||||
|
||||
void makeBLX(uintptr_t func, uintptr_t addr)
|
||||
{
|
||||
uint32_t code = ((addr - func - 4) >> 12) & 0x7FF | ((addr - func - 4) << 15) | 0xF800F000;
|
||||
WriteMemory(func, (uintptr_t)&code, 4);
|
||||
}
|
||||
|
||||
void WriteHookProc(uintptr_t addr, uintptr_t func)
|
||||
{
|
||||
char code[16];
|
||||
|
||||
memcpy(code, HOOK_PROC, 16);
|
||||
*(uint32_t*)&code[12] = (func | 1);
|
||||
|
||||
WriteMemory(addr, (uintptr_t)code, 16);
|
||||
}
|
||||
|
||||
void InstallBLXHook(uintptr_t addr, uintptr_t func)
|
||||
{
|
||||
// memlib_start = 0
|
||||
// memlib_end = 10
|
||||
|
||||
if(memlib_end < (memlib_start + 0x10) || mmap_end < (mmap_start + 0x20))
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
makeBLX(addr, func);
|
||||
WriteHookProc(addr, func);
|
||||
|
||||
memlib_start += 16;
|
||||
}
|
||||
|
||||
void InstallJMPHook(uintptr_t addr, uintptr_t func)
|
||||
{
|
||||
|
||||
if(memlib_end < (memlib_start + 0x10) || mmap_end < (mmap_start + 0x20))
|
||||
{
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
makeJMP(addr, func);
|
||||
WriteHookProc(addr, func);
|
||||
|
||||
memlib_start += 16;
|
||||
}
|
||||
|
||||
void InstallHook(uintptr_t addr, uintptr_t func, uintptr_t *orig)
|
||||
{
|
||||
|
||||
if(memlib_end < (memlib_start + 0x10) || mmap_end < (mmap_start + 0x20))
|
||||
{
|
||||
Log("FAILED!");
|
||||
std::terminate();
|
||||
}
|
||||
|
||||
ReadMemory(mmap_start, addr, 4);
|
||||
WriteHookProc(mmap_start+4, addr+4);
|
||||
*orig = mmap_start+1;
|
||||
mmap_start += 32;
|
||||
|
||||
makeJMP(addr, memlib_start);
|
||||
WriteHookProc(memlib_start, func);
|
||||
memlib_start += 16;
|
||||
}
|
||||
|
||||
void RedirectCall(uintptr_t addr, uintptr_t func)
|
||||
{
|
||||
makeJMP(addr, memlib_start);
|
||||
WriteHookProc(memlib_start, func);
|
||||
memlib_start += 16;
|
||||
}
|
||||
|
||||
void InstallMethodHook(uintptr_t addr, uintptr_t func)
|
||||
{
|
||||
unProtect(addr);
|
||||
*(uintptr_t*)addr = func;
|
||||
}
|
||||
|
||||
void CodeInject(uintptr_t addr, uintptr_t func, int reg)
|
||||
{
|
||||
|
||||
char injectCode[12];
|
||||
|
||||
injectCode[0] = 0x01;
|
||||
injectCode[1] = 0xA0 + reg;
|
||||
injectCode[2] = (0x08 * reg) + reg;
|
||||
injectCode[3] = 0x68;
|
||||
injectCode[4] = 0x87 + (0x08 * reg);
|
||||
injectCode[5] = 0x46;
|
||||
injectCode[6] = injectCode[4];
|
||||
injectCode[7] = injectCode[5];
|
||||
|
||||
*(uintptr_t*)&injectCode[8] = func;
|
||||
|
||||
WriteMemory(addr, (uintptr_t)injectCode, 12);
|
||||
hook_region = MemoryRegion(reinterpret_cast<uintptr_t>(
|
||||
mmap(nullptr, PAGE_SIZE, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)), PAGE_SIZE);
|
||||
}
|
||||
@@ -2,34 +2,24 @@
|
||||
|
||||
#include <sys/mman.h>
|
||||
|
||||
// Структура для управления памятью
|
||||
extern struct MemoryRegion {
|
||||
uintptr_t start;
|
||||
uintptr_t end;
|
||||
size_t size;
|
||||
|
||||
MemoryRegion() : start(0), end(0), size(0) {}
|
||||
MemoryRegion(uintptr_t s, size_t sz) : start(s), end(s + sz), size(sz) {}
|
||||
} mmap_region, hook_region;
|
||||
|
||||
extern uintptr_t mmap_start;
|
||||
extern uintptr_t mmap_end;
|
||||
extern uintptr_t memlib_start;
|
||||
extern uintptr_t memlib_end;
|
||||
|
||||
void unProtect(uintptr_t ptr, size_t dwSize = 100);
|
||||
|
||||
void WriteMemory(uintptr_t dest, uintptr_t src, size_t size);
|
||||
void ReadMemory(uintptr_t dest, uintptr_t src, size_t size);
|
||||
|
||||
void makeNOP(uintptr_t addr, unsigned int count);
|
||||
void makeJMP(uintptr_t func, uintptr_t addr);
|
||||
void makeBLX(uintptr_t func, uintptr_t addr);
|
||||
|
||||
void InitHookStuff();
|
||||
|
||||
void InstallHook(uintptr_t addr, uintptr_t func, uintptr_t *orig);
|
||||
void InstallMethodHook(uintptr_t addr, uintptr_t func);
|
||||
void InstallJMPHook(uintptr_t addr, uintptr_t func);
|
||||
void InstallBLXHook(uintptr_t addr, uintptr_t func);
|
||||
|
||||
void CodeInject(uintptr_t addr, uintptr_t func, int reg);
|
||||
|
||||
void WriteMemory(uintptr_t dest, void* src, size_t size);
|
||||
void SetPointer(uintptr_t addr, void* value);
|
||||
|
||||
template <typename Ret, typename... Args>
|
||||
static Ret CallFunction(unsigned int address, Args... args)
|
||||
{
|
||||
return reinterpret_cast<Ret(__cdecl *)(Args...)>(address)(args...);
|
||||
}
|
||||
bool setMemoryProtection(uintptr_t address, size_t size, int prot);
|
||||
bool isThumbMode(uintptr_t address);
|
||||
uintptr_t makeThumbPtr(uintptr_t address);
|
||||
void makeThumbJump(uintptr_t from, uintptr_t to);
|
||||
bool installHook(uintptr_t target, uintptr_t hook, uintptr_t* original);
|
||||
void initHookSystem();
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
//
|
||||
// Created by megboyzz on 12.04.2025.
|
||||
//
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/mman.h>
|
||||
#include <android/log.h>
|
||||
|
||||
#define LOG_TAG "HOOK"
|
||||
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
|
||||
|
||||
// Структура для ARM инструкций
|
||||
#pragma pack(push, 1)
|
||||
typedef struct {
|
||||
uint16_t movw; // MOVW R12, #low16(address)
|
||||
uint16_t imm16_low;
|
||||
uint16_t movt; // MOVT R12, #high16(address)
|
||||
uint16_t imm16_high;
|
||||
uint16_t bx_r12; // BX R12
|
||||
} ARM_HOOK;
|
||||
#pragma pack(pop)
|
||||
|
||||
// Прототип оригинальной функции
|
||||
typedef int (*original_function_t)(int param1, const char* param2);
|
||||
|
||||
// Указатель на оригинальную функцию
|
||||
original_function_t original_function = NULL;
|
||||
|
||||
// Наша функция-заменитель
|
||||
int my_function(int param1, const char* param2) {
|
||||
LOGD("Function hooked! Params: %d, %s", param1, param2);
|
||||
|
||||
// Вызываем оригинальную функцию
|
||||
int result = original_function(param1, param2);
|
||||
|
||||
LOGD("Original function returned: %d", result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Функция для установки хука
|
||||
void install_hook(void* target_func, void* hook_func, void** original_func) {
|
||||
// Вычисляем страницу памяти
|
||||
uintptr_t page_start = (uintptr_t)target_func & ~(getpagesize() - 1);
|
||||
|
||||
// Делаем память доступной для записи
|
||||
mprotect((void*)page_start, getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC);
|
||||
|
||||
// Сохраняем оригинальные байты
|
||||
ARM_HOOK original_bytes;
|
||||
memcpy(&original_bytes, target_func, sizeof(ARM_HOOK));
|
||||
|
||||
// Создаем прыжок к нашей функции
|
||||
ARM_HOOK hook;
|
||||
hook.movw = 0x0C00 | (((uintptr_t)hook_func >> 0) & 0xFFFF);
|
||||
hook.movt = 0x0C00 | (((uintptr_t)hook_func >> 16) & 0xFFFF);
|
||||
hook.bx_r12 = 0x46E0;
|
||||
|
||||
// Записываем хук
|
||||
memcpy(target_func, &hook, sizeof(ARM_HOOK));
|
||||
|
||||
// Восстанавливаем защиту памяти
|
||||
mprotect((void*)page_start, getpagesize(), PROT_READ | PROT_EXEC);
|
||||
|
||||
// Сохраняем оригинальную функцию с прыжком назад
|
||||
*original_func = malloc(sizeof(ARM_HOOK) + 4);
|
||||
memcpy(*original_func, &original_bytes, sizeof(ARM_HOOK));
|
||||
|
||||
// Добавляем прыжок обратно после оригинальных инструкций
|
||||
uint32_t* jump_back = (uint32_t*)((uintptr_t)*original_func + sizeof(ARM_HOOK));
|
||||
*jump_back = 0xE51FF004; // LDR PC, [PC, #-4]
|
||||
*(uintptr_t*)(jump_back + 1) = (uintptr_t)target_func + sizeof(ARM_HOOK);
|
||||
}
|
||||
@@ -2,6 +2,8 @@ package nfs.mod.mpcore
|
||||
|
||||
object MultiplayerCore {
|
||||
|
||||
external fun bumpBackTraceToLogcat()
|
||||
|
||||
fun loadCore() = System.loadLibrary("mpcore")
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user