Add build script and hook updates

This commit is contained in:
√(noham)²
2026-05-15 19:44:54 +02:00
parent bb174602ba
commit 33f9772c90
8 changed files with 289 additions and 30 deletions

View File

@@ -17,34 +17,127 @@
#include <QtCore/QVariant>
#include <QtCore/QAnyStringView>
#import <UIKit/UIKit.h>
#define TARGET_MODULE "remarkable_mobile"
#define IDA_BASE 0x100000000
// __ZN21QNetworkAccessManager13createRequestENS_9OperationERK15QNetworkRequestP9QIODevice
#if V3_25_0
#define QtNetworkAccessManager_createRequest 0x1017FB9F4 // sub_1017FB9F4
#elif V3_27_1
#define QtNetworkAccessManager_createRequest 0x10192472C // sub_10192472C
#endif
// __ZN10QWebSocket4openERK15QNetworkRequest
#if V3_25_0
# define QtWebSocket_open 0x100526A18 // sub_100526A18
#elif V3_27_1
# define QtWebSocket_open 0x100564A24 // sub_100564A24
#endif
// QObject *__fastcall QNetworkAccessManager::createRequest(
// QtSharedPointer::ExternalRefCountData *a1,
// __int64 a2,
// const QNetworkRequest *a3,
// __int64 a4)
static void *(*orig_createRequest)(void *a1, int a2, const void *a3, void *a4);
#import "Config.h"
void *hook_createRequest(void *a1, int a2, const void *a3, void *a4) {
NSLog(@"[RMHook-iOS] createRequest called");
return orig_createRequest(a1, a2, a3, a4);
static inline QString QStringFromNSStringSafe(NSString* str) {
if (!str) return QString();
return QString::fromNSString(str);
}
// void __fastcall QWebSocket::open(QWebSocket *this, const QUrl *a2, const QWebSocketHandshakeOptions *a3)
static void (*orig_open)(void *this_ptr, const void *a2, const void *a3);
static inline bool shouldPatchURL(const QString &host) {
if (host.isEmpty()) {
return false;
}
void hook_open(void *this_ptr, const void *a2, const void *a3) {
NSLog(@"[RMHook-iOS] QWebSocket::open called");
orig_open(this_ptr, a2, a3);
return QString(R"""(
hwr-production-dot-remarkable-production.appspot.com
service-manager-production-dot-remarkable-production.appspot.com
local.appspot.com
my.remarkable.com
ping.remarkable.com
internal.cloud.remarkable.com
eu.tectonic.remarkable.com
backtrace-proxy.cloud.remarkable.engineering
dev.ping.remarkable.com
dev.tectonic.remarkable.com
dev.internal.cloud.remarkable.com
eu.internal.tctn.cloud.remarkable.com
webapp-prod.cloud.remarkable.engineering
)""")
.contains(host, Qt::CaseInsensitive);
}
// QObject *__fastcall QNetworkAccessManager::createRequest(
// QtSharedPointer::ExternalRefCountData *self,
// __int64 op,
// const QNetworkRequest *req,
// __int64 outgoingData)
static QNetworkReply* (*original_qNetworkAccessManager_createRequest)(
QNetworkAccessManager* self,
QNetworkAccessManager::Operation op,
const QNetworkRequest& req,
QIODevice* outgoingData
);
QNetworkReply* hooked_qNetworkAccessManager_createRequest(
QNetworkAccessManager* self,
QNetworkAccessManager::Operation op,
const QNetworkRequest& req,
QIODevice* outgoingData
) {
NSLog(@"[RMHook-iOS] createRequest called for URL: %s", req.url().toString().toStdString().c_str());
const QString host = req.url().host();
if (shouldPatchURL(host)) {
QNetworkRequest newReq(req);
QUrl newUrl = req.url();
const QString overrideHost = QStringFromNSStringSafe(gConfiguredHost);
newUrl.setHost(overrideHost);
newUrl.setPort([gConfiguredPort intValue]);
newReq.setUrl(newUrl);
if (original_qNetworkAccessManager_createRequest) {
return original_qNetworkAccessManager_createRequest(self, op, newReq, outgoingData);
}
return nullptr;
}
if (original_qNetworkAccessManager_createRequest) {
return original_qNetworkAccessManager_createRequest(self, op, req, outgoingData);
}
return nullptr;
}
// void __fastcall QWebSocket::open(QWebSocket *self, const QNetworkRequest *req)
static void (*original_qWebSocket_open)(
QWebSocket* self,
const QNetworkRequest& req
);
void hooked_qWebSocket_open(
QWebSocket* self,
const QNetworkRequest& req
) {
NSLog(@"[RMHook-iOS] QWebSocket::open called for URL: %s", req.url().toString().toStdString().c_str());
if (!original_qWebSocket_open) {
return;
}
const QString host = req.url().host();
if (shouldPatchURL(host)) {
QUrl newUrl = req.url();
const QString overrideHost = QStringFromNSStringSafe(gConfiguredHost);
newUrl.setHost(overrideHost);
newUrl.setPort([gConfiguredPort intValue]);
QNetworkRequest newReq(req);
newReq.setUrl(newUrl);
original_qWebSocket_open(self, newReq);
return;
}
original_qWebSocket_open(self, req);
}
@@ -58,9 +151,20 @@ static uintptr_t findModuleBase(const char *moduleName) {
return 0;
}
// Constructor
%ctor {
@autoreleasepool {
loadConfiguration();
if (gConfiguredHost.length == 0 || [gConfiguredPort intValue] == 0) {
[[NSNotificationCenter defaultCenter] addObserverForName:UIApplicationDidFinishLaunchingNotification
object:nil
queue:[NSOperationQueue mainQueue]
usingBlock:^(NSNotification * _Nonnull note) {
showConfigAlert();
}];
}
uintptr_t base = findModuleBase(TARGET_MODULE);
if (!base) {
NSLog(@"[RMHook-iOS] Module '%s' not found, tweak inactive.", TARGET_MODULE);
@@ -70,12 +174,12 @@ static uintptr_t findModuleBase(const char *moduleName) {
uintptr_t offset = QtNetworkAccessManager_createRequest - IDA_BASE;
uintptr_t addr = base + offset;
MSHookFunction((void *)addr, (void *)hook_createRequest, (void **)&orig_createRequest);
MSHookFunction((void *)addr, (void *)hooked_qNetworkAccessManager_createRequest, (void **)&original_qNetworkAccessManager_createRequest);
NSLog(@"[RMHook-iOS] Hooked QtNetworkAccessManager_createRequest @ 0x%lx (offset 0x%lx)", (unsigned long)addr, (unsigned long)offset);
uintptr_t offset2 = QtWebSocket_open - IDA_BASE;
uintptr_t addr2 = base + offset2;
MSHookFunction((void *)addr2, (void *)hook_open, (void **)&orig_open);
MSHookFunction((void *)addr2, (void *)hooked_qWebSocket_open, (void **)&original_qWebSocket_open);
NSLog(@"[RMHook-iOS] Hooked QtWebSocket_open @ 0x%lx (offset 0x%lx)", (unsigned long)addr2, (unsigned long)offset2);
}
}