Skip to content

Commit 32c7757

Browse files
authored
Merge pull request #9 from borntohonk/master
Contains BL cond fix, buffer change, ca_verification patches, workflow change Combination of some PR and addition of SSL patches.
2 parents 3de2853 + e86f471 commit 32c7757

7 files changed

Lines changed: 114 additions & 95 deletions

File tree

.github/workflows/build-jobs.yaml

Lines changed: 43 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -2,24 +2,51 @@ name: Build jobs
22

33
on:
44
workflow_call:
5+
workflow_dispatch:
6+
push:
57

68
jobs:
79
build:
8-
name: build
910
runs-on: ubuntu-latest
10-
container: ghcr.io/pgalonza/devkita64-atmosphere:latest
11-
#or you can use a generic one
12-
#container: devkitpro/devkita64:latest
11+
container: devkitpro/devkita64
12+
1313
steps:
14-
- name: Checkout
15-
uses: actions/checkout@v4
16-
with:
17-
submodules: recursive
18-
- name: Build sys-patch
19-
run: |
20-
make dist -j $(nproc)
21-
- name: Upload artifacts
22-
uses: actions/upload-artifact@v4
23-
with:
24-
name: sys-patch-artifacts
25-
path: ./sys-patch.zip
14+
- name: Checkout
15+
uses: actions/checkout@v4
16+
with:
17+
fetch-tags: true
18+
path: sys-patch
19+
submodules: recursive
20+
21+
- name: Build sys-patch
22+
run: |
23+
make -C sys-patch -j$(nproc) dist && \
24+
VERSION=$(grep 'export VERSION := ' sys-patch/Makefile | cut -c 19-)
25+
TAGVERSION=$(curl -s https://api.github.com/repos/$GITHUB_REPOSITORY/releases/latest | grep "tag_name" | head -1 | cut -d '"' -f 4)
26+
echo "VERSION=${VERSION}" >> $GITHUB_ENV
27+
echo "TAGVERSION=${TAGVERSION}" >> $GITHUB_ENV
28+
29+
- name: Upload artifact
30+
uses: actions/upload-artifact@v4
31+
with:
32+
include-hidden-files: true
33+
overwrite: true
34+
name: sys-patch-${{ env.VERSION }}
35+
path: sys-patch/out/
36+
37+
- name: Fetch git cli and upload release
38+
env:
39+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
40+
run: |
41+
if [ ${{ env.TAGVERSION }} = v${{ env.VERSION }} ];
42+
then echo "Tag version and makefile version are same, don't publish release, only artifact uploaded."
43+
else
44+
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) && \
45+
tar -xzf gh*.tar.gz && \
46+
chmod +x gh*/bin/gh && \
47+
chmod +x gh*/bin/gh && \
48+
cp gh*/bin/gh /bin/gh && \
49+
rm gh*.tar.gz && \
50+
rm -rf gh*
51+
gh release create v${{ env.VERSION }} sys-patch/sys-patch.zip --title "Sys-patch version ${{ env.VERSION }}" --repo github.com/$GITHUB_REPOSITORY
52+
fi

.github/workflows/build.yml

Lines changed: 0 additions & 14 deletions
This file was deleted.

.github/workflows/release.yml

Lines changed: 0 additions & 38 deletions
This file was deleted.

Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ MAKEFILES := sysmod overlay
22
TARGETS := $(foreach dir,$(MAKEFILES),$(CURDIR)/$(dir))
33

44
# the below was taken from atmosphere + switch-examples makefile
5-
export VERSION := 1.5.4
5+
export VERSION := 1.5.5
66

77
ifneq ($(strip $(shell git symbolic-ref --short HEAD 2>/dev/null)),)
88
export GIT_BRANCH := $(shell git symbolic-ref --short HEAD)

README.md

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# sys-patch
22

3-
A script-like system module that patches **fs**, **es**, **ldr** and **nifm** on boot.
3+
A script-like system module that patches **fs**, **es**, **ldr**, **nifm** and **nim** on boot.
44

55
---
66

@@ -57,14 +57,10 @@ To activate the sys-module, reboot your switch, or, use [sysmodules overlay](htt
5757

5858
Here's a quick run down of what's being patched:
5959

60-
- **fs**
61-
- **es**
62-
- **ldr**
63-
- **nifm**
64-
65-
**fs** and **es** need new patches after every new firmware version.
66-
**ldr** needs new patches after every new [Atmosphere](https://github.com/Atmosphere-NX/Atmosphere/) release.
67-
**nifm** ctest patch allows the device to connect to a network without needing to make a connection to a server.
60+
- **fs** and **es** need new patches after every new firmware version.
61+
- **ldr** needs new patches after every new [Atmosphere](https://github.com/Atmosphere-NX/Atmosphere/) release.
62+
- **nifm** ctest patch allows the device to connect to a network without needing to make a connection to a server
63+
- **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.
6864

6965
The patches are applied on boot. Once done, the sys-module stops running.
7066
The memory footprint *(16kib)* and the binary size *(~50kib)* are both very small.

overlay/src/main.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,6 @@ class GuiToggle final : public tsl::Gui {
103103
list->addItem(config_noacidsigchk2.create_list_item("noacidsigchk2"));
104104
list->addItem(config_noncasigchk_old.create_list_item("noncasigchk_old"));
105105
list->addItem(config_noncasigchk_new.create_list_item("noncasigchk_new"));
106-
list->addItem(config_noncasigchk_new2.create_list_item("noncasigchk_new2"));
107106
list->addItem(config_nocntchk.create_list_item("nocntchk"));
108107
list->addItem(config_nocntchk2.create_list_item("nocntchk2"));
109108

@@ -121,6 +120,11 @@ class GuiToggle final : public tsl::Gui {
121120
list->addItem(new tsl::elm::CategoryHeader("NIM - 0100000000000025"));
122121
list->addItem(config_nim.create_list_item("nim"));
123122

123+
list->addItem(new tsl::elm::CategoryHeader("Disable CA Verification - apply all"));
124+
list->addItem(config_ssl1.create_list_item("disablecaverification1"));
125+
list->addItem(config_ssl2.create_list_item("disablecaverification2"));
126+
list->addItem(config_ssl3.create_list_item("disablecaverification3"));
127+
124128
frame->setContent(list);
125129
return frame;
126130
}
@@ -129,7 +133,6 @@ class GuiToggle final : public tsl::Gui {
129133
ConfigEntry config_noacidsigchk2{"fs", "noacidsigchk2", true};
130134
ConfigEntry config_noncasigchk_old{"fs", "noncasigchk_old", true};
131135
ConfigEntry config_noncasigchk_new{"fs", "noncasigchk_new", true};
132-
ConfigEntry config_noncasigchk_new2{"fs", "noncasigchk_new2", true};
133136
ConfigEntry config_nocntchk{"fs", "nocntchk", true};
134137
ConfigEntry config_nocntchk2{"fs", "nocntchk2", true};
135138
ConfigEntry config_noacidsigchk{"ldr", "noacidsigchk", true};
@@ -138,6 +141,9 @@ class GuiToggle final : public tsl::Gui {
138141
ConfigEntry config_es3{"es", "es3", true};
139142
ConfigEntry config_ctest{"nifm", "ctest", true};
140143
ConfigEntry config_nim{"nim", "nim", true};
144+
ConfigEntry config_ssl1{"ssl", "disablecaverification1", false};
145+
ConfigEntry config_ssl2{"ssl", "disablecaverification2", false};
146+
ConfigEntry config_ssl3{"ssl", "disablecaverification3", false};
141147
};
142148

143149
class GuiLog final : public tsl::Gui {

sysmod/src/main.cpp

Lines changed: 57 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ constexpr auto subr_cond(u32 inst) -> bool {
141141
}
142142

143143
constexpr auto bl_cond(u32 inst) -> bool {
144-
return ((inst >> 26) & 0x3F) == 0x25;
144+
const auto type = inst >> 24;
145+
return type == 0x25 || type == 0x94;
145146
}
146147

147148
constexpr auto tbz_cond(u32 inst) -> bool {
@@ -169,6 +170,10 @@ constexpr auto mov2_cond(u32 inst) -> bool {
169170
}
170171
}
171172

173+
constexpr auto mov3_cond(u32 inst) -> bool {
174+
return (inst >> 24) == 0xD2; // mov x10, #0x3
175+
}
176+
172177
constexpr auto and_cond(u32 inst) -> bool {
173178
return ((inst >> 24) & 0x1F) == 0x0A;
174179
}
@@ -183,6 +188,14 @@ constexpr auto bne_cond(u32 inst) -> bool {
183188
return type == 0x54 || cond == 0x0;
184189
}
185190

191+
constexpr auto beq_cond(u32 inst) -> bool {
192+
return (inst >> 24) == 0x54; // beq, 0x710011c94c
193+
}
194+
195+
constexpr auto str_cond(u32 inst) -> bool {
196+
return (inst >> 24) == 0xB9; // str, w8,[x19, #0x15c]
197+
}
198+
186199
constexpr auto ctest_cond(u32 inst) -> bool {
187200
return std::byteswap(0xF50301AA) == inst; // mov x21, x1
188201
}
@@ -195,6 +208,8 @@ constexpr PatchData nop_patch_data{ "0x1F2003D5" };
195208
constexpr PatchData mov0_patch_data{ "0xE0031FAA" };
196209
//mov x2, xzr
197210
constexpr PatchData mov2_patch_data{ "0xE2031FAA" };
211+
constexpr PatchData ssl1_patch_data{ "0x0A" };
212+
constexpr PatchData ssl2_patch_data{ "0x08008052" };
198213
constexpr PatchData ctest_patch_data{ "0x00309AD2001EA1F2610100D4E0031FAAC0035FD6" };
199214

200215
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; }
203218
constexpr auto subs_patch(u32 inst) -> PatchData { return subi_cond(inst) ? (u8)0x1 : (u8)0x0; }
204219
constexpr auto mov0_patch(u32 inst) -> PatchData { return mov0_patch_data; }
205220
constexpr auto mov2_patch(u32 inst) -> PatchData { return mov2_patch_data; }
221+
constexpr auto ssl1_patch(u32 inst) -> PatchData { return ssl1_patch_data; }
222+
constexpr auto ssl2_patch(u32 inst) -> PatchData { return ssl2_patch_data; }
206223
constexpr auto ctest_patch(u32 inst) -> PatchData { return ctest_patch_data; }
207224

208225
constexpr auto b_patch(u32 inst) -> PatchData {
@@ -243,22 +260,29 @@ constexpr auto mov2_applied(const u8* data, u32 inst) -> bool {
243260
return mov2_patch(inst).cmp(data);
244261
}
245262

263+
constexpr auto ssl1_applied(const u8* data, u32 inst) -> bool {
264+
return ssl1_patch(inst).cmp(data);
265+
}
266+
267+
constexpr auto ssl2_applied(const u8* data, u32 inst) -> bool {
268+
return ssl2_patch(inst).cmp(data);
269+
}
270+
246271
constexpr auto ctest_applied(const u8* data, u32 inst) -> bool {
247272
return ctest_patch(inst).cmp(data);
248273
}
249274

250275
constinit Patterns fs_patterns[] = {
251276
{ "noacidsigchk1", "0xC8FE4739", -24, 0, bl_cond, ret0_patch, ret0_applied, true, FW_VER_ANY, MAKEHOSVERSION(9,2,0) },
252277
{ "noacidsigchk2", "0x0210911F000072", -5, 0, bl_cond, ret0_patch, ret0_applied, true, FW_VER_ANY, MAKEHOSVERSION(9,2,0) },
253-
{ "noncasigchk_old", "0x1E42B9", -5, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(10,0,0), MAKEHOSVERSION(14,2,1) },
254-
{ "noncasigchk_new", "0x3E4479", -5, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(15,0,0), MAKEHOSVERSION(16,1,0) },
255-
{ "noncasigchk_new2", "0x258052", -5, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(17,0,0), FW_VER_ANY },
256-
{ "nocntchk", "0x081C00121F050071..0054", -4, 0, bl_cond, ret0_patch, ret0_applied, true, MAKEHOSVERSION(10,0,0), MAKEHOSVERSION(18,1,0) },
257-
{ "nocntchk2", "0x091C00123F05007161010054", -8, 0, bl_cond, ret0_patch, ret0_applied, true, MAKEHOSVERSION(19,0,0), FW_VER_ANY },
278+
{ "noncasigchk_old", "0x0036.......71..0054..4839", -2, 0, tbz_cond, nop_patch, nop_applied, true, MAKEHOSVERSION(10,0,0), MAKEHOSVERSION(16,1,0) },
279+
{ "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+
280+
{ "nocntchk", "0x40f9...9408.0012.050071", 2, 0, bl_cond, ret0_patch, ret0_applied, true, MAKEHOSVERSION(10,0,0), MAKEHOSVERSION(18,1,0) },
281+
{ "nocntchk2", "0x40f9...94..40b9..0012", 2, 0, bl_cond, ret0_patch, ret0_applied, true, MAKEHOSVERSION(19,0,0), FW_VER_ANY },
258282
};
259283

260284
constinit Patterns ldr_patterns[] = {
261-
{ "noacidsigchk", "0xFD7B.A8C0035FD6", 16, 2, subs_cond, subs_patch, subs_applied, true, FW_VER_ANY },
285+
{ "noacidsigchk", "0xFD7B.A8C0035FD6", 16, 2, subs_cond, subs_patch, subs_applied, true, FW_VER_ANY },
262286
};
263287

264288
constinit Patterns es_patterns[] = {
@@ -273,7 +297,12 @@ constinit Patterns nifm_patterns[] = {
273297

274298
constinit Patterns nim_patterns[] = {
275299
{ "nim", "0x.0F00351F2003D5", 8, 0, adr_cond, mov2_patch, mov2_applied, true, MAKEHOSVERSION(17,0,0), FW_VER_ANY },
276-
// { "nim2", "0x600F00351F2003D5", 8, 0, adr_cond, mov2_patch, mov2_applied, true, MAKEHOSVERSION(19,0,0), FW_VER_ANY },
300+
};
301+
302+
constinit Patterns ssl_patterns[] = {
303+
{ "disablecaverification1", "0x6A0080D2", 0, 0, mov3_cond, ssl1_patch, ssl1_applied, false, FW_VER_ANY },
304+
{ "disablecaverification2", "0x2409437AA0000054", 4, 0, beq_cond, ret1_patch, ret1_applied, false, FW_VER_ANY },
305+
{ "disablecaverification3", "0x88160012", 4, 0, str_cond, ssl2_patch, ssl2_applied, false, FW_VER_ANY },
277306
};
278307

279308
// NOTE: add system titles that you want to be patched to this table.
@@ -286,6 +315,7 @@ constinit PatchEntry patches[] = {
286315
{ "es", 0x0100000000000033, es_patterns, MAKEHOSVERSION(2,0,0) },
287316
{ "nifm", 0x010000000000000F, nifm_patterns },
288317
{ "nim", 0x0100000000000025, nim_patterns },
318+
{ "ssl", 0x0100000000000024, ssl_patterns },
289319
};
290320

291321
struct EmummcPaths {
@@ -380,7 +410,8 @@ auto apply_patch(PatchEntry& patch) -> bool {
380410

381411
u64 pids[0x50]{};
382412
s32 process_count{};
383-
static u8 buffer[READ_BUFFER_SIZE];
413+
constexpr u64 overlap_size = 0x4f;
414+
static u8 buffer[READ_BUFFER_SIZE + overlap_size];
384415

385416
// skip if version isn't valid
386417
if (VERSION_SKIP &&
@@ -419,16 +450,27 @@ auto apply_patch(PatchEntry& patch) -> bool {
419450
continue;
420451
}
421452

422-
// todo: the byte pattern can in between 2 READ_BUFFER_SIZE boundries!
423-
for (u64 sz = 0; sz < mem_info.size; sz += READ_BUFFER_SIZE) {
424-
const auto actual_size = std::min(READ_BUFFER_SIZE, mem_info.size);
425-
if (R_FAILED(svcReadDebugProcessMemory(buffer, handle, mem_info.addr + sz, actual_size))) {
426-
// todo: log failed reads!
453+
// u32 overlap_size = 0;
454+
// for (const auto& pattern : patch.patterns) {
455+
// overlap_size = std::max(overlap_size, static_cast<u32>(pattern.byte_pattern.size));
456+
// }
457+
// u8* buffer = (u8*)aligned_alloc(alignof(u8*), READ_BUFFER_SIZE + overlap_size);
458+
// if (!buffer) {
459+
// svcCloseHandle(handle);
460+
// return false;
461+
// }
462+
for (u64 sz = 0; sz < mem_info.size; sz += READ_BUFFER_SIZE - overlap_size) {
463+
const auto actual_size = std::min(READ_BUFFER_SIZE, mem_info.size - sz);
464+
if (R_FAILED(svcReadDebugProcessMemory(buffer + overlap_size, handle, mem_info.addr + sz, actual_size))) {
427465
break;
428466
} else {
429-
patcher(handle, std::span{buffer, actual_size}, mem_info.addr + sz, patch.patterns);
467+
patcher(handle, std::span{buffer, actual_size + overlap_size}, mem_info.addr + sz - overlap_size, patch.patterns);
468+
if (actual_size >= overlap_size) {
469+
memcpy(buffer, buffer + actual_size, overlap_size);
470+
}
430471
}
431472
}
473+
// free(buffer);
432474
}
433475
svcCloseHandle(handle);
434476
return true;

0 commit comments

Comments
 (0)