forked from PretendoNetwork/Inkay
refactor: Move applet and olv url patches out into files
This commit is contained in:
parent
51e9042d71
commit
862e095e5a
8 changed files with 329 additions and 220 deletions
2
Makefile
2
Makefile
|
|
@ -21,7 +21,7 @@ WUMS_ROOT := $(DEVKITPRO)/wums
|
||||||
#-------------------------------------------------------------------------------
|
#-------------------------------------------------------------------------------
|
||||||
TARGET := Inkay-pretendo
|
TARGET := Inkay-pretendo
|
||||||
BUILD := build
|
BUILD := build
|
||||||
SOURCES := src src/utils
|
SOURCES := src src/patches src/utils
|
||||||
DATA := data
|
DATA := data
|
||||||
INCLUDES := src
|
INCLUDES := src
|
||||||
|
|
||||||
|
|
|
||||||
222
src/main.cpp
222
src/main.cpp
|
|
@ -26,9 +26,10 @@
|
||||||
#include <coreinit/memexpheap.h>
|
#include <coreinit/memexpheap.h>
|
||||||
#include <notifications/notifications.h>
|
#include <notifications/notifications.h>
|
||||||
#include <utils/logger.h>
|
#include <utils/logger.h>
|
||||||
#include "url_patches.h"
|
#include "iosu_url_patches.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "Notification.h"
|
#include "Notification.h"
|
||||||
|
#include "patches/olv_urls.h"
|
||||||
|
|
||||||
#include <coreinit/filesystem.h>
|
#include <coreinit/filesystem.h>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
|
|
@ -56,46 +57,6 @@ WUPS_USE_STORAGE("inkay");
|
||||||
#include <kernel/kernel.h>
|
#include <kernel/kernel.h>
|
||||||
#include <mocha/mocha.h>
|
#include <mocha/mocha.h>
|
||||||
|
|
||||||
const char original_url[] = "discovery.olv.nintendo.net/v1/endpoint";
|
|
||||||
const char new_url[] = "discovery.olv.pretendo.cc/v1/endpoint";
|
|
||||||
const char wave_original[] = {
|
|
||||||
0x68, 0x74, 0x74, 0x70, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2E, 0x6E, 0x69, 0x6E, 0x74, 0x65, 0x6E, 0x64,
|
|
||||||
0x6F, 0x2E, 0x6E, 0x65, 0x74
|
|
||||||
};
|
|
||||||
const char wave_new[] = {
|
|
||||||
0x68, 0x74, 0x74, 0x70, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00, 0x2E, 0x70, 0x72, 0x65, 0x74, 0x65, 0x6E, 0x64,
|
|
||||||
0x6F, 0x2E, 0x63, 0x63, 0x00
|
|
||||||
};
|
|
||||||
|
|
||||||
const char miiverse_green_highlight[] = {
|
|
||||||
0x82,0xff,0x05,0xff,0x82,0xff,0x05,0xff,0x1d,0xff,0x04,0xff,0x1d,0xff,0x04,0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
const char juxt_purple_highlight[] = {
|
|
||||||
0x5d,0x4a,0x9a,0xff,0x5d,0x4a,0x9a,0xff,0x5d,0x4a,0x9a,0xff,0x5d,0x4a,0x9a,0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
const char miiverse_green_touch1[] = {
|
|
||||||
0x94,0xd9,0x2a,0x00,0x57,0xbd,0x12,0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
const char juxt_purple_touch1[] = {
|
|
||||||
0x5d,0x4a,0x9a,0x00,0x5d,0x4a,0x9a,0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
const char miiverse_green_touch2[] = {
|
|
||||||
0x57,0xbd,0x12,0x00,0x94,0xd9,0x2a,0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
const char juxt_purple_touch2[] = {
|
|
||||||
0x5d,0x4a,0x9a,0x00,0x5d,0x4a,0x9a,0xff
|
|
||||||
};
|
|
||||||
|
|
||||||
_Static_assert(sizeof(original_url) > sizeof(new_url),
|
|
||||||
"new_url too long! Must be less than 38chars.");
|
|
||||||
|
|
||||||
//thanks @Gary#4139 :p
|
//thanks @Gary#4139 :p
|
||||||
static void write_string(uint32_t addr, const char* str)
|
static void write_string(uint32_t addr, const char* str)
|
||||||
{
|
{
|
||||||
|
|
@ -182,193 +143,16 @@ DEINITIALIZE_PLUGIN() {
|
||||||
NotificationModule_DeInitLibrary();
|
NotificationModule_DeInitLibrary();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool check_olv_libs() {
|
|
||||||
OSDynLoad_Module olv_handle = 0;
|
|
||||||
OSDynLoad_Error dret;
|
|
||||||
|
|
||||||
dret = OSDynLoad_IsModuleLoaded("nn_olv", &olv_handle);
|
|
||||||
if (dret == OS_DYNLOAD_OK && olv_handle != 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
dret = OSDynLoad_IsModuleLoaded("nn_olv2", &olv_handle);
|
|
||||||
if (dret == OS_DYNLOAD_OK && olv_handle != 0) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool replace(uint32_t start, uint32_t size, const char* original_val, size_t original_val_sz, const char* new_val, size_t new_val_sz) {
|
|
||||||
for (uint32_t addr = start; addr < start + size - original_val_sz; addr++) {
|
|
||||||
int ret = memcmp(original_val, (void*)addr, original_val_sz);
|
|
||||||
if (ret == 0) {
|
|
||||||
DEBUG_FUNCTION_LINE("found str @%08x: %s", addr, (const char*)addr);
|
|
||||||
KernelCopyData(OSEffectiveToPhysical(addr), OSEffectiveToPhysical((uint32_t)new_val), new_val_sz);
|
|
||||||
DEBUG_FUNCTION_LINE("new str @%08x: %s", addr, (const char*)addr);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
#define OLV_RPL "nn_olv.rpl"
|
|
||||||
bool path_is_olv(const char* path) {
|
|
||||||
auto path_len = strlen(path);
|
|
||||||
auto* path_suffix = path + path_len - (sizeof(OLV_RPL) - 1); //1 for null
|
|
||||||
return strcmp(path_suffix, OLV_RPL) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void new_rpl_loaded(OSDynLoad_Module module, void* ctx, OSDynLoad_NotifyReason reason, OSDynLoad_NotifyData* rpl) {
|
|
||||||
if (!Config::connect_to_network) {
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: Miiverse patches skipped.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Loaded olv?
|
|
||||||
if (reason != OS_DYNLOAD_NOTIFY_LOADED) return;
|
|
||||||
if (!path_is_olv(rpl->name)) return;
|
|
||||||
|
|
||||||
replace(rpl->dataAddr, rpl->dataSize, original_url, sizeof(original_url), new_url, sizeof(new_url));
|
|
||||||
}
|
|
||||||
|
|
||||||
void replaceBulk(uint32_t start, uint32_t size, const char* original_val, size_t original_val_sz, const char* new_val, size_t new_val_sz) {
|
|
||||||
for (uint32_t addr = start; addr < start + size - original_val_sz; addr++) {
|
|
||||||
int ret = memcmp(original_val, (void*)addr, original_val_sz);
|
|
||||||
if (ret == 0) {
|
|
||||||
DEBUG_FUNCTION_LINE("found bulk @%08x", addr);
|
|
||||||
KernelCopyData(OSEffectiveToPhysical(addr), OSEffectiveToPhysical((uint32_t)new_val), new_val_sz);
|
|
||||||
DEBUG_FUNCTION_LINE("new bulk @%08x", addr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ON_APPLICATION_START() {
|
ON_APPLICATION_START() {
|
||||||
WHBLogUdpInit();
|
WHBLogUdpInit();
|
||||||
WHBLogCafeInit();
|
WHBLogCafeInit();
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: hewwo!\n");
|
DEBUG_FUNCTION_LINE("Inkay: hewwo!\n");
|
||||||
|
|
||||||
OSDynLoad_AddNotifyCallback(&new_rpl_loaded, nullptr);
|
setup_olv_libs();
|
||||||
|
|
||||||
auto olvLoaded = check_olv_libs();
|
|
||||||
if (!olvLoaded) {
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: no olv, quitting for now\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!Config::connect_to_network) {
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: Miiverse patches skipped.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//wish there was a better way than "blow through MEM2"
|
|
||||||
uint32_t base_addr, size;
|
|
||||||
if (OSGetMemBound(OS_MEM2, &base_addr, &size)) {
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: OSGetMemBound failed!");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
replace(base_addr, size, original_url, sizeof(original_url), new_url, sizeof(new_url));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ON_APPLICATION_ENDS() {
|
ON_APPLICATION_ENDS() {
|
||||||
DEBUG_FUNCTION_LINE("Inkay: shutting down...\n");
|
DEBUG_FUNCTION_LINE("Inkay: shutting down...\n");
|
||||||
StopNotificationThread();
|
StopNotificationThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
static std::optional<FSFileHandle> rootca_pem_handle{};
|
|
||||||
|
|
||||||
DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, const char *mode, uint32_t *handle, int error) {
|
|
||||||
const char *initialOma = "vol/content/initial.oma";
|
|
||||||
|
|
||||||
if (!Config::connect_to_network) {
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: Miiverse patches skipped.");
|
|
||||||
return real_FSOpenFile(client, block, path, mode, handle, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (strcmp(initialOma, path) == 0) {
|
|
||||||
//below is a hacky (yet functional!) way to get Inkay to redirect URLs from the Miiverse applet
|
|
||||||
//we do it when loading this file since it should only load once, preventing massive lag spikes as it searches all of MEM2 xD
|
|
||||||
//WHBLogUdpInit();
|
|
||||||
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: hewwo!\n");
|
|
||||||
|
|
||||||
auto olvLoaded = check_olv_libs();
|
|
||||||
|
|
||||||
if (!olvLoaded) {
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: no olv, quitting for now\n");
|
|
||||||
} else {
|
|
||||||
uint32_t base_addr, size;
|
|
||||||
if (OSGetMemBound(OS_MEM2, &base_addr, &size)) {
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: OSGetMemBound failed!");
|
|
||||||
} else {
|
|
||||||
//We replace 2 times here.
|
|
||||||
//The first is for nn_olv, the second Wave (the applet itself)
|
|
||||||
replace(base_addr, size, original_url, sizeof(original_url), new_url, sizeof(new_url));
|
|
||||||
replace(0x10000000, 0x10000000, wave_original, sizeof(wave_original), wave_new, sizeof(wave_new));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check for root CA file and take note of its handle
|
|
||||||
} else if (strcmp("vol/content/browser/rootca.pem", path) == 0) {
|
|
||||||
int ret = real_FSOpenFile(client, block, path, mode, handle, error);
|
|
||||||
rootca_pem_handle = *handle;
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: Found Miiverse CA, replacing...");
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return real_FSOpenFile(client, block, path, mode, handle, error);
|
|
||||||
}
|
|
||||||
|
|
||||||
DECL_FUNCTION(FSStatus, FSReadFile, FSClient *client, FSCmdBlock *block, uint8_t *buffer, uint32_t size, uint32_t count, FSFileHandle handle, uint32_t unk1, uint32_t flags) {
|
|
||||||
if (size != 1) {
|
|
||||||
DEBUG_FUNCTION_LINE("Inkay: Miiverse CA replacement failed!");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rootca_pem_handle && *rootca_pem_handle == handle) {
|
|
||||||
memset(buffer, 0, size);
|
|
||||||
strcpy((char*)buffer, (const char*)ca_pem);
|
|
||||||
|
|
||||||
//this can't be done above (in the FSOpenFile hook) since it's not loaded yet.
|
|
||||||
replaceBulk(0x10000000, 0x10000000, miiverse_green_highlight, sizeof(miiverse_green_highlight), juxt_purple_highlight, sizeof(juxt_purple_highlight));
|
|
||||||
replaceBulk(0x10000000, 0x10000000, miiverse_green_touch1, sizeof(miiverse_green_touch1), juxt_purple_touch1, sizeof(juxt_purple_touch1));
|
|
||||||
replaceBulk(0x10000000, 0x10000000, miiverse_green_touch2, sizeof(miiverse_green_touch2), juxt_purple_touch2, sizeof(juxt_purple_touch2));
|
|
||||||
|
|
||||||
return (FSStatus)count;
|
|
||||||
}
|
|
||||||
|
|
||||||
return real_FSReadFile(client, block, buffer, size, count, handle, unk1, flags);
|
|
||||||
}
|
|
||||||
|
|
||||||
DECL_FUNCTION(FSStatus, FSCloseFile, FSClient * client, FSCmdBlock * block, FSFileHandle handle, FSErrorFlag errorMask) {
|
|
||||||
if (handle == rootca_pem_handle) {
|
|
||||||
rootca_pem_handle.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
return real_FSCloseFile(client, block, handle, errorMask);
|
|
||||||
}
|
|
||||||
|
|
||||||
DECL_FUNCTION(uint32_t, NSSLExportInternalServerCertificate, NSSLServerCertId cert, int unk, void* unk2, void* unk3) {
|
|
||||||
if (cert == NSSL_SERVER_CERT_THAWTE_PREMIUM_SERVER_CA) { // Martini patches
|
|
||||||
OSFatal("[598-0069] Please uninstall Martini patches to continue.\n" \
|
|
||||||
"See pretendo.network/docs/search for more info.\n\n" \
|
|
||||||
"Hold the POWER button for 4 seconds to shut down.\n\n"
|
|
||||||
" .\n"
|
|
||||||
".---------.'---.\n"
|
|
||||||
"'. : .'\n"
|
|
||||||
" '. .::: .'\n"
|
|
||||||
" '.'::'.'\n"
|
|
||||||
" '||'\n"
|
|
||||||
" ||\n"
|
|
||||||
" ||\n"
|
|
||||||
"mrz ||\n"
|
|
||||||
" ---====---");
|
|
||||||
}
|
|
||||||
return real_NSSLExportInternalServerCertificate(cert, unk, unk2, unk3);
|
|
||||||
}
|
|
||||||
|
|
||||||
WUPS_MUST_REPLACE_FOR_PROCESS(FSOpenFile, WUPS_LOADER_LIBRARY_COREINIT, FSOpenFile, WUPS_FP_TARGET_PROCESS_MIIVERSE);
|
|
||||||
WUPS_MUST_REPLACE_FOR_PROCESS(FSReadFile, WUPS_LOADER_LIBRARY_COREINIT, FSReadFile, WUPS_FP_TARGET_PROCESS_MIIVERSE);
|
|
||||||
WUPS_MUST_REPLACE_FOR_PROCESS(FSCloseFile, WUPS_LOADER_LIBRARY_COREINIT, FSCloseFile, WUPS_FP_TARGET_PROCESS_MIIVERSE);
|
|
||||||
WUPS_MUST_REPLACE_FOR_PROCESS(NSSLExportInternalServerCertificate, WUPS_LOADER_LIBRARY_NSYSNET, NSSLExportInternalServerCertificate, WUPS_FP_TARGET_PROCESS_MIIVERSE);
|
|
||||||
|
|
|
||||||
152
src/patches/olv_applet.cpp
Normal file
152
src/patches/olv_applet.cpp
Normal file
|
|
@ -0,0 +1,152 @@
|
||||||
|
/* Copyright 2023 Pretendo Network contributors <pretendo.network>
|
||||||
|
Copyright 2023 Ash Logan <ash@heyquark.com>
|
||||||
|
Copyright 2019 Maschell
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||||
|
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "config.h"
|
||||||
|
#include "olv_urls.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include "utils/replace_mem.h"
|
||||||
|
|
||||||
|
#include <wups.h>
|
||||||
|
#include <optional>
|
||||||
|
#include <coreinit/debug.h>
|
||||||
|
#include <coreinit/filesystem.h>
|
||||||
|
#include <coreinit/memory.h>
|
||||||
|
#include <nsysnet/nssl.h>
|
||||||
|
|
||||||
|
#include "ca_pem.h" // generated at buildtime
|
||||||
|
|
||||||
|
const char wave_original[] = {
|
||||||
|
0x68, 0x74, 0x74, 0x70, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x2E, 0x6E, 0x69, 0x6E, 0x74, 0x65, 0x6E, 0x64,
|
||||||
|
0x6F, 0x2E, 0x6E, 0x65, 0x74
|
||||||
|
};
|
||||||
|
const char wave_new[] = {
|
||||||
|
0x68, 0x74, 0x74, 0x70, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x2E, 0x70, 0x72, 0x65, 0x74, 0x65, 0x6E, 0x64,
|
||||||
|
0x6F, 0x2E, 0x63, 0x63, 0x00
|
||||||
|
};
|
||||||
|
|
||||||
|
const char miiverse_green_highlight[] = {
|
||||||
|
0x82, 0xff, 0x05, 0xff, 0x82, 0xff, 0x05, 0xff, 0x1d, 0xff, 0x04, 0xff, 0x1d, 0xff, 0x04, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
const char juxt_purple_highlight[] = {
|
||||||
|
0x5d, 0x4a, 0x9a, 0xff, 0x5d, 0x4a, 0x9a, 0xff, 0x5d, 0x4a, 0x9a, 0xff, 0x5d, 0x4a, 0x9a, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
const char miiverse_green_touch1[] = {
|
||||||
|
0x94, 0xd9, 0x2a, 0x00, 0x57, 0xbd, 0x12, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
const char juxt_purple_touch1[] = {
|
||||||
|
0x5d, 0x4a, 0x9a, 0x00, 0x5d, 0x4a, 0x9a, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
const char miiverse_green_touch2[] = {
|
||||||
|
0x57, 0xbd, 0x12, 0x00, 0x94, 0xd9, 0x2a, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
const char juxt_purple_touch2[] = {
|
||||||
|
0x5d, 0x4a, 0x9a, 0x00, 0x5d, 0x4a, 0x9a, 0xff
|
||||||
|
};
|
||||||
|
|
||||||
|
static std::optional <FSFileHandle> rootca_pem_handle{};
|
||||||
|
|
||||||
|
DECL_FUNCTION(int, FSOpenFile, FSClient *client, FSCmdBlock *block, char *path, const char *mode, uint32_t *handle,
|
||||||
|
int error) {
|
||||||
|
const char *initialOma = "vol/content/initial.oma";
|
||||||
|
|
||||||
|
if (!Config::connect_to_network) {
|
||||||
|
DEBUG_FUNCTION_LINE("Inkay: Miiverse patches skipped.");
|
||||||
|
return real_FSOpenFile(client, block, path, mode, handle, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (strcmp(initialOma, path) == 0) {
|
||||||
|
//below is a hacky (yet functional!) way to get Inkay to redirect URLs from the Miiverse applet
|
||||||
|
//we do it when loading this file since it should only load once, preventing massive lag spikes as it searches all of MEM2 xD
|
||||||
|
//WHBLogUdpInit();
|
||||||
|
|
||||||
|
DEBUG_FUNCTION_LINE("Inkay: hewwo!\n");
|
||||||
|
|
||||||
|
auto olv_ok = setup_olv_libs();
|
||||||
|
// Patch applet binary too
|
||||||
|
if (olv_ok)
|
||||||
|
replace(0x10000000, 0x10000000, wave_original, sizeof(wave_original), wave_new, sizeof(wave_new));
|
||||||
|
// Check for root CA file and take note of its handle
|
||||||
|
} else if (strcmp("vol/content/browser/rootca.pem", path) == 0) {
|
||||||
|
int ret = real_FSOpenFile(client, block, path, mode, handle, error);
|
||||||
|
rootca_pem_handle = *handle;
|
||||||
|
DEBUG_FUNCTION_LINE("Inkay: Found Miiverse CA, replacing...");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_FSOpenFile(client, block, path, mode, handle, error);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL_FUNCTION(FSStatus, FSReadFile, FSClient *client, FSCmdBlock *block, uint8_t *buffer, uint32_t size, uint32_t count,
|
||||||
|
FSFileHandle handle, uint32_t unk1, uint32_t flags) {
|
||||||
|
if (size != 1) {
|
||||||
|
DEBUG_FUNCTION_LINE("Inkay: Miiverse CA replacement failed!");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rootca_pem_handle && *rootca_pem_handle == handle) {
|
||||||
|
memset(buffer, 0, size);
|
||||||
|
strcpy((char *) buffer, (const char *) ca_pem);
|
||||||
|
|
||||||
|
//this can't be done above (in the FSOpenFile hook) since it's not loaded yet.
|
||||||
|
replaceBulk(0x10000000, 0x10000000, miiverse_green_highlight, sizeof(miiverse_green_highlight),
|
||||||
|
juxt_purple_highlight, sizeof(juxt_purple_highlight));
|
||||||
|
replaceBulk(0x10000000, 0x10000000, miiverse_green_touch1, sizeof(miiverse_green_touch1), juxt_purple_touch1,
|
||||||
|
sizeof(juxt_purple_touch1));
|
||||||
|
replaceBulk(0x10000000, 0x10000000, miiverse_green_touch2, sizeof(miiverse_green_touch2), juxt_purple_touch2,
|
||||||
|
sizeof(juxt_purple_touch2));
|
||||||
|
|
||||||
|
return (FSStatus) count;
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_FSReadFile(client, block, buffer, size, count, handle, unk1, flags);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL_FUNCTION(FSStatus, FSCloseFile, FSClient *client, FSCmdBlock *block, FSFileHandle handle, FSErrorFlag errorMask) {
|
||||||
|
if (handle == rootca_pem_handle) {
|
||||||
|
rootca_pem_handle.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
return real_FSCloseFile(client, block, handle, errorMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
DECL_FUNCTION(uint32_t, NSSLExportInternalServerCertificate, NSSLServerCertId cert, int unk, void *unk2, void *unk3) {
|
||||||
|
if (cert == NSSL_SERVER_CERT_THAWTE_PREMIUM_SERVER_CA) { // Martini patches
|
||||||
|
OSFatal("[598-0069] Please uninstall Martini patches to continue.\n" \
|
||||||
|
"See pretendo.network/docs/search for more info.\n\n" \
|
||||||
|
"Hold the POWER button for 4 seconds to shut down.\n\n"
|
||||||
|
" .\n"
|
||||||
|
".---------.'---.\n"
|
||||||
|
"'. : .'\n"
|
||||||
|
" '. .::: .'\n"
|
||||||
|
" '.'::'.'\n"
|
||||||
|
" '||'\n"
|
||||||
|
" ||\n"
|
||||||
|
" ||\n"
|
||||||
|
"mrz ||\n"
|
||||||
|
" ---====---");
|
||||||
|
}
|
||||||
|
return real_NSSLExportInternalServerCertificate(cert, unk, unk2, unk3);
|
||||||
|
}
|
||||||
|
|
||||||
|
WUPS_MUST_REPLACE_FOR_PROCESS(FSOpenFile, WUPS_LOADER_LIBRARY_COREINIT, FSOpenFile, WUPS_FP_TARGET_PROCESS_MIIVERSE);
|
||||||
|
WUPS_MUST_REPLACE_FOR_PROCESS(FSReadFile, WUPS_LOADER_LIBRARY_COREINIT, FSReadFile, WUPS_FP_TARGET_PROCESS_MIIVERSE);
|
||||||
|
WUPS_MUST_REPLACE_FOR_PROCESS(FSCloseFile, WUPS_LOADER_LIBRARY_COREINIT, FSCloseFile, WUPS_FP_TARGET_PROCESS_MIIVERSE);
|
||||||
|
WUPS_MUST_REPLACE_FOR_PROCESS(NSSLExportInternalServerCertificate, WUPS_LOADER_LIBRARY_NSYSNET,
|
||||||
|
NSSLExportInternalServerCertificate, WUPS_FP_TARGET_PROCESS_MIIVERSE);
|
||||||
83
src/patches/olv_urls.cpp
Normal file
83
src/patches/olv_urls.cpp
Normal file
|
|
@ -0,0 +1,83 @@
|
||||||
|
/* Copyright 2023 Pretendo Network contributors <pretendo.network>
|
||||||
|
Copyright 2023 Ash Logan <ash@heyquark.com>
|
||||||
|
Copyright 2019 Maschell
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||||
|
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "olv_urls.h"
|
||||||
|
#include "config.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
#include "utils/replace_mem.h"
|
||||||
|
|
||||||
|
#include <cstring>
|
||||||
|
#include <coreinit/dynload.h>
|
||||||
|
#include <coreinit/memory.h>
|
||||||
|
|
||||||
|
bool check_olv_libs() {
|
||||||
|
OSDynLoad_Module olv_handle = 0;
|
||||||
|
OSDynLoad_Error dret;
|
||||||
|
|
||||||
|
dret = OSDynLoad_IsModuleLoaded("nn_olv", &olv_handle);
|
||||||
|
if (dret == OS_DYNLOAD_OK && olv_handle != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
dret = OSDynLoad_IsModuleLoaded("nn_olv2", &olv_handle);
|
||||||
|
if (dret == OS_DYNLOAD_OK && olv_handle != 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#define OLV_RPL "nn_olv.rpl"
|
||||||
|
bool path_is_olv(const char* path) {
|
||||||
|
auto path_len = strlen(path);
|
||||||
|
auto* path_suffix = path + path_len - (sizeof(OLV_RPL) - 1); //1 for null
|
||||||
|
return strcmp(path_suffix, OLV_RPL) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void new_rpl_loaded(OSDynLoad_Module module, void* ctx, OSDynLoad_NotifyReason reason, OSDynLoad_NotifyData* rpl) {
|
||||||
|
if (!Config::connect_to_network) {
|
||||||
|
DEBUG_FUNCTION_LINE("Inkay: Miiverse patches skipped.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Loaded olv?
|
||||||
|
if (reason != OS_DYNLOAD_NOTIFY_LOADED) return;
|
||||||
|
if (!path_is_olv(rpl->name)) return;
|
||||||
|
|
||||||
|
replace(rpl->dataAddr, rpl->dataSize, original_url, sizeof(original_url), new_url, sizeof(new_url));
|
||||||
|
}
|
||||||
|
|
||||||
|
bool setup_olv_libs() {
|
||||||
|
if (!Config::connect_to_network) {
|
||||||
|
DEBUG_FUNCTION_LINE("Inkay: Miiverse patches skipped.");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
OSDynLoad_AddNotifyCallback(&new_rpl_loaded, nullptr);
|
||||||
|
|
||||||
|
auto olvLoaded = check_olv_libs();
|
||||||
|
if (!olvLoaded) {
|
||||||
|
DEBUG_FUNCTION_LINE("Inkay: no olv, quitting for now\n");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
//wish there was a better way than "blow through MEM2"
|
||||||
|
uint32_t base_addr, size;
|
||||||
|
if (OSGetMemBound(OS_MEM2, &base_addr, &size)) {
|
||||||
|
DEBUG_FUNCTION_LINE("Inkay: OSGetMemBound failed!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return replace(base_addr, size, original_url, sizeof(original_url), new_url, sizeof(new_url));
|
||||||
|
}
|
||||||
25
src/patches/olv_urls.h
Normal file
25
src/patches/olv_urls.h
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* Copyright 2023 Pretendo Network contributors <pretendo.network>
|
||||||
|
Copyright 2023 Ash Logan <ash@heyquark.com>
|
||||||
|
Copyright 2019 Maschell
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||||
|
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
const char original_url[] = "discovery.olv.nintendo.net/v1/endpoint";
|
||||||
|
const char new_url[] = "discovery.olv.pretendo.cc/v1/endpoint";
|
||||||
|
|
||||||
|
_Static_assert(sizeof(original_url) > sizeof(new_url),
|
||||||
|
"new_url too long! Must be less than 38chars.");
|
||||||
|
|
||||||
|
bool setup_olv_libs();
|
||||||
44
src/utils/replace_mem.cpp
Normal file
44
src/utils/replace_mem.cpp
Normal file
|
|
@ -0,0 +1,44 @@
|
||||||
|
/* Copyright 2023 Pretendo Network contributors <pretendo.network>
|
||||||
|
Copyright 2023 Ash Logan <ash@heyquark.com>
|
||||||
|
Copyright 2019 Maschell
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||||
|
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "replace_mem.h"
|
||||||
|
#include "utils/logger.h"
|
||||||
|
|
||||||
|
#include <kernel/kernel.h>
|
||||||
|
#include <coreinit/memorymap.h>
|
||||||
|
|
||||||
|
bool replace(uint32_t start, uint32_t size, const char* original_val, size_t original_val_sz, const char* new_val, size_t new_val_sz) {
|
||||||
|
for (uint32_t addr = start; addr < start + size - original_val_sz; addr++) {
|
||||||
|
int ret = memcmp(original_val, (void*)addr, original_val_sz);
|
||||||
|
if (ret == 0) {
|
||||||
|
DEBUG_FUNCTION_LINE("found str @%08x: %s", addr, (const char*)addr);
|
||||||
|
KernelCopyData(OSEffectiveToPhysical(addr), OSEffectiveToPhysical((uint32_t)new_val), new_val_sz);
|
||||||
|
DEBUG_FUNCTION_LINE("new str @%08x: %s", addr, (const char*)addr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void replaceBulk(uint32_t start, uint32_t size, const char* original_val, size_t original_val_sz, const char* new_val, size_t new_val_sz) {
|
||||||
|
for (uint32_t addr = start; addr < start + size - original_val_sz; addr++) {
|
||||||
|
int ret = memcmp(original_val, (void*)addr, original_val_sz);
|
||||||
|
if (ret == 0) {
|
||||||
|
DEBUG_FUNCTION_LINE("found bulk @%08x", addr);
|
||||||
|
KernelCopyData(OSEffectiveToPhysical(addr), OSEffectiveToPhysical((uint32_t)new_val), new_val_sz);
|
||||||
|
DEBUG_FUNCTION_LINE("new bulk @%08x", addr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
21
src/utils/replace_mem.h
Normal file
21
src/utils/replace_mem.h
Normal file
|
|
@ -0,0 +1,21 @@
|
||||||
|
/* Copyright 2023 Pretendo Network contributors <pretendo.network>
|
||||||
|
Copyright 2023 Ash Logan <ash@heyquark.com>
|
||||||
|
Copyright 2019 Maschell
|
||||||
|
|
||||||
|
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby
|
||||||
|
granted, provided that the above copyright notice and this permission notice appear in all copies.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
|
||||||
|
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
|
||||||
|
INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
|
||||||
|
PERFORMANCE OF THIS SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <cstdint>
|
||||||
|
#include <cstddef>
|
||||||
|
|
||||||
|
bool replace(uint32_t start, uint32_t size, const char* original_val, size_t original_val_sz, const char* new_val, size_t new_val_sz);
|
||||||
|
void replaceBulk(uint32_t start, uint32_t size, const char* original_val, size_t original_val_sz, const char* new_val, size_t new_val_sz);
|
||||||
Loading…
Reference in a new issue