Skip to content

Commit

Permalink
Version 2.0: Patch the useragent
Browse files Browse the repository at this point in the history
Fixes #3
  • Loading branch information
GaryOderNichts committed Oct 31, 2022
1 parent 961c94b commit 1037e1b
Show file tree
Hide file tree
Showing 10 changed files with 266 additions and 31 deletions.
6 changes: 6 additions & 0 deletions Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
FROM wiiuenv/devkitppc:20220806

COPY --from=wiiuenv/libkernel:20220724 /artifacts $DEVKITPRO
COPY --from=wiiuenv/wiiupluginsystem:20220826 /artifacts $DEVKITPRO

WORKDIR /project
13 changes: 7 additions & 6 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ TOPDIR ?= $(CURDIR)
include $(DEVKITPRO)/wups/share/wups_rules

WUT_ROOT := $(DEVKITPRO)/wut
WUMS_ROOT := $(DEVKITPRO)/wums
#-------------------------------------------------------------------------------
# TARGET is the name of the output
# BUILD is the directory where object files & intermediate files will be placed
Expand All @@ -20,9 +21,9 @@ WUT_ROOT := $(DEVKITPRO)/wut
#-------------------------------------------------------------------------------
TARGET := $(notdir $(CURDIR))
BUILD := build
SOURCES := .
SOURCES := source source/patcher
DATA := data
INCLUDES :=
INCLUDES := source

#-------------------------------------------------------------------------------
# options for code generation
Expand All @@ -32,18 +33,18 @@ CFLAGS := -Wall -O2 -ffunction-sections \

CFLAGS += $(INCLUDE) -D__WIIU__ -D__WUT__ -D__WUPS__

CXXFLAGS := $(CFLAGS)
CXXFLAGS := $(CFLAGS) -std=gnu++20

ASFLAGS := $(ARCH)
LDFLAGS = $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) $(WUPSSPECS)
LDFLAGS = $(ARCH) $(RPXSPECS) -Wl,-Map,$(notdir $*.map) -T$(WUMS_ROOT)/share/libkernel.ld $(WUPSSPECS)

LIBS := -lwups -lwut
LIBS := -lkernel -lwups -lwut

#-------------------------------------------------------------------------------
# list of directories containing libraries, this must be the top level
# containing include and lib
#-------------------------------------------------------------------------------
LIBDIRS := $(PORTLIBS) $(WUPS_ROOT) $(WUT_ROOT)
LIBDIRS := $(PORTLIBS) $(WUMS_ROOT) $(WUPS_ROOT) $(WUT_ROOT)

#-------------------------------------------------------------------------------
# no real need to edit anything past this point unless you need to add additional
Expand Down
19 changes: 15 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,21 @@ This endpoint now responds with:
The app then checks if acquiring this token has been sucessful and if not it will display the error. The acquired token itself is not used.
This is a Wii U Plugin System plugin for Aroma which just makes this request always return sucess and thus allowing the YouTube app to continue functioning.

## Info about version 2.0
On November 1st, 2022 YouTube started returning response 404 for the `WiiU` useragent platform.
Since v2.0 this plugin patches the platform in the useragent for the YouTube app to `NoU` instead of `WiiU`, which bypasses this block.

## Special Thanks to
[@ashquarky](https://github.com/ashquarky) for the awesome patcher framework which was taken from [Nimble](https://github.com/PretendoNetwork/Nimble).

## Building
```bash
# Build docker image (only needed once)
docker build . -t givemiiyoutube_builder

For building you need:
- [wups](https://github.com/wiiu-env/WiiUPluginSystem)
- [wut](https://github.com/decaf-emu/wut)
# make
docker run -it --rm -v ${PWD}:/project givemiiyoutube_builder make

Install them (in this order) according to their README's. Don't forget the dependencies of the libs itself.
# make clean
docker run -it --rm -v ${PWD}:/project givemiiyoutube_builder make clean
```
21 changes: 0 additions & 21 deletions main.cpp

This file was deleted.

81 changes: 81 additions & 0 deletions source/main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
#include <wups.h>
#include <whb/log.h>
#include <whb/log_module.h>
#include <whb/log_cafe.h>
#include <whb/log_udp.h>
#include <string.h>

#include <coreinit/title.h>

#include <patcher/rplinfo.h>
#include <patcher/patcher.h>

WUPS_PLUGIN_NAME("GiveMiiYouTube");
WUPS_PLUGIN_DESCRIPTION("Allows the YouTube app to continue functioning after its discontinuation");
WUPS_PLUGIN_VERSION("v2.0");
WUPS_PLUGIN_AUTHOR("GaryOderNichts");
WUPS_PLUGIN_LICENSE("MIT");

#define YOUTUBE_CLIENT_ID "e921a604fce89365498613fdf001b492"
#define YOUTUBE_TITLE_ID 0x0005000010105700llu
#define YOUTUBE_USERAGENT_PLATFORM "WiiU; "
#define YOUTUBE_USERAGENT_PLATFORM_REPLACEMENT "NoU; "

ON_APPLICATION_START()
{
// If this is not the YouTube app no need to do anything
if (OSGetTitleID() != YOUTUBE_TITLE_ID) {
return;
}

// Init logging
if (!WHBLogModuleInit()) {
WHBLogCafeInit();
WHBLogUdpInit();
}

WHBLogPrintf("GiveMiiYouTube: applying patches...");

// Patch the dynload functions so GetRPLInfo works
if (!PatchDynLoadFunctions()) {
WHBLogPrintf("GiveMiiYouTube: Failed to patch dynload functions");
return;
}

// Get the RPLInfo
auto rpl_info = TryGetRPLInfo();
if (!rpl_info) {
WHBLogPrintf("GiveMiiYouTube: Failed to get RPL info");
return;
}

// Find the rpx
rplinfo rpls = *rpl_info;
auto lb_shell_rpx = FindRPL(rpls, "lb_shell.rpx");
if (!lb_shell_rpx) {
WHBLogPrintf("GiveMiiYouTube: Failed to find lb_shell.rpx");
return;
}

// Patch the useragent platform
OSDynLoad_NotifyData rpx_data = *lb_shell_rpx;
if (!replace_string(rpx_data.dataAddr, rpx_data.dataSize,
YOUTUBE_USERAGENT_PLATFORM, sizeof(YOUTUBE_USERAGENT_PLATFORM),
YOUTUBE_USERAGENT_PLATFORM_REPLACEMENT, sizeof(YOUTUBE_USERAGENT_PLATFORM_REPLACEMENT))) {
WHBLogPrintf("GiveMiiYouTube: Failed to replace useragent platform");
return;
}
}

DECL_FUNCTION(int, AcquireIndependentServiceToken__Q2_2nn3actFPcPCc, uint8_t* token, const char* client_id)
{
// If this is the YouTube client, return sucess
if (client_id && strcmp(client_id, YOUTUBE_CLIENT_ID) == 0) {
WHBLogPrintf("GiveMiiYouTube: Faking service sucess for '%s'", client_id);
return 0;
}

return real_AcquireIndependentServiceToken__Q2_2nn3actFPcPCc(token, client_id);
}

WUPS_MUST_REPLACE(AcquireIndependentServiceToken__Q2_2nn3actFPcPCc, WUPS_LOADER_LIBRARY_NN_ACT, AcquireIndependentServiceToken__Q2_2nn3actFPcPCc);
20 changes: 20 additions & 0 deletions source/patcher/patcher.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
#include "patcher.h"

#include "utils/logger.h"

#include <kernel/kernel.h>
#include <coreinit/memorymap.h>

bool replace_string(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;
}
6 changes: 6 additions & 0 deletions source/patcher/patcher.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
#pragma once

#include <cstdint>
#include <cstdlib>

bool replace_string(uint32_t start, uint32_t size, const char* original_val, size_t original_val_sz, const char* new_val, size_t new_val_sz);
70 changes: 70 additions & 0 deletions source/patcher/rplinfo.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
/* Copyright 2022 Pretendo Network contributors <pretendo.network>
Copyright 2022 Ash Logan <[email protected]>
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 "rplinfo.h"

#include "utils/logger.h"

#include <kernel/kernel.h>

#include <coreinit/cache.h>
#include <coreinit/memorymap.h>

std::optional<std::vector<OSDynLoad_NotifyData>> TryGetRPLInfo() {
int num_rpls = OSDynLoad_GetNumberOfRPLs();
if (num_rpls == 0) {
return std::nullopt;
}

DEBUG_FUNCTION_LINE("num_rpls: %d", num_rpls);

std::vector<OSDynLoad_NotifyData> rpls;
rpls.resize(num_rpls);

bool ret = OSDynLoad_GetRPLInfo(0, num_rpls, rpls.data());
if (!ret) {
return std::nullopt;
}

return rpls;
}

bool PatchInstruction(void* instr, uint32_t original, uint32_t replacement) {
uint32_t current = *(uint32_t*)instr;
DEBUG_FUNCTION_LINE("current instr %08x", current);
if (current != original) return current == replacement;

KernelCopyData(OSEffectiveToPhysical((uint32_t)instr), OSEffectiveToPhysical((uint32_t)&replacement), sizeof(replacement));
//Only works on AROMA! WUPS 0.1's KernelCopyData is uncached, needs DCInvalidate here instead
DCFlushRange(instr, 4);
ICInvalidateRange(instr, 4);

current = *(uint32_t*)instr;
DEBUG_FUNCTION_LINE("patched instr %08x", current);

return true;
}

bool PatchDynLoadFunctions() {
uint32_t *patch1 = ((uint32_t *) &OSDynLoad_GetNumberOfRPLs) + 6;
uint32_t *patch2 = ((uint32_t *) &OSDynLoad_GetRPLInfo) + 22;

if (!PatchInstruction(patch1, 0x41820038 /* beq +38 */, 0x60000000 /*nop*/)) {
return false;
}
if (!PatchInstruction(patch2, 0x41820100 /* beq +100 */, 0x60000000 /*nop*/)) {
return false;
}

return true;
}
31 changes: 31 additions & 0 deletions source/patcher/rplinfo.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
/* Copyright 2022 Pretendo Network contributors <pretendo.network>
Copyright 2022 Ash Logan <[email protected]>
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 <optional>
#include <vector>
#include <string>
#include <algorithm>

#include <coreinit/dynload.h>

using rplinfo = std::vector<OSDynLoad_NotifyData>;

std::optional<rplinfo> TryGetRPLInfo();
bool PatchDynLoadFunctions();

constexpr inline std::optional<OSDynLoad_NotifyData> FindRPL(const rplinfo& rpls, const std::string& name) {
auto res = std::find_if(rpls.cbegin(), rpls.cend(), [&](const OSDynLoad_NotifyData& data){ return std::string(data.name).ends_with(name); });
if (res == rpls.cend()) return std::nullopt;
return *res;
}
30 changes: 30 additions & 0 deletions source/utils/logger.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#pragma once

#ifdef __cplusplus
extern "C" {
#endif

#include <string.h>
#include <whb/log.h>

#define __FILENAME_X__ (strrchr(__FILE__, '\\') ? strrchr(__FILE__, '\\') + 1 : __FILE__)
#define __FILENAME__ (strrchr(__FILE__, '/') ? strrchr(__FILE__, '/') + 1 : __FILENAME_X__)

#define OSFATAL_FUNCTION_LINE(FMT, ARGS...) \
do { \
OSFatal_printf("[%s]%s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
} while (0)

#define DEBUG_FUNCTION_LINE(FMT, ARGS...) \
do { \
WHBLogPrintf("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
} while (0);

#define DEBUG_FUNCTION_LINE_WRITE(FMT, ARGS...) \
do { \
WHBLogWritef("[%23s]%30s@L%04d: " FMT "", __FILENAME__, __FUNCTION__, __LINE__, ##ARGS); \
} while (0);

#ifdef __cplusplus
}
#endif

0 comments on commit 1037e1b

Please sign in to comment.