-
Notifications
You must be signed in to change notification settings - Fork 3
/
main.go
168 lines (138 loc) · 4.5 KB
/
main.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
package main
import (
"errors"
"fmt"
"github.com/logrusorgru/aurora/v3"
"github.com/wii-tools/GoNUSD"
"github.com/wii-tools/arclib"
"github.com/wii-tools/powerpc"
"github.com/wii-tools/wadlib"
"io/fs"
"io/ioutil"
"log"
"os"
)
// baseDomain holds our needed base domain.
var baseDomain string
// mainDol holds the main DOL - our content at index 1.
var mainDol []byte
// mainArc holds the main ARC - our content at index 2.
var mainArc *arclib.ARC
// rootCertificate holds the public certificate, in DER form, to be patched in.
var rootCertificate []byte
// filePresent returns whether the specified path is present on disk.
func filePresent(path string) bool {
_, err := os.Stat(path)
return errors.Is(err, fs.ErrNotExist) == false
}
// createDir creates a directory at the given path if it is not already present.
func createDir(path string) {
if !filePresent(path) {
os.Mkdir(path, 0755)
}
}
func main() {
if len(os.Args) != 2 {
fmt.Printf("Usage: %s <base domain>\n", os.Args[0])
fmt.Println("For more information, please refer to the README.")
os.Exit(-1)
}
baseDomain = os.Args[1]
if len(baseDomain) > 12 {
fmt.Println("The given base domain must not exceed 12 characters.")
fmt.Println("For more information, please refer to the README.")
os.Exit(-1)
}
fmt.Println("===========================")
fmt.Println("= WSC-Patcher =")
fmt.Println("===========================")
// Create directories we may need later.
createDir("./output")
createDir("./cache")
var err error
// Determine whether the Wii Shop Channel is cached.
if !filePresent("./cache/original.wad") {
log.Println("Downloading a copy of the original Wii Shop Channel, please wait...")
var downloadedShop *wadlib.WAD
downloadedShop, err = GoNUSD.Download(0x00010002_48414241, 21, true)
check(err)
// Cache this downloaded WAD to disk.
var contents []byte
contents, err = downloadedShop.GetWAD(wadlib.WADTypeCommon)
check(err)
os.WriteFile("./cache/original.wad", contents, 0755)
}
var originalWad *wadlib.WAD
originalWad, err = wadlib.LoadWADFromFile("./cache/original.wad")
check(err)
// Determine whether a certificate authority was provided, or generated previously.
if !filePresent("./output/root.cer") {
fmt.Println(aurora.Green("Generating root certificates..."))
rootCertificate = createCertificates()
} else {
rootCertificate, err = ioutil.ReadFile("./output/root.cer")
check(err)
}
// Ensure the loaded certificate has a suitable length.
// It must not be longer than 928 bytes.
if len(rootCertificate) > 928 {
fmt.Println("The passed root certificate exceeds the maximum length possible, 928 bytes.")
fmt.Println("Please verify parameters passed for generation and reduce its size.")
os.Exit(-1)
}
// Load main DOL
mainDol, err = originalWad.GetContent(1)
check(err)
// Permit r/w access to MEM2_PROT via the TMD.
// See docs/patch_overwrite_ios.md for more information!
originalWad.TMD.AccessRightsFlags = 0x3
// Apply all DOL patches
fmt.Println(aurora.Green("Applying DOL patches..."))
applyDefaultPatches()
// Save main DOL
err = originalWad.UpdateContent(1, mainDol)
check(err)
// Load main ARC
arcData, err := originalWad.GetContent(2)
check(err)
mainArc, err = arclib.Load(arcData)
check(err)
// Generate filter list and certificate store
fmt.Println(aurora.Green("Applying Opera patches..."))
modifyAllowList()
generateOperaCertStore()
// Save main ARC
updated, err := mainArc.Save()
check(err)
err = originalWad.UpdateContent(2, updated)
check(err)
// Generate a patched WAD with our changes
output, err := originalWad.GetWAD(wadlib.WADTypeCommon)
check(err)
fmt.Println(aurora.Green("Done! Install ./output/patched.wad, sit back, and enjoy."))
writeOut("patched.wad", output)
}
// applyDefaultPatches applies the default patches to our main DOL.
func applyDefaultPatches() {
var err error
mainDol, err = powerpc.ApplyPatchSet(OverwriteIOSPatch, mainDol)
check(err)
mainDol, err = powerpc.ApplyPatchSet(LoadCustomCA(), mainDol)
check(err)
mainDol, err = powerpc.ApplyPatchSet(PatchBaseDomain(), mainDol)
check(err)
mainDol, err = powerpc.ApplyPatchSet(NegateECTitle, mainDol)
check(err)
mainDol, err = powerpc.ApplyPatchSet(PatchECCfgPath, mainDol)
check(err)
}
// check has an anxiety attack if things go awry.
func check(err error) {
if err != nil {
panic(err)
}
}
// writeOut writes a file with the given name and contents to the output folder.
func writeOut(filename string, contents []byte) {
os.WriteFile("./output/"+filename, contents, 0755)
}