From 046b3d002334d14c7d20c50829c6c3945bf8e007 Mon Sep 17 00:00:00 2001 From: Tau Date: Thu, 28 Mar 2019 13:31:27 -0400 Subject: [PATCH] wip --- src/idz/decoder.ts | 17 +++++--- src/idz/defs.ts | 3 ++ src/idz/encoder.ts | 104 ++++++++++++++++++++------------------------ src/idz/index.ts | 2 +- src/idz/request.ts | 25 +++++++++++ src/idz/response.ts | 54 +++++++++++++++++++++++ src/idz/setup.ts | 15 ++++++- 7 files changed, 154 insertions(+), 66 deletions(-) create mode 100644 src/idz/request.ts create mode 100644 src/idz/response.ts diff --git a/src/idz/decoder.ts b/src/idz/decoder.ts index 9f40143..b9ac043 100644 --- a/src/idz/decoder.ts +++ b/src/idz/decoder.ts @@ -1,24 +1,27 @@ import { Transform } from "stream"; import { MSG, MSG_LEN } from "./defs"; +import { Request } from "./request"; -const readers = new Map(); +type ReaderFn = (buf: Buffer) => Request; -function readHeader(buf) { +const readers = new Map(); + +function readHeader(buf: Buffer) { return { blah: "blah", }; } -readers.set(MSG.GET_CONFIG_DATA_REQ, buf => { +readers.set(MSG.GET_CONFIG_DATA_REQ, () => { return { type: "get_config_data_req" }; }); -readers.set(MSG.GET_CONFIG_DATA_2_REQ, buf => { +readers.set(MSG.GET_CONFIG_DATA_2_REQ, () => { return { type: "get_config_data_2_req" }; }); -readers.set(MSG.GET_SERVER_LIST_REQ, buf => { +readers.set(MSG.GET_SERVER_LIST_REQ, () => { return { type: "get_server_list_req" }; }); @@ -34,7 +37,7 @@ export class Decoder extends Transform { this.state = Buffer.alloc(0); } - _transform(chunk, encoding, callback) { + _transform(chunk: Buffer, encoding, callback) { this.state = Buffer.concat([this.state, chunk]); // Read header @@ -86,6 +89,6 @@ export class Decoder extends Transform { console.log("Idz: Header:", header); console.log("Idz: Payload:", payload); - return callback(null, { header, payload }); + return callback(null, payload); } } diff --git a/src/idz/defs.ts b/src/idz/defs.ts index 8ffb65a..0bea8a9 100644 --- a/src/idz/defs.ts +++ b/src/idz/defs.ts @@ -3,6 +3,8 @@ export const MSG = { GET_CONFIG_DATA_RES: 0x0005, GET_SERVER_LIST_REQ: 0x0006, GET_SERVER_LIST_RES: 0x0007, + ACT_LOCK_REQ: 0x0069, + ACT_LOCK_RES: 0x006a, GET_CONFIG_DATA_2_REQ: 0x00ab, GET_CONFIG_DATA_2_RES: 0x00ac, }; @@ -11,4 +13,5 @@ export const MSG_LEN = new Map(); MSG_LEN.set(MSG.GET_CONFIG_DATA_REQ, 0x0050); MSG_LEN.set(MSG.GET_CONFIG_DATA_2_REQ, 0x0010); +MSG_LEN.set(MSG.ACT_LOCK_REQ, 0x001c); MSG_LEN.set(MSG.GET_SERVER_LIST_REQ, 0x0020); diff --git a/src/idz/encoder.ts b/src/idz/encoder.ts index 6233840..b949ad2 100644 --- a/src/idz/encoder.ts +++ b/src/idz/encoder.ts @@ -1,56 +1,7 @@ import { Transform } from "stream"; import { MSG } from "./defs"; - -const writers = new Map Buffer>(); - -writers.set("get_config_data_res", obj => { - const buf = Buffer.alloc(0x01a0); - - buf.writeUInt16LE(MSG.GET_CONFIG_DATA_RES, 0x0000); - buf.writeUInt16LE(obj.status, 0x0002); - - return buf; -}); - -writers.set("get_config_data_2_res", obj => { - const buf = Buffer.alloc(0x230); - - buf.writeUInt16LE(MSG.GET_CONFIG_DATA_2_RES, 0x0000); - buf.writeUInt16LE(obj.status, 0x0002); - - return buf; -}); - -writers.set("get_server_list_res", obj => { - const buf = Buffer.alloc(0x04b0); - - buf.writeUInt16LE(MSG.GET_SERVER_LIST_RES, 0x0000); - buf.writeUInt16LE(obj.status, 0x0002); - buf.write(obj.userDb.addr, 0x0004); - buf.writeUInt16LE(obj.userDb.tcp, 0x0084); - buf.writeUInt16LE(obj.userDb.http, 0x0086); - buf.write(obj.matchAddr, 0x0088); - buf.writeUInt16LE(obj.matchPort.tcp, 0x0108); - buf.writeUInt16LE(obj.matchPort.udpSend, 0x010a); - buf.writeUInt16LE(obj.matchPort.udpRecv, 0x010c); - buf.writeUInt16LE(obj.tagMatchPort.tcp, 0x010e); - buf.writeUInt16LE(obj.tagMatchPort.udpSend, 0x0110); - buf.writeUInt16LE(obj.tagMatchPort.udpRecv, 0x0112); - buf.write(obj.event.addr, 0x0114); - buf.writeUInt16LE(obj.event.tcp, 0x0194); - buf.write(obj.screenshot.addr, 0x0198); - buf.writeUInt16LE(obj.screenshot.tcp, 0x0218); - buf.write(obj.pingReturn, 0x021c); - buf.write(obj.echo1.addr, 0x029c); - buf.write(obj.echo2.addr, 0x031c); - buf.writeUInt16LE(obj.echo1.udp, 0x39c); - buf.writeUInt16LE(obj.echo2.udp, 0x39e); - buf.write(obj.newsUrl, 0x03a0); - buf.write(obj.reportErrorUrl, 0x0424); - - return buf; -}); +import { Response } from "./response"; export class Encoder extends Transform { constructor() { @@ -60,17 +11,58 @@ export class Encoder extends Transform { }); } - _transform(obj, encoding, callback) { + _transform(obj: Response, encoding, callback) { console.log("Idz: Response:", obj); - const writer = writers.get(obj.type); + let buf: Buffer; - if (writer === undefined) { - return callback(new Error(`No writer for type ${obj.type}`)); + switch (obj.type) { + case "get_config_data_res": + buf = Buffer.alloc(0x01a0); + buf.writeUInt16LE(MSG.GET_CONFIG_DATA_RES, 0x0000); + buf.writeUInt16LE(obj.status, 0x0002); + + break; + + case "get_config_data_2_res": + buf = Buffer.alloc(0x230); + buf.writeUInt16LE(MSG.GET_CONFIG_DATA_2_RES, 0x0000); + buf.writeUInt16LE(obj.status, 0x0002); + + break; + + case "get_server_list_res": + buf = Buffer.alloc(0x04b0); + buf.writeUInt16LE(MSG.GET_SERVER_LIST_RES, 0x0000); + buf.writeUInt16LE(obj.status, 0x0002); + buf.write(obj.userDb.addr, 0x0004); + buf.writeUInt16LE(obj.userDb.tcp, 0x0084); + buf.writeUInt16LE(obj.userDb.http, 0x0086); + buf.write(obj.matchAddr, 0x0088); + buf.writeUInt16LE(obj.matchPort.tcp, 0x0108); + buf.writeUInt16LE(obj.matchPort.udpSend, 0x010a); + buf.writeUInt16LE(obj.matchPort.udpRecv, 0x010c); + buf.writeUInt16LE(obj.tagMatchPort.tcp, 0x010e); + buf.writeUInt16LE(obj.tagMatchPort.udpSend, 0x0110); + buf.writeUInt16LE(obj.tagMatchPort.udpRecv, 0x0112); + buf.write(obj.event.addr, 0x0114); + buf.writeUInt16LE(obj.event.tcp, 0x0194); + buf.write(obj.screenshot.addr, 0x0198); + buf.writeUInt16LE(obj.screenshot.tcp, 0x0218); + buf.write(obj.pingReturn, 0x021c); + buf.write(obj.echo1.addr, 0x029c); + buf.write(obj.echo2.addr, 0x031c); + buf.writeUInt16LE(obj.echo1.udp, 0x39c); + buf.writeUInt16LE(obj.echo2.udp, 0x39e); + buf.write(obj.newsUrl, 0x03a0); + buf.write(obj.reportErrorUrl, 0x0424); + + break; + + default: + return callback(new Error(`No writer fn for ${obj["type"]}`)); } - const buf = writer(obj); - return callback(null, buf); } } diff --git a/src/idz/index.ts b/src/idz/index.ts index ca3d2fa..5fa49a7 100644 --- a/src/idz/index.ts +++ b/src/idz/index.ts @@ -9,7 +9,7 @@ export default async function idz(socket) { try { for await (const msg of input) { - switch (msg.payload.type) { + switch (msg.type) { case "get_server_list_req": const myHost = hostname(); diff --git a/src/idz/request.ts b/src/idz/request.ts new file mode 100644 index 0000000..33c57dc --- /dev/null +++ b/src/idz/request.ts @@ -0,0 +1,25 @@ +export interface AccountLockRequest { + type: "account_lock_req"; + field_0002: number; + field_0004: number; + field_0008: Buffer; + field_0018: number; +} + +export interface GetConfigDataRequest { + type: "get_config_data_req"; +} + +export interface GetConfigDataRequest2 { + type: "get_config_data_2_req"; +} + +export interface GetServerListRequest { + type: "get_server_list_req"; +} + +export type Request = + | AccountLockRequest + | GetConfigDataRequest + | GetConfigDataRequest2 + | GetServerListRequest; diff --git a/src/idz/response.ts b/src/idz/response.ts new file mode 100644 index 0000000..ec97704 --- /dev/null +++ b/src/idz/response.ts @@ -0,0 +1,54 @@ +export interface GetConfigDataResponse { + type: "get_config_data_res"; + status: number; +} + +export interface GetConfigDataResponse2 { + type: "get_config_data_2_res"; + status: number; +} + +export interface GetServerListResponse { + type: "get_server_list_res"; + status: number; + userDb: { + addr: string; + tcp: number; + http: number; + }; + matchAddr: string; + matchPort: { + tcp: number; + udpSend: number; + udpRecv: number; + }; + tagMatchPort: { + tcp: number; + udpSend: number; + udpRecv: number; + }; + event: { + addr: string; + tcp: number; + }; + screenshot: { + addr: string; + tcp: number; + }; + pingReturn: string; + echo1: { + addr: string; + udp: number; + }; + echo2: { + addr: string; + udp: number; + }; + newsUrl: string; + reportErrorUrl: string; +} + +export type Response = + | GetConfigDataResponse + | GetConfigDataResponse2 + | GetServerListResponse; diff --git a/src/idz/setup.ts b/src/idz/setup.ts index b21143a..f1f8628 100644 --- a/src/idz/setup.ts +++ b/src/idz/setup.ts @@ -5,8 +5,12 @@ import { pipeline } from "stream"; import { byteString, modPow } from "./bigint"; import { Decoder } from "./decoder"; import { Encoder } from "./encoder"; +import { Request } from "./request"; +import { Response } from "./response"; + +// Proof-of-concept, so we only ever use one of the ten RSA key pairs +// (SEGA shipped their central server private keys for god knows what reason) -// Proof-of-concept, so we only ever use one of the ten RSA keys const key = { N: 4922323266120814292574970172377860734034664704992758249880018618131907367614177800329506877981986877921220485681998287752778495334541127048495486311792061n, d: 1163847742215766215216916151663017691387519688859977157498780867776436010396072628219119707788340687440419444081289736279466637153082223960965411473296473n, @@ -25,7 +29,14 @@ console.log("RSA ENC :", byteString(test1, 0x40).toString("hex")); console.log("RSA ENCDEC :", byteString(test2, 0x40).toString("hex")); // -- TEST -- -export default function setup(socket: Socket) { +interface Session { + input: AsyncIterable; + output: { + write: (res: Response) => void; + }; +} + +export default function setup(socket: Socket): Session { // // Construct and transmit setup message //