From 9293335118fc684b29b446ea41d2c6e23f030060 Mon Sep 17 00:00:00 2001 From: borntohonk <6264306+borntohonk@users.noreply.github.com> Date: Sun, 27 Oct 2024 10:57:15 +0100 Subject: [PATCH 1/4] :) --- .github/workflows/build-jobs.yaml | 59 ++++++++++++++++++++++--------- .github/workflows/build.yml | 14 -------- .github/workflows/release.yml | 38 -------------------- Makefile | 2 +- README.md | 14 +++----- overlay/src/main.cpp | 10 ++++-- sysmod/src/main.cpp | 46 +++++++++++++++++++----- 7 files changed, 95 insertions(+), 88 deletions(-) delete mode 100644 .github/workflows/build.yml delete mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/build-jobs.yaml b/.github/workflows/build-jobs.yaml index 9858275..dfd713e 100644 --- a/.github/workflows/build-jobs.yaml +++ b/.github/workflows/build-jobs.yaml @@ -2,24 +2,51 @@ name: Build jobs on: workflow_call: + workflow_dispatch: + push: jobs: build: - name: build runs-on: ubuntu-latest - container: ghcr.io/pgalonza/devkita64-atmosphere:latest - #or you can use a generic one - #container: devkitpro/devkita64:latest + container: devkitpro/devkita64 + steps: - - name: Checkout - uses: actions/checkout@v4 - with: - submodules: recursive - - name: Build sys-patch - run: | - make dist -j $(nproc) - - name: Upload artifacts - uses: actions/upload-artifact@v4 - with: - name: sys-patch-artifacts - path: ./sys-patch.zip + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-tags: true + path: sys-patch + submodules: recursive + + - name: Build sys-patch + run: | + make -C sys-patch -j$(nproc) dist && \ + VERSION=$(grep 'export VERSION := ' sys-patch/Makefile | cut -c 19-) + TAGVERSION=$(curl -s https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest | grep "tag_name" | head -1 | cut -d '"' -f 4) + echo "VERSION=${VERSION}" >> $GITHUB_ENV + echo "TAGVERSION=${TAGVERSION}" >> $GITHUB_ENV + + - name: Upload artifact + uses: actions/upload-artifact@v4 + with: + include-hidden-files: true + overwrite: true + name: sys-patch-${{ env.VERSION }} + path: sys-patch/out/ + + - name: Fetch git cli and upload release + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + run: | + if [ ${{ env.TAGVERSION }} = v${{ env.VERSION }} ]; + then echo "Tag version and makefile version are same, don't publish release, only artifact uploaded." + else + wget -q $(curl -s https://api.github.com/repos/cli/cli/releases/latest | grep "browser_download_url" | grep "linux_amd64.tar.gz" | head -1 | cut -d '"' -f 4) && \ + tar -xzf gh*.tar.gz && \ + chmod +x gh*/bin/gh && \ + chmod +x gh*/bin/gh && \ + cp gh*/bin/gh /bin/gh && \ + rm gh*.tar.gz && \ + rm -rf gh* + gh release create v${{ env.VERSION }} sys-patch/sys-patch.zip --title "Sys-patch version ${{ env.VERSION }}" --repo github.com/$GITHUB_REPOSITORY + fi diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml deleted file mode 100644 index 6443090..0000000 --- a/.github/workflows/build.yml +++ /dev/null @@ -1,14 +0,0 @@ -name: Build sys-patch - -on: - push: - branches: - - master - - feature-integration - paths-ignore: - - 'Dockerfile' - - '.github/workflows/image.yml' - -jobs: - build-workflow: - uses: ./.github/workflows/build-jobs.yaml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml deleted file mode 100644 index ce4f921..0000000 --- a/.github/workflows/release.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Create release - -on: - push: - tags: - - '[0-9]+.[0-9]+.[0-9]+' - -permissions: - contents: write - -jobs: - build-workflow: - uses: ./.github/workflows/build-jobs.yaml - create-release: - runs-on: ubuntu-latest - needs: build-workflow - steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 0 - - name: Generate a changelog - uses: orhun/git-cliff-action@v3 - with: - config: ./configs/cliff.toml - args: --verbose - - name: Download artifact - uses: actions/download-artifact@v4 - with: - name: sys-patch-artifacts - path: "./" - - name: Create release - uses: ncipollo/release-action@v1 - with: - artifacts: "sys-patch.zip" - prerelease: false - name: "ns-sys-patch ${{ github.ref_name }}" - bodyFile: "git-cliff/CHANGELOG.md" diff --git a/Makefile b/Makefile index 5d4b3a8..40c7fc0 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ MAKEFILES := sysmod overlay TARGETS := $(foreach dir,$(MAKEFILES),$(CURDIR)/$(dir)) # the below was taken from atmosphere + switch-examples makefile -export VERSION := 1.5.4 +export VERSION := 1.5.6 ifneq ($(strip $(shell git symbolic-ref --short HEAD 2>/dev/null)),) export GIT_BRANCH := $(shell git symbolic-ref --short HEAD) diff --git a/README.md b/README.md index ad833ca..f1940d8 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # sys-patch -A script-like system module that patches **fs**, **es**, **ldr** and **nifm** on boot. +A script-like system module that patches **fs**, **es**, **ldr**, **nifm** and **nim** on boot. --- @@ -57,14 +57,10 @@ To activate the sys-module, reboot your switch, or, use [sysmodules overlay](htt Here's a quick run down of what's being patched: -- **fs** -- **es** -- **ldr** -- **nifm** - -**fs** and **es** need new patches after every new firmware version. -**ldr** needs new patches after every new [Atmosphere](https://github.com/Atmosphere-NX/Atmosphere/) release. -**nifm** ctest patch allows the device to connect to a network without needing to make a connection to a server. +- **fs** and **es** need new patches after every new firmware version. +- **ldr** needs new patches after every new [Atmosphere](https://github.com/Atmosphere-NX/Atmosphere/) release. +- **nifm** ctest patch allows the device to connect to a network without needing to make a connection to a server +- **nim** patches to the ssl function call within nim that queries "https://api.hac.%.ctest.srv.nintendo.net/v1/time", and crashes the console if console ssl certificate is not intact. This patch instead makes the console not crash. The patches are applied on boot. Once done, the sys-module stops running. The memory footprint *(16kib)* and the binary size *(~50kib)* are both very small. diff --git a/overlay/src/main.cpp b/overlay/src/main.cpp index 46a1500..2afb6f3 100644 --- a/overlay/src/main.cpp +++ b/overlay/src/main.cpp @@ -103,7 +103,6 @@ class GuiToggle final : public tsl::Gui { list->addItem(config_noacidsigchk2.create_list_item("noacidsigchk2")); list->addItem(config_noncasigchk_old.create_list_item("noncasigchk_old")); list->addItem(config_noncasigchk_new.create_list_item("noncasigchk_new")); - list->addItem(config_noncasigchk_new2.create_list_item("noncasigchk_new2")); list->addItem(config_nocntchk.create_list_item("nocntchk")); list->addItem(config_nocntchk2.create_list_item("nocntchk2")); @@ -121,6 +120,11 @@ class GuiToggle final : public tsl::Gui { list->addItem(new tsl::elm::CategoryHeader("NIM - 0100000000000025")); list->addItem(config_nim.create_list_item("nim")); + list->addItem(new tsl::elm::CategoryHeader("Disable CA Verification - apply all")); + list->addItem(config_ssl1.create_list_item("disablecaverification1")); + list->addItem(config_ssl2.create_list_item("disablecaverification2")); + list->addItem(config_ssl3.create_list_item("disablecaverification3")); + frame->setContent(list); return frame; } @@ -129,7 +133,6 @@ class GuiToggle final : public tsl::Gui { ConfigEntry config_noacidsigchk2{"fs", "noacidsigchk2", true}; ConfigEntry config_noncasigchk_old{"fs", "noncasigchk_old", true}; ConfigEntry config_noncasigchk_new{"fs", "noncasigchk_new", true}; - ConfigEntry config_noncasigchk_new2{"fs", "noncasigchk_new2", true}; ConfigEntry config_nocntchk{"fs", "nocntchk", true}; ConfigEntry config_nocntchk2{"fs", "nocntchk2", true}; ConfigEntry config_noacidsigchk{"ldr", "noacidsigchk", true}; @@ -138,6 +141,9 @@ class GuiToggle final : public tsl::Gui { ConfigEntry config_es3{"es", "es3", true}; ConfigEntry config_ctest{"nifm", "ctest", true}; ConfigEntry config_nim{"nim", "nim", true}; + ConfigEntry config_ssl1{"ssl", "disablecaverification1", false}; + ConfigEntry config_ssl2{"ssl", "disablecaverification2", false}; + ConfigEntry config_ssl3{"ssl", "disablecaverification3", false}; }; class GuiLog final : public tsl::Gui { diff --git a/sysmod/src/main.cpp b/sysmod/src/main.cpp index cce3ae3..521f6ba 100644 --- a/sysmod/src/main.cpp +++ b/sysmod/src/main.cpp @@ -141,7 +141,8 @@ constexpr auto subr_cond(u32 inst) -> bool { } constexpr auto bl_cond(u32 inst) -> bool { - return ((inst >> 26) & 0x3F) == 0x25; + const auto type = inst >> 24; + return type == 0x25 || type == 0x94; } constexpr auto tbz_cond(u32 inst) -> bool { @@ -169,6 +170,10 @@ constexpr auto mov2_cond(u32 inst) -> bool { } } +constexpr auto mov_cond3(u32 inst) -> bool { + return (inst >> 24) == 0xD2; // mov x10, #0x3 +} + constexpr auto and_cond(u32 inst) -> bool { return ((inst >> 24) & 0x1F) == 0x0A; } @@ -183,6 +188,14 @@ constexpr auto bne_cond(u32 inst) -> bool { return type == 0x54 || cond == 0x0; } +constexpr auto beq_cond(u32 inst) -> bool { + return (inst >> 24) == 0x54; // beq, 0x710011c94c +} + +constexpr auto str_cond(u32 inst) -> bool { + return (inst >> 24) == 0xB9; // str, w8,[x19, #0x15c] +} + constexpr auto ctest_cond(u32 inst) -> bool { return std::byteswap(0xF50301AA) == inst; // mov x21, x1 } @@ -195,6 +208,8 @@ constexpr PatchData nop_patch_data{ "0x1F2003D5" }; constexpr PatchData mov0_patch_data{ "0xE0031FAA" }; //mov x2, xzr constexpr PatchData mov2_patch_data{ "0xE2031FAA" }; +constexpr PatchData ssl1_patch_data{ "0x0A" }; +constexpr PatchData ssl2_patch_data{ "0x08008052" }; constexpr PatchData ctest_patch_data{ "0x00309AD2001EA1F2610100D4E0031FAAC0035FD6" }; constexpr auto ret0_patch(u32 inst) -> PatchData { return ret0_patch_data; } @@ -203,6 +218,8 @@ constexpr auto nop_patch(u32 inst) -> PatchData { return nop_patch_data; } constexpr auto subs_patch(u32 inst) -> PatchData { return subi_cond(inst) ? (u8)0x1 : (u8)0x0; } constexpr auto mov0_patch(u32 inst) -> PatchData { return mov0_patch_data; } constexpr auto mov2_patch(u32 inst) -> PatchData { return mov2_patch_data; } +constexpr auto ssl1_patch(u32 inst) -> PatchData { return ssl1_patch_data; } +constexpr auto ssl2_patch(u32 inst) -> PatchData { return ssl2_patch_data; } constexpr auto ctest_patch(u32 inst) -> PatchData { return ctest_patch_data; } constexpr auto b_patch(u32 inst) -> PatchData { @@ -243,6 +260,14 @@ constexpr auto mov2_applied(const u8* data, u32 inst) -> bool { return mov2_patch(inst).cmp(data); } +constexpr auto ssl1_applied(const u8* data, u32 inst) -> bool { + return ssl1_patch(inst).cmp(data); +} + +constexpr auto ssl2_applied(const u8* data, u32 inst) -> bool { + return ssl2_patch(inst).cmp(data); +} + constexpr auto ctest_applied(const u8* data, u32 inst) -> bool { return ctest_patch(inst).cmp(data); } @@ -250,15 +275,14 @@ constexpr auto ctest_applied(const u8* data, u32 inst) -> bool { constinit Patterns fs_patterns[] = { { "noacidsigchk1", "0xC8FE4739", -24, 0, bl_cond, ret0_patch, ret0_applied, true, FW_VER_ANY, MAKEHOSVERSION(9,2,0) }, { "noacidsigchk2", "0x0210911F000072", -5, 0, bl_cond, ret0_patch, ret0_applied, true, FW_VER_ANY, MAKEHOSVERSION(9,2,0) }, - { "noncasigchk_old", "0x1E42B9", -5, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(10,0,0), MAKEHOSVERSION(14,2,1) }, - { "noncasigchk_new", "0x3E4479", -5, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(15,0,0), MAKEHOSVERSION(16,1,0) }, - { "noncasigchk_new2", "0x258052", -5, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(17,0,0), FW_VER_ANY }, - { "nocntchk", "0x081C00121F050071..0054", -4, 0, bl_cond, ret0_patch, ret0_applied, true, MAKEHOSVERSION(10,0,0), MAKEHOSVERSION(18,1,0) }, - { "nocntchk2", "0x091C00123F05007161010054", -8, 0, bl_cond, ret0_patch, ret0_applied, true, MAKEHOSVERSION(19,0,0), FW_VER_ANY }, + { "noncasigchk_old", "0x0036.......71..0054..4839", -2, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(10,0,0), MAKEHOSVERSION(16,1,0) }, + { "noncasigchk_new", "0x.94..0036.258052", 2, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(17,0,0), FW_VER_ANY }, // 17.0.0 - 19.0.0+ + { "nocntchk", "0x40f9...9408.0012.050071", 2, 0, bl_cond, ret0_patch, ret0_applied, true, MAKEHOSVERSION(10,0,0), MAKEHOSVERSION(18,1,0) }, + { "nocntchk2", "0x40f9...94..40b9..0012", 2, 0, bl_cond, ret0_patch, ret0_applied, true, MAKEHOSVERSION(19,0,0), FW_VER_ANY }, }; constinit Patterns ldr_patterns[] = { - { "noacidsigchk", "0xFD7B.A8C0035FD6", 16, 2, subs_cond, subs_patch, subs_applied, true, FW_VER_ANY }, + { "noacidsigchk", "0xFD7B.A8C0035FD6", 16, 2, subs_cond, subs_patch, subs_applied, true, FW_VER_ANY }, }; constinit Patterns es_patterns[] = { @@ -273,7 +297,12 @@ constinit Patterns nifm_patterns[] = { constinit Patterns nim_patterns[] = { { "nim", "0x.0F00351F2003D5", 8, 0, adr_cond, mov2_patch, mov2_applied, true, MAKEHOSVERSION(17,0,0), FW_VER_ANY }, - // { "nim2", "0x600F00351F2003D5", 8, 0, adr_cond, mov2_patch, mov2_applied, true, MAKEHOSVERSION(19,0,0), FW_VER_ANY }, +}; + +constinit Patterns ssl_patterns[] = { + { "disablecaverification1", "0x6A0080D2", 0, 0, mov_cond3, ssl1_patch, ssl1_applied, false, FW_VER_ANY }, + { "disablecaverification2", "0x2409437AA0000054", 4, 0, beq_cond, ret1_patch, ret1_applied, false, FW_VER_ANY }, + { "disablecaverification3", "0x88160012", 4, 0, str_cond, ssl2_patch, ssl2_applied, false, FW_VER_ANY }, }; // NOTE: add system titles that you want to be patched to this table. @@ -286,6 +315,7 @@ constinit PatchEntry patches[] = { { "es", 0x0100000000000033, es_patterns, MAKEHOSVERSION(2,0,0) }, { "nifm", 0x010000000000000F, nifm_patterns }, { "nim", 0x0100000000000025, nim_patterns }, + { "ssl", 0x0100000000000024, ssl_patterns }, }; struct EmummcPaths { From 589e3abbb33c93e6ead49efcf17db78e5f57df1b Mon Sep 17 00:00:00 2001 From: shadow2560 <24191064+shadow2560@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:45:28 +0100 Subject: [PATCH 2/4] Fix when pattern can be in between 2 READ_BUFFER_SIZE boundries Signed-off-by: shadow2560 <24191064+shadow2560@users.noreply.github.com> --- sysmod/src/main.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/sysmod/src/main.cpp b/sysmod/src/main.cpp index 521f6ba..6452a97 100644 --- a/sysmod/src/main.cpp +++ b/sysmod/src/main.cpp @@ -410,7 +410,8 @@ auto apply_patch(PatchEntry& patch) -> bool { u64 pids[0x50]{}; s32 process_count{}; - static u8 buffer[READ_BUFFER_SIZE]; + constexpr u64 overlap_size = 0x4f; + static u8 buffer[READ_BUFFER_SIZE + overlap_size]; // skip if version isn't valid if (VERSION_SKIP && @@ -449,16 +450,27 @@ auto apply_patch(PatchEntry& patch) -> bool { continue; } - // todo: the byte pattern can in between 2 READ_BUFFER_SIZE boundries! - for (u64 sz = 0; sz < mem_info.size; sz += READ_BUFFER_SIZE) { - const auto actual_size = std::min(READ_BUFFER_SIZE, mem_info.size); - if (R_FAILED(svcReadDebugProcessMemory(buffer, handle, mem_info.addr + sz, actual_size))) { - // todo: log failed reads! + // u32 overlap_size = 0; + // for (const auto& pattern : patch.patterns) { + // overlap_size = std::max(overlap_size, static_cast(pattern.byte_pattern.size)); + // } + // u8* buffer = (u8*)aligned_alloc(alignof(u8*), READ_BUFFER_SIZE + overlap_size); + // if (!buffer) { + // svcCloseHandle(handle); + // return false; + // } + for (u64 sz = 0; sz < mem_info.size; sz += READ_BUFFER_SIZE - overlap_size) { + const auto actual_size = std::min(READ_BUFFER_SIZE, mem_info.size - sz); + if (R_FAILED(svcReadDebugProcessMemory(buffer + overlap_size, handle, mem_info.addr + sz, actual_size))) { break; } else { - patcher(handle, std::span{buffer, actual_size}, mem_info.addr + sz, patch.patterns); + patcher(handle, std::span{buffer, actual_size + overlap_size}, mem_info.addr + sz - overlap_size, patch.patterns); + if (actual_size >= overlap_size) { + memcpy(buffer, buffer + actual_size, overlap_size); + } } } + // free(buffer); } svcCloseHandle(handle); return true; From 5842b3c96c9a377e9915d32ffa1e717b29a8d2bc Mon Sep 17 00:00:00 2001 From: shadow2560 <24191064+shadow2560@users.noreply.github.com> Date: Tue, 3 Dec 2024 13:48:28 +0100 Subject: [PATCH 3/4] mov_cond3 function renamed to mov3_cond Signed-off-by: shadow2560 <24191064+shadow2560@users.noreply.github.com> --- sysmod/src/main.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sysmod/src/main.cpp b/sysmod/src/main.cpp index 6452a97..005b2fd 100644 --- a/sysmod/src/main.cpp +++ b/sysmod/src/main.cpp @@ -170,7 +170,7 @@ constexpr auto mov2_cond(u32 inst) -> bool { } } -constexpr auto mov_cond3(u32 inst) -> bool { +constexpr auto mov3_cond(u32 inst) -> bool { return (inst >> 24) == 0xD2; // mov x10, #0x3 } @@ -300,7 +300,7 @@ constinit Patterns nim_patterns[] = { }; constinit Patterns ssl_patterns[] = { - { "disablecaverification1", "0x6A0080D2", 0, 0, mov_cond3, ssl1_patch, ssl1_applied, false, FW_VER_ANY }, + { "disablecaverification1", "0x6A0080D2", 0, 0, mov3_cond, ssl1_patch, ssl1_applied, false, FW_VER_ANY }, { "disablecaverification2", "0x2409437AA0000054", 4, 0, beq_cond, ret1_patch, ret1_applied, false, FW_VER_ANY }, { "disablecaverification3", "0x88160012", 4, 0, str_cond, ssl2_patch, ssl2_applied, false, FW_VER_ANY }, }; From e86f4711f74a4146a2a6d2c7afdc0b3087bd047a Mon Sep 17 00:00:00 2001 From: borntohonk <6264306+borntohonk@users.noreply.github.com> Date: Wed, 4 Dec 2024 14:23:26 +0100 Subject: [PATCH 4/4] Set version 1.5.5 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 40c7fc0..46276e5 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ MAKEFILES := sysmod overlay TARGETS := $(foreach dir,$(MAKEFILES),$(CURDIR)/$(dir)) # the below was taken from atmosphere + switch-examples makefile -export VERSION := 1.5.6 +export VERSION := 1.5.5 ifneq ($(strip $(shell git symbolic-ref --short HEAD 2>/dev/null)),) export GIT_BRANCH := $(shell git symbolic-ref --short HEAD)