-
Notifications
You must be signed in to change notification settings - Fork 17
Expand file tree
/
Copy pathwwfcSecurity.cpp
More file actions
172 lines (144 loc) · 5.21 KB
/
wwfcSecurity.cpp
File metadata and controls
172 lines (144 loc) · 5.21 KB
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
169
170
171
172
#include "mkwSecurity.hpp"
#include "wwfcLog.hpp"
#include "wwfcPatch.hpp"
namespace wwfc::Security
{
#if ADDRESS_DWCi_GetGPBuddyAdditionalMsg
// SERVER TO CLIENT VULNERABILITY
// CVE-ID: CVE-2023-45887
// https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-45887
WWFC_DEFINE_PATCH = Patch::CallWithCTR(
WWFC_PATCH_LEVEL_CRITICAL, //
ADDRESS_DWCi_GetGPBuddyAdditionalMsg + 0x90, //
ASM_LAMBDA(
(),
// clang-format off
cmplwi r31, 0xF; // The destination buffer is of size 0x10; leave room for the null terminator
mflr r9;
mr r5, r31;
mr r4, r28;
mr r3, r27;
ble+ L_ValidLength;
addi r9, r9, -0x1C; // return -1
mtctr r9;
bctr;
L_ValidLength:
b memcpy;
// clang-format on
)
);
#endif
// SERVER|CLIENT TO CLIENT VULNERABILITY
// Match command stack buffer overflow. This exists in nearly every Wii game.
#if ADDRESS_PATCH_SECURITY_GT2MATCHCOMMAND
// CLIENT TO CLIENT VULNERABILITY
// The peer to peer match command exploit
WWFC_DEFINE_PATCH = Patch::CallWithCTR(
WWFC_PATCH_LEVEL_CRITICAL, //
ADDRESS_PATCH_SECURITY_GT2MATCHCOMMAND - 0x24, // 0x800E591C
ASM_LAMBDA(
(),
// clang-format off
lbz r5, 0x11(r1);
addi r0, r5, 0x14;
cmplw r31, r0;
bnelr-; // Error "Got wrong data size GT2 command."
// Check the maximum length to prevent a buffer overflow
cmplwi r5, 0x80;
bgtlr-; // Error "Got wrong data size GT2 command."
// OK, jump to the copy routine
mflr r12;
addi r12, r12, 0x14;
mtctr r12;
bctr;
// clang-format on
)
);
#endif
#if ADDRESS_PATCH_SECURITY_QR2MATCHCOMMAND
// SERVER TO CLIENT VULNERABILITY
// The QR2/MASTER server-sent match command exploit
WWFC_DEFINE_PATCH = Patch::CallWithCTR(
WWFC_PATCH_LEVEL_CRITICAL, //
ADDRESS_PATCH_SECURITY_QR2MATCHCOMMAND, // 0x800E5AC8
ASM_LAMBDA(
(),
// clang-format off
lbz r5, 0x11(r1);
// Check the maximum length to prevent a buffer overflow
cmplwi r5, 0x80;
bgt- L%=SBCommandError;
// OK, copy the data to the stack
addi r3, r1, 0x1C;
addi r4, r28, 0x14;
// Call and return
b memcpy@local;
L%=SBCommandError:;
// Jump to "Got different version SBcommand." error
mflr r12;
subi r12, r12, 0x24;
mtctr r12;
bctr;
// clang-format on
)
);
#endif
#if RMC || RMCN
// SERVER TO CLIENT VULNERABILITY
// Patch for Mario Kart Wii friend status (locstring) stack buffer overflow.
// Located in DWC_GetFriendStatusData, this one is a bit annoying because it
// could exist in other games, it just depends on the size the caller is
// expecting.
WWFC_DEFINE_PATCH = Patch::WriteASM(
WWFC_PATCH_LEVEL_CRITICAL, //
RMCXD_PORT(0x800CE220, 0x800CE180, 0x800CE140, 0x800CE280, DEMOTODO) // Disc
RMCXN_PORT(0x800B5D98, 0x800B5D08, 0x800B5CE8, 0x800B5E08), // Channel
1, ASM_LAMBDA((), li r6, 0x10)
);
#endif
#if RMC
// CLIENT TO CLIENT VULNERABILITY
// Patch for the Mario Kart Wii Race packet exploit. This was the first RCE
// exploit discovered in a Wii game. Originally discovered by XeR, but then
// rediscovered by Star, who reported the exploit and then released it.
// CVE-ID: CVE-2023-35856
// https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2023-35856
WWFC_DEFINE_PATCH = Patch::BranchWithCTR( //
WWFC_PATCH_LEVEL_CRITICAL, //
RMCXD_PORT(0x80658604, 0x8065417C, 0x80657C70, 0x8064691C, DEMOTODO), //
[](mkw::Net::NetController* netController, mkw::Net::RacePacket* racePacket,
u32 packetSize, u32 _, u8 playerAid) -> void {
if (packetSize < sizeof(mkw::Net::RacePacket)) {
WWFC_LOG_WARN_FMT(
"Invalid Race packet from aid %u (insufficient size)", playerAid
);
netController->reportAndKick("wl:bad_packet", playerAid);
GPReport::ReportB64Encode("wl:bad_packet_data", racePacket, packetSize);
return;
}
[[gnu::longcall]] u32 NETCalcCRC32( //
const void* data, u32 size
) AT(RMCXD_PORT(0x801D1CA0, 0x801D1C00, 0x801D1BC0, 0x801D1FFC, DEMOTODO));
u32 savedChecksum = racePacket->checksum;
racePacket->checksum = 0;
u32 realChecksum = NETCalcCRC32(racePacket, packetSize);
racePacket->checksum = savedChecksum;
if (realChecksum != savedChecksum) {
WWFC_LOG_WARN_FMT(
"Invalid Race packet from aid %u (checksum mismatch)", playerAid
);
return;
}
if (!mkw::Security::IsRacePacketValid(racePacket, packetSize, playerAid)) {
WWFC_LOG_WARN_FMT(
"Invalid Race packet from aid %u (malicious packet)", playerAid
);
netController->reportAndKick("wl:bad_packet", playerAid);
GPReport::ReportB64Encode("wl:bad_packet_data", racePacket, packetSize);
return;
}
netController->processRacePacket(playerAid, racePacket, packetSize);
}
);
#endif
} // namespace wwfc::Security