From 0bdda7bdf75b51fdf773d790948d574b669ef078 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E2=88=9A=28noham=29=C2=B2?= <100566912+NohamR@users.noreply.github.com> Date: Tue, 2 Dec 2025 22:52:47 +0100 Subject: [PATCH] Add hooks for new reMarkable functions and improve build script --- scripts/build.sh | 34 ++++++++++++- src/reMarkable/reMarkable.m | 99 ++++++++++++++++++++++++++++++------- 2 files changed, 114 insertions(+), 19 deletions(-) diff --git a/scripts/build.sh b/scripts/build.sh index 86fb931..f850ec2 100755 --- a/scripts/build.sh +++ b/scripts/build.sh @@ -14,6 +14,25 @@ QT_PATH=${QT_PATH:-$(ls -d "$HOME/Qt/6."* 2>/dev/null | sort -V | tail -n1)} # Parse build mode argument BUILD_MODE=${1:-rmfakecloud} +# Determine final dylib name for the selected build mode +case "$BUILD_MODE" in + rmfakecloud) + DYLIB_NAME="rmfakecloud.dylib" + ;; + qmldiff) + DYLIB_NAME="qmldiff.dylib" + ;; + dev) + DYLIB_NAME="dev.dylib" + ;; + all) + DYLIB_NAME="all.dylib" + ;; + *) + DYLIB_NAME="reMarkable.dylib" + ;; +esac + # Set CMake options based on build mode CMAKE_OPTIONS="" case "$BUILD_MODE" in @@ -54,12 +73,23 @@ fi make reMarkable if [ $? -eq 0 ]; then + # Rename the produced dylib so each build mode has a distinct file name + DYLIB_DIR="$PROJECT_DIR/build/dylibs" + DEFAULT_DYLIB="$DYLIB_DIR/reMarkable.dylib" + TARGET_DYLIB="$DYLIB_DIR/$DYLIB_NAME" + + if [ -f "$DEFAULT_DYLIB" ]; then + mv "$DEFAULT_DYLIB" "$TARGET_DYLIB" + else + echo "⚠️ Expected dylib not found at $DEFAULT_DYLIB" + fi + echo "" echo "✅ Compilation successful!" - echo "📍 Dylib: $PROJECT_DIR/build/dylibs/reMarkable.dylib" + echo "📍 Dylib: $TARGET_DYLIB" echo "" echo "🚀 To inject into the reMarkable application:" - echo " DYLD_INSERT_LIBRARIES=\"$PROJECT_DIR/build/dylibs/reMarkable.dylib\" /Applications/reMarkable.app/Contents/MacOS/reMarkable" + echo " DYLD_INSERT_LIBRARIES=\"$TARGET_DYLIB\" /Applications/reMarkable.app/Contents/MacOS/reMarkable" echo "" else echo "❌ Compilation failed" diff --git a/src/reMarkable/reMarkable.m b/src/reMarkable/reMarkable.m index ad41ca5..6e617fb 100644 --- a/src/reMarkable/reMarkable.m +++ b/src/reMarkable/reMarkable.m @@ -254,6 +254,12 @@ static ssize_t (*original_qIODevice_write)( 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; @@ -356,26 +362,47 @@ 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" - hookFunction:(void *)hooked_qIODevice_write - originalFunction:(void **)&original_qIODevice_write - logPrefix:@"[reMarkable]"]; + // [MemoryUtils hookSymbol:@"QtCore" + // symbolName:@"__ZN9QIODevice5writeEPKcx" + // hookFunction:(void *)hooked_qIODevice_write + // originalFunction:(void **)&original_qIODevice_write + // logPrefix:@"[reMarkable]"]; - // Hook function at address 0x10016D520 - [MemoryUtils hookAddress:@"reMarkable" - staticAddress:0x10016D520 - hookFunction:(void *)hooked_function_at_0x10016D520 - originalFunction:(void **)&original_function_at_0x10016D520 - logPrefix:@"[reMarkable]"]; + // // Hook function at address 0x10015A130 + // [MemoryUtils hookAddress:@"reMarkable" + // staticAddress:0x10015A130 + // hookFunction:(void *)hooked_function_at_0x10015A130 + // originalFunction:(void **)&original_function_at_0x10015A130 + // logPrefix:@"[reMarkable]"]; - // Hook function at address 0x1001B6EE0 - [MemoryUtils hookAddress:@"reMarkable" - staticAddress:0x1001B6EE0 - hookFunction:(void *)hooked_function_at_0x1001B6EE0 - originalFunction:(void **)&original_function_at_0x1001B6EE0 - logPrefix:@"[reMarkable]"]; + // // Hook function at address 0x10015BC90 + // [MemoryUtils hookAddress:@"reMarkable" + // staticAddress:0x10015BC90 + // hookFunction:(void *)hooked_function_at_0x10015BC90 + // originalFunction:(void **)&original_function_at_0x10015BC90 + // logPrefix:@"[reMarkable]"]; + + // // Hook function at address 0x10016D520 + // [MemoryUtils hookAddress:@"reMarkable" + // staticAddress:0x10016D520 + // hookFunction:(void *)hooked_function_at_0x10016D520 + // originalFunction:(void **)&original_function_at_0x10016D520 + // logPrefix:@"[reMarkable]"]; + + // // Hook function at address 0x1001B6EE0 + // [MemoryUtils hookAddress:@"reMarkable" + // staticAddress:0x1001B6EE0 + // hookFunction:(void *)hooked_function_at_0x1001B6EE0 + // originalFunction:(void **)&original_function_at_0x1001B6EE0 + // logPrefix:@"[reMarkable]"]; #endif return YES; @@ -437,6 +464,9 @@ extern "C" void hooked_qWebSocket_open( #endif // BUILD_MODE_RMFAKECLOUD #ifdef BUILD_MODE_QMLDIFF + +// See https://deepwiki.com/search/once-the-qrr-file-parsed-take_871f24a0-8636-4aee-bddf-7405b6e32584 for details on qmldiff replacement strategy + extern "C" int hooked_qRegisterResourceData( int version, const unsigned char *tree, @@ -501,6 +531,41 @@ extern "C" ssize_t hooked_qIODevice_write( 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);