diff --git a/.gitignore b/.gitignore index 9594106..3560f25 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,6 @@ # Local configuration file config.xml +salt.bin # Payload data payload diff --git a/nas/payload.go b/nas/payload.go index 911616b..bc1939b 100644 --- a/nas/payload.go +++ b/nas/payload.go @@ -10,11 +10,11 @@ import ( "encoding/hex" "encoding/pem" "github.com/logrusorgru/aurora/v3" - "log" "net/http" "net/url" "os" "strconv" + "wwfc/logging" ) func getStage1(r *Response, fields map[string]string) map[string]string { @@ -27,56 +27,85 @@ func getStage1(r *Response, fields map[string]string) map[string]string { return map[string]string{} } -func handlePayloadRequest(w http.ResponseWriter, r *http.Request) { +func handlePayloadRequest(moduleName string, w http.ResponseWriter, r *http.Request) { // Example request: // GET /payload?g=RMCPD00&s=4e44b095817f8cfb62e6cffd57e9cfd411004a492784039ea4b2b7ca64717c91&h=9fdb6f60 u, err := url.Parse(r.URL.String()) if err != nil { - log.Printf(aurora.Red("failed to parse URL").String()) + logging.Error(moduleName, "Failed to parse URL") return } query, err := url.ParseQuery(u.RawQuery) if err != nil { - log.Printf(aurora.Red("failed to parse URL query").String()) + logging.Error(moduleName, "Failed to parse URL query") return } - // TODO: Read payload ID (g) from URL - dat, err := os.ReadFile("payload/binary/RMCPD00.bin") + // Read payload ID (g) from URL + game := query["g"][0] + if len(game) != 7 && len(game) != 9 { + logging.Error(moduleName, "Invalid or missing game ID:", aurora.Cyan(game)) + return + } + + if (len(game) == 7 && game[4] != 'D') || (len(game) == 9 && game[4] != 'N') { + logging.Error(moduleName, "Invalid game ID:", aurora.Cyan(game)) + return + } + + for i := 0; i < 4; i++ { + if (game[i] >= 'A' && game[i] <= 'Z') || (game[i] >= '0' && game[i] <= '9') { + continue + } + + logging.Error(moduleName, "Invalid game ID char:", aurora.Cyan(game)) + return + } + + for i := 5; i < len(game); i++ { + if (game[i] >= '0' && game[i] <= '9') || (game[i] >= 'a' && game[i] <= 'f') { + continue + } + + logging.Error(moduleName, "Invalid game ID version:", aurora.Cyan(game)) + return + } + + dat, err := os.ReadFile("payload/binary/payload." + game + ".bin") if err != nil { - log.Printf(aurora.Red("failed to read payload file").String()) + logging.Error(moduleName, "Failed to read payload file") return } salt, ok := query["s"] if ok { if len(salt[0]) != 64 { - log.Printf(aurora.Red("invalid salt length").String()) + logging.Error(moduleName, "Invalid salt length:", aurora.BrightCyan(len(salt[0]))) return } _, err := hex.DecodeString(salt[0]) if err != nil { - log.Printf(aurora.Red("invalid salt hex string").String()) + logging.Error(moduleName, "Invalid salt hex string") return } saltHashTest, ok := query["h"] if !ok { - log.Printf(aurora.Red("Request is missing salt hash").String()) + logging.Error(moduleName, "Request is missing salt hash") return } if len(saltHashTest[0]) != 8 { - log.Printf(aurora.Red("Invalid salt hash length").String()) + logging.Error(moduleName, "Invalid salt hash length:", aurora.BrightCyan(len(saltHashTest[0]))) return } saltHashTestData, err := hex.DecodeString(saltHashTest[0]) if err != nil { - log.Printf(aurora.Red("Invalid salt hash hex string").String()) + logging.Error(moduleName, "Invalid salt hash hex string") return } @@ -91,7 +120,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) { saltHash := hashCtx.Sum(nil) if !bytes.Equal(saltHashTestData, saltHash[:4]) { - log.Printf(aurora.Red("Invalid salt hash").String()) + logging.Error(moduleName, "Salt hash mismatch") return } @@ -100,7 +129,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) { // TODO: Cache the request for a zero salt - rsaData, err := os.ReadFile("payload/stage1-private-temp.pem") + rsaData, err := os.ReadFile("payload/private-key.pem") if err != nil { panic(err) } @@ -113,7 +142,7 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) { rsaKey, ok := parsedKey.(*rsa.PrivateKey) if !ok { - log.Fatalf("got unexpected key type: %T", parsedKey) + panic("Unexpected key type") } // Hash our data then sign @@ -133,7 +162,6 @@ func handlePayloadRequest(w http.ResponseWriter, r *http.Request) { dat = append(append(dat[:0x10], signature...), dat[0x110:]...) - log.Printf(aurora.White("write data").String()) w.Header().Set("Content-Length", strconv.Itoa(len(dat))) w.Write(dat) } diff --git a/nas/route.go b/nas/route.go index 44a178b..1a3a3bf 100644 --- a/nas/route.go +++ b/nas/route.go @@ -69,7 +69,7 @@ func (route *Route) Handle() http.Handler { // TODO: Move this to its own server // Check for /payload if strings.HasPrefix(r.URL.String(), "/payload") { - handlePayloadRequest(w, r) + handlePayloadRequest(moduleName, w, r) return }