mirror of
https://github.com/PretendoNetwork/nex-go.git
synced 2025-04-02 11:02:14 -04:00
145 lines
No EOL
4.1 KiB
Markdown
145 lines
No EOL
4.1 KiB
Markdown
# NEX related libraries to make NEX servers in Go
|
|
|
|
[](https://godoc.org/github.com/PretendoNetwork/nex-go)
|
|
|
|
## How to install and use
|
|
|
|
### Install
|
|
|
|
`go get https://github.com/PretendoNetwork/nex-go`
|
|
|
|
### Usage
|
|
|
|
```Golang
|
|
package main
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
NEX "https://github.com/PretendoNetwork/nex-go"
|
|
)
|
|
|
|
// Bare-bones example of the structure of the Friends service AUTH server for the WiiU/3DS
|
|
|
|
/*
|
|
THIS IS VERY ROUGH EXAMPLE, USING TECHNIQUES THAT SHOULD NOT BE USED
|
|
NO REAL AUTHENTICATION OR CHECKS ARE GOING ON, THIS EXAMPLE JUST
|
|
BRUTE-FORCES THE USER THROUGH AUTHENTICATION.
|
|
*/
|
|
|
|
func main() {
|
|
|
|
settings := NEX.NewSettings()
|
|
|
|
settings.PrudpVersion = 0
|
|
settings.PrudpV0SignatureVersion = 1
|
|
settings.KerberosKeySize = 16
|
|
settings.AccessKey = "ridfebb9"
|
|
|
|
fmt.Println("STARTING FRIENDS AUTH SERVER")
|
|
|
|
Server := NEX.NewServer(settings)
|
|
|
|
Server.On("Packet", func(Client *NEX.Client, Packet *NEX.Packet) {
|
|
// Acknowledge every packet if it needs it. If it makes it this far, it's good
|
|
if Packet.HasFlag(NEX.Flags["NeedAck"]) {
|
|
Server.Acknowledge(Packet)
|
|
}
|
|
})
|
|
|
|
Server.On("Data", func(Client *NEX.Client, Packet *NEX.Packet) {
|
|
stream := NEX.NewInputStream(Packet.RMCRequest.Parameters)
|
|
response := NEX.NewRMCResponse(0x0A, Packet.RMCRequest.Header.CallID)
|
|
responseStream := NEX.NewOutputStream()
|
|
|
|
ResponsePacket := NEX.NewPacket(Client)
|
|
|
|
ResponsePacket.SetVersion(0)
|
|
ResponsePacket.SetSource(Packet.Destination)
|
|
ResponsePacket.SetDestination(Packet.Source)
|
|
ResponsePacket.SetType(NEX.Types["Data"])
|
|
|
|
pid := 1234567890 // account PID/NEX username (dummy)
|
|
password := "nex_password" // account NEX password (dummy)
|
|
|
|
key := []byte(password)
|
|
|
|
for i := 0; i < 65000+pid%1024; i++ {
|
|
key = NEX.MD5Hash(key)
|
|
}
|
|
|
|
Kerberos := NEX.NewKerberos(string(key))
|
|
|
|
// Checking the Method ID in this way is generally bad.
|
|
// A better way would be to track each protocol and have a reference to it's methods stored by their ID,
|
|
// and dynamically getting the handler
|
|
if Packet.RMCRequest.Header.MethodID == 2 { // 0x0A::0x02 (LoginEx)
|
|
_ = stream.String() // username
|
|
_ = stream.DataHolder() // login data
|
|
|
|
Kerberos := NEX.NewKerberos(string(key))
|
|
str := "test string test" // dummy data
|
|
|
|
kerberosData := Kerberos.Encrypt([]byte(str))
|
|
|
|
JSONBuffer := []byte(`{
|
|
"stream": "10",
|
|
"type": "2",
|
|
"PID": "2",
|
|
"port": "60001",
|
|
"address": "127.0.0.1",
|
|
"sid": "1",
|
|
"CID": "1"
|
|
}`)
|
|
|
|
var JSON map[string]string
|
|
_ = json.Unmarshal(JSONBuffer, &JSON)
|
|
|
|
station := NEX.NewStationURL("prudps", JSON)
|
|
|
|
name := "branch:origin/feature/45925_FixAutoReconnect build:3_10_11_2006_0" // official server
|
|
|
|
responseStream.UInt32LE(uint32(0x00010001)) // success
|
|
responseStream.UInt32LE(uint32(pid))
|
|
responseStream.Buffer(kerberosData)
|
|
|
|
responseStream.String(station) // Station URL (normal)
|
|
responseStream.UInt32LE(uint32(0)) // Special protocols (unused)
|
|
responseStream.String("") // Station URL (special) (unused)
|
|
|
|
responseStream.String(name)
|
|
|
|
response.SetSuccess(uint32(2), responseStream.Bytes())
|
|
|
|
ResponsePacket.SetPayload(response.Bytes())
|
|
} else if Packet.RMCRequest.Header.MethodID == 3 { // 0x0A::0x03 (RequestTicket)
|
|
str := "test string test test string tes" // dummy data
|
|
|
|
_ = stream.UInt32LE() // User PID
|
|
_ = stream.UInt32LE() // Server PID?
|
|
|
|
responseStream.UInt32LE(uint32(0x00010001)) // success
|
|
|
|
kerberosStream := NEX.NewOutputStream()
|
|
|
|
kerberosStream.Write([]byte("I like chickens.")) // Kerberos key (dummy)
|
|
kerberosStream.UInt32LE(uint32(0xFFFFFFFF)) // Unknown PID
|
|
kerberosStream.Buffer([]byte(str)) // Kerberos data
|
|
|
|
kerberosData := Kerberos.Encrypt(kerberosStream.Bytes())
|
|
|
|
responseStream.Buffer(kerberosData)
|
|
|
|
response.SetSuccess(uint32(3), responseStream.Bytes())
|
|
|
|
} else {
|
|
panic("INVALID PROTOCOL METHOD ID " + string(Packet.RMCRequest.Header.MethodID))
|
|
}
|
|
|
|
ResponsePacket.SetPayload(response.Bytes())
|
|
Server.Send(Client, &ResponsePacket)
|
|
})
|
|
|
|
Server.Listen(":60000")
|
|
}
|
|
``` |