mirror of
https://github.com/NohamR/RMHook.git
synced 2026-04-08 07:59:58 +00:00
Move dev hooks to separate DevHooks files
Extracted development/reverse engineering hooks and helpers from reMarkable.m into new DevHooks.h and DevHooks.m files. Updated CMakeLists.txt to include the new files and their directory. This improves code organization and maintainability for development-only instrumentation.
This commit is contained in:
@@ -4,6 +4,9 @@
|
||||
#import "MemoryUtils.h"
|
||||
#import "Logger.h"
|
||||
#import "ResourceUtils.h"
|
||||
#ifdef BUILD_MODE_DEV
|
||||
#import "DevHooks.h"
|
||||
#endif
|
||||
#import <objc/runtime.h>
|
||||
#import <Cocoa/Cocoa.h>
|
||||
#include <stdint.h>
|
||||
@@ -26,6 +29,7 @@
|
||||
#include <QtCore/QVariant>
|
||||
#include <QtCore/QAnyStringView>
|
||||
|
||||
|
||||
static NSString *const kReMarkableConfigFileName = @"rmfakecloud.config";
|
||||
static NSString *const kReMarkableConfigHostKey = @"host";
|
||||
static NSString *const kReMarkableConfigPortKey = @"port";
|
||||
@@ -248,63 +252,7 @@ static int (*original_qRegisterResourceData)(
|
||||
const unsigned char *) = NULL;
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_MODE_DEV
|
||||
static ssize_t (*original_qIODevice_write)(
|
||||
QIODevice *self,
|
||||
const char *data,
|
||||
qint64 maxSize) = NULL;
|
||||
|
||||
// Hook for function at 0x10015A130
|
||||
static int64_t (*original_function_at_0x10015A130)(int64_t a1, int64_t a2) = NULL;
|
||||
|
||||
// Hook for function at 0x10015BC90
|
||||
static void (*original_function_at_0x10015BC90)(int64_t a1, int64_t a2) = NULL;
|
||||
|
||||
// Hook for function at 0x10016D520
|
||||
static int64_t (*original_function_at_0x10016D520)(int64_t a1, int64_t *a2, unsigned int a3, int64_t a4) = NULL;
|
||||
|
||||
// Hook for function at 0x1001B6EE0
|
||||
static void (*original_function_at_0x1001B6EE0)(int64_t a1, int64_t *a2, unsigned int a3) = NULL;
|
||||
#endif
|
||||
|
||||
#if defined(BUILD_MODE_DEV)
|
||||
// Memory logging helper function
|
||||
static void logMemory(const char *label, void *address, size_t length) {
|
||||
if (!address) {
|
||||
NSLogger(@"[reMarkable] %s: (null)", label);
|
||||
return;
|
||||
}
|
||||
|
||||
unsigned char *ptr = (unsigned char *)address;
|
||||
NSMutableString *hexLine = [NSMutableString stringWithFormat:@"[reMarkable] %s: ", label];
|
||||
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
[hexLine appendFormat:@"%02x ", ptr[i]];
|
||||
if ((i + 1) % 16 == 0 && i < length - 1) {
|
||||
NSLogger(@"%@", hexLine);
|
||||
hexLine = [NSMutableString stringWithString:@"[reMarkable] "];
|
||||
}
|
||||
}
|
||||
|
||||
// Log remaining bytes if any
|
||||
if ([hexLine length] > 28) { // More than just the prefix
|
||||
NSLogger(@"%@", hexLine);
|
||||
}
|
||||
}
|
||||
|
||||
// Stack trace logging helper function
|
||||
static void logStackTrace(const char *label) {
|
||||
NSLogger(@"[reMarkable] %s - Stack trace:", label);
|
||||
NSArray<NSString *> *callStack = [NSThread callStackSymbols];
|
||||
NSUInteger count = [callStack count];
|
||||
|
||||
// Skip first 2 frames (this function and the immediate caller's logging statement)
|
||||
for (NSUInteger i = 0; i < count; i++) {
|
||||
NSString *frame = callStack[i];
|
||||
NSLogger(@"[reMarkable] #%lu: %@", (unsigned long)i, frame);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_MODE_RMFAKECLOUD
|
||||
static inline bool shouldPatchURL(const QString &host) {
|
||||
@@ -362,13 +310,6 @@ static inline bool shouldPatchURL(const QString &host) {
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_MODE_DEV
|
||||
// // Hook function at address 0x1????
|
||||
// [MemoryUtils hookAddress:@"reMarkable"
|
||||
// staticAddress:0x????
|
||||
// hookFunction:(void *)hooked_function_at_0x????
|
||||
// originalFunction:(void **)&original_function_at_0x????
|
||||
// logPrefix:@"[reMarkable]"];
|
||||
|
||||
NSLogger(@"[reMarkable] Build mode: dev/reverse engineering");
|
||||
// [MemoryUtils hookSymbol:@"QtCore"
|
||||
// symbolName:@"__ZN9QIODevice5writeEPKcx"
|
||||
@@ -403,6 +344,29 @@ static inline bool shouldPatchURL(const QString &host) {
|
||||
// hookFunction:(void *)hooked_function_at_0x1001B6EE0
|
||||
// originalFunction:(void **)&original_function_at_0x1001B6EE0
|
||||
// logPrefix:@"[reMarkable]"];
|
||||
|
||||
// PlatformHelpers.exportFile implementation WIP
|
||||
|
||||
// // Hook function at address 0x100011790
|
||||
// [MemoryUtils hookAddress:@"reMarkable"
|
||||
// staticAddress:0x100011790
|
||||
// hookFunction:(void *)hooked_function_at_0x100011790
|
||||
// originalFunction:(void **)&original_function_at_0x100011790
|
||||
// logPrefix:@"[reMarkable]"];
|
||||
|
||||
// // Hook function at address 0x100011CE0
|
||||
// [MemoryUtils hookAddress:@"reMarkable"
|
||||
// staticAddress:0x100011CE0
|
||||
// hookFunction:(void *)hooked_function_at_0x100011CE0
|
||||
// originalFunction:(void **)&original_function_at_0x100011CE0
|
||||
// logPrefix:@"[reMarkable]"];
|
||||
|
||||
// [MemoryUtils hookSymbol:@"QtQml"
|
||||
// symbolName:@"__ZN11QQmlPrivate11qmlregisterENS_16RegistrationTypeEPv"
|
||||
// hookFunction:(void *)hooked_qmlregister
|
||||
// originalFunction:(void **)&original_qmlregister
|
||||
// logPrefix:@"[reMarkable]"];
|
||||
|
||||
#endif
|
||||
|
||||
return YES;
|
||||
@@ -509,141 +473,4 @@ extern "C" int hooked_qRegisterResourceData(
|
||||
}
|
||||
#endif // BUILD_MODE_QMLDIFF
|
||||
|
||||
#ifdef BUILD_MODE_DEV
|
||||
extern "C" ssize_t hooked_qIODevice_write(
|
||||
QIODevice *self,
|
||||
const char *data,
|
||||
qint64 maxSize) {
|
||||
NSLogger(@"[reMarkable] QIODevice::write called with maxSize: %lld", (long long)maxSize);
|
||||
|
||||
// Log the call stack
|
||||
logStackTrace("QIODevice::write call stack");
|
||||
|
||||
// Log the data to write
|
||||
logMemory("Data to write", (void *)data, (size_t)(maxSize < 64 ? maxSize : 64));
|
||||
|
||||
if (original_qIODevice_write) {
|
||||
ssize_t result = original_qIODevice_write(self, data, maxSize);
|
||||
NSLogger(@"[reMarkable] QIODevice::write result: %zd", result);
|
||||
return result;
|
||||
}
|
||||
NSLogger(@"[reMarkable] WARNING: Original QIODevice::write not available, returning 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" int64_t hooked_function_at_0x10015A130(int64_t a1, int64_t a2) {
|
||||
NSLogger(@"[reMarkable] Hook at 0x10015A130 called!");
|
||||
NSLogger(@"[reMarkable] a1 = 0x%llx", (unsigned long long)a1);
|
||||
NSLogger(@"[reMarkable] a2 = 0x%llx", (unsigned long long)a2);
|
||||
|
||||
logMemory("Memory at a1", (void *)a1, 64);
|
||||
logMemory("Memory at a2", (void *)a2, 64);
|
||||
|
||||
if (original_function_at_0x10015A130) {
|
||||
int64_t result = original_function_at_0x10015A130(a1, a2);
|
||||
NSLogger(@"[reMarkable] result = 0x%llx", (unsigned long long)result);
|
||||
return result;
|
||||
}
|
||||
|
||||
NSLogger(@"[reMarkable] WARNING: Original function at 0x10015A130 not available, returning 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void hooked_function_at_0x10015BC90(int64_t a1, int64_t a2) {
|
||||
NSLogger(@"[reMarkable] Hook at 0x10015BC90 called!");
|
||||
NSLogger(@"[reMarkable] a1 = 0x%llx", (unsigned long long)a1);
|
||||
NSLogger(@"[reMarkable] a2 = 0x%llx", (unsigned long long)a2);
|
||||
|
||||
logMemory("Memory at a1", (void *)a1, 64);
|
||||
logMemory("Memory at a2", (void *)a2, 64);
|
||||
|
||||
if (original_function_at_0x10015BC90) {
|
||||
original_function_at_0x10015BC90(a1, a2);
|
||||
NSLogger(@"[reMarkable] original function returned (void)");
|
||||
return;
|
||||
}
|
||||
|
||||
NSLogger(@"[reMarkable] WARNING: Original function at 0x10015BC90 not available");
|
||||
}
|
||||
|
||||
extern "C" int64_t hooked_function_at_0x10016D520(int64_t a1, int64_t *a2, unsigned int a3, int64_t a4) {
|
||||
NSLogger(@"[reMarkable] Hook at 0x10016D520 called!");
|
||||
NSLogger(@"[reMarkable] a1 = 0x%llx", (unsigned long long)a1);
|
||||
NSLogger(@"[reMarkable] a2 = %p", a2);
|
||||
if (a2) {
|
||||
NSLogger(@"[reMarkable] *a2 = 0x%llx", (unsigned long long)*a2);
|
||||
}
|
||||
NSLogger(@"[reMarkable] a3 = %u (0x%x)", a3, a3);
|
||||
NSLogger(@"[reMarkable] a4 = 0x%llx", (unsigned long long)a4);
|
||||
|
||||
// Log memory contents using helper function
|
||||
logMemory("Memory at a1", (void *)a1, 64);
|
||||
logMemory("Memory at a2", (void *)a2, 64);
|
||||
|
||||
if (a2 && *a2 != 0) {
|
||||
logMemory("Memory at *a2", (void *)*a2, 64);
|
||||
}
|
||||
|
||||
logMemory("Memory at a4", (void *)a4, 64);
|
||||
|
||||
if (original_function_at_0x10016D520) {
|
||||
int64_t result = original_function_at_0x10016D520(a1, a2, a3, a4);
|
||||
NSLogger(@"[reMarkable] result = 0x%llx", (unsigned long long)result);
|
||||
return result;
|
||||
}
|
||||
|
||||
NSLogger(@"[reMarkable] WARNING: Original function not available, returning 0");
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" void hooked_function_at_0x1001B6EE0(int64_t a1, int64_t *a2, unsigned int a3) {
|
||||
NSLogger(@"[reMarkable] Hook at 0x1001B6EE0 called!");
|
||||
NSLogger(@"[reMarkable] a1 = 0x%llx", (unsigned long long)a1);
|
||||
|
||||
// At a1 (PdfExporter object at 0x7ff4c17391e0):
|
||||
// +0x10 0x000600043EC10 QString (likely document name)
|
||||
NSLogger(@"[reMarkable] Reading QString at a1+0x10:");
|
||||
logMemory("a1 + 0x10 (raw)", (void *)(a1 + 0x10), 64);
|
||||
|
||||
void **qstrPtr = (void **)(a1 + 0x10);
|
||||
void *dataPtr = *qstrPtr;
|
||||
|
||||
if (!dataPtr) {
|
||||
NSLogger(@"[reMarkable] QString has null data pointer");
|
||||
return;
|
||||
}
|
||||
|
||||
// try reading potential size fields near dataPtr
|
||||
int32_t size = 0;
|
||||
for (int delta = 4; delta <= 32; delta += 4) {
|
||||
int32_t candidate = *(int32_t *)((char *)dataPtr - delta);
|
||||
if (candidate > 0 && candidate < 10000) {
|
||||
size = candidate;
|
||||
NSLogger(@"[reMarkable] QString plausible size=%d (found at -%d)", size, delta);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (size > 0) {
|
||||
NSString *qstringValue = [[NSString alloc] initWithCharacters:(unichar *)dataPtr length:size];
|
||||
NSLogger(@"[reMarkable] QString value: \"%@\"", qstringValue);
|
||||
} else {
|
||||
NSLogger(@"[reMarkable] QString: could not find valid size");
|
||||
}
|
||||
|
||||
NSLogger(@"[reMarkable] a2 = %p", a2);
|
||||
if (a2) {
|
||||
NSLogger(@"[reMarkable] *a2 = 0x%llx", (unsigned long long)*a2);
|
||||
}
|
||||
NSLogger(@"[reMarkable] a3 = %u (0x%x)", a3, a3);
|
||||
|
||||
if (original_function_at_0x1001B6EE0) {
|
||||
original_function_at_0x1001B6EE0(a1, a2, a3);
|
||||
NSLogger(@"[reMarkable] Original function at 0x1001B6EE0 executed");
|
||||
} else {
|
||||
NSLogger(@"[reMarkable] WARNING: Original function not available");
|
||||
}
|
||||
}
|
||||
#endif // BUILD_MODE_DEV
|
||||
|
||||
@end
|
||||
Reference in New Issue
Block a user