Wave provides configurable MITM proxy to read and edit TCP packets from games.
- Hook packets by their ID
- Edit packets on-fly
- Prevent unnecessary packets from being sent
- Manually create and send custom packet
You can find full example on examples/proxy
Import the wave
package from GitHub in your code:
import "github.com/Dmitriy-Vas/wave"
Create remote and local addresses, they must implement net.Addr
interface.
localAddr, _ := net.ResolveTCPAddr("tcp", ":7999")
remoteAddr, _ := net.ResolveTCPAddr("tcp", "74.91.123.86:7000")
Create buffer, must implement wave.PacketBuffer
interface.
You can use default buffer, but I'd recommend create your own wrapper.
buf := &buffer.DefaultBuffer{
PacketReader: &buffer.DefaultReader{Order: binary.LittleEndian},
PacketWriter: &buffer.DefaultWriter{Order: binary.LittleEndian},
}
Create wave.Config
and fill with your parameters
config := wave.Config{
// First bytes of packet, means packet payload size
PacketLengthSize: wave.Size32Bits,
// Packet type usually goes right after payload size
PacketTypeSize: wave.Size8Bits,
// Sometimes PacketLengthSize may include self bytes, in this example it will be additional 32bits (4 bytes)
LengthIncludesSelf: false,
// Remote address of server, wave will connect to this address
RemoteAddress: remoteAddr,
// Local address, wave will listen for new connection on this address
LocalAddress: localAddr,
// If you want to establish connection to the remove server right after receiving local connection
ConnectImmediately: true,
// Implementation of wave.PacketBuffer
Buffer: buf,
// In current example packet is encrypted using RC4
// I want to decrypt on start (to read) and encrypt on end (to send)
OutgoingProcess: func(buffer buffer.PacketBuffer, start bool) {
raw, _ := hex.DecodeString("c79332b197f92ba85ed281a023")
cipher, _ := rc4.NewCipher(raw)
cipher.XORKeyStream(buffer.Bytes()[5:], buffer.Bytes()[5:])
},
IncomingProcess: func(buffer buffer.PacketBuffer, start bool) {
raw, _ := hex.DecodeString("6a39570cc9de4ec71d64821894")
cipher, _ := rc4.NewCipher(raw)
cipher.XORKeyStream(buffer.Bytes()[5:], buffer.Bytes()[5:])
},
}
Create new wave.Proxy
instance
proxy := wave.New(config)
If you want to edit packets, you must create packet structure and register to wave.Proxy
.
Check lib/packets for examples.
// 1 is packet ID
// true means this packet is outgoing (from client to server)
// last parameter is a pointer to the empty packet, must implement wave.Packet interface
proxy.AddPacket(1, true, (*outgoing.NewAccountPacket)(nil))
To actually edit packet, register your hook and do magic
proxy.HookPacket(int64(lib.IncReceiveHour), false, func(conn *wave.Conn, packet wave.Packet) {
receiveHourPacket := packet.(*incoming.ReceiveHourPacket)
log.Printf("Changing hour from %d to 12", receiveHourPacket.Hour)
receiveHourPacket.Hour = 12
})
- DarkStory Online
- Traffic is not encrypted.
- Boolean takes 1 extra bytes (2 in total) and uses int16.
- Byte takes 1 extra byte (2 in total) and uses int16.
- Length goes in first 8 bytes and uses int64.
- After length goes packet ID and uses int64.
- Most part of packets were added and ready for use.
!!!Need help with typos!!!
If you want to contribute, fork this project, commit changes and create pull request.
Please describe your changes and what they are doing in pull request.