mirror of
https://github.com/redstrate/Kawari.git
synced 2025-06-08 17:37:46 +00:00
Begin decrypting packets, add IPC segment type
This commit is contained in:
parent
21419aa09c
commit
cdc250fca1
2 changed files with 61 additions and 10 deletions
|
@ -1,4 +1,4 @@
|
||||||
use kawari::packet::parse_packet;
|
use kawari::packet::{parse_packet, State};
|
||||||
use tokio::io::AsyncReadExt;
|
use tokio::io::AsyncReadExt;
|
||||||
use tokio::net::TcpListener;
|
use tokio::net::TcpListener;
|
||||||
|
|
||||||
|
@ -14,13 +14,15 @@ async fn main() {
|
||||||
let (socket, _) = listener.accept().await.unwrap();
|
let (socket, _) = listener.accept().await.unwrap();
|
||||||
let (mut read, mut write) = tokio::io::split(socket);
|
let (mut read, mut write) = tokio::io::split(socket);
|
||||||
|
|
||||||
|
let mut state = State { client_key: None };
|
||||||
|
|
||||||
tokio::spawn(async move {
|
tokio::spawn(async move {
|
||||||
let mut buf = [0; 2056];
|
let mut buf = [0; 2056];
|
||||||
loop {
|
loop {
|
||||||
let n = read.read(&mut buf).await.expect("Failed to read data!");
|
let n = read.read(&mut buf).await.expect("Failed to read data!");
|
||||||
|
|
||||||
if n != 0 {
|
if n != 0 {
|
||||||
parse_packet(&mut write, &buf[..n]).await;
|
parse_packet(&mut write, &buf[..n], &mut state).await;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{fs::write, io::Cursor, time::{SystemTime, UNIX_EPOCH}};
|
use std::{fs::write, io::Cursor, time::{SystemTime, UNIX_EPOCH}};
|
||||||
|
|
||||||
use binrw::{binrw, helpers::until_eof, BinRead, BinWrite};
|
use binrw::{binrw, helpers::until_eof, BinRead, BinResult, BinWrite};
|
||||||
use physis::blowfish::Blowfish;
|
use physis::blowfish::Blowfish;
|
||||||
use tokio::{io::{AsyncWriteExt, WriteHalf}, net::TcpStream};
|
use tokio::{io::{AsyncWriteExt, WriteHalf}, net::TcpStream};
|
||||||
|
|
||||||
|
@ -29,7 +29,37 @@ enum ConnectionType {
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
|
struct IPCSegment {
|
||||||
|
unk: u32
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binrw::parser(reader, endian)]
|
||||||
|
pub(crate) fn decrypt<T>(size: u32, encryption_key: Option<&[u8]>) -> BinResult<T>
|
||||||
|
where
|
||||||
|
for<'a> T: BinRead<Args<'a> = ()> + 'a
|
||||||
|
{
|
||||||
|
let Some(encryption_key) = encryption_key else {
|
||||||
|
panic!("This segment type is encrypted and no key was provided!");
|
||||||
|
};
|
||||||
|
|
||||||
|
let size = size - 16; // 16 = header size
|
||||||
|
|
||||||
|
let mut data = Vec::new();
|
||||||
|
data.resize(size as usize, 0x0);
|
||||||
|
reader.read_exact(&mut data)?;
|
||||||
|
|
||||||
|
let blowfish = Blowfish::new(encryption_key);
|
||||||
|
let decrypted_data = blowfish.decrypt(&data).unwrap();
|
||||||
|
|
||||||
|
let mut cursor = Cursor::new(&decrypted_data);
|
||||||
|
T::read_options(&mut cursor, endian, ())
|
||||||
|
}
|
||||||
|
|
||||||
|
#[binrw]
|
||||||
|
#[br(import(size: u32, encryption_key: Option<&[u8]>))]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
enum SegmentType {
|
enum SegmentType {
|
||||||
|
// Client->Server Packets
|
||||||
#[brw(magic = 0x9u32)]
|
#[brw(magic = 0x9u32)]
|
||||||
InitializeEncryption {
|
InitializeEncryption {
|
||||||
#[brw(pad_before = 36)] // empty
|
#[brw(pad_before = 36)] // empty
|
||||||
|
@ -41,11 +71,19 @@ enum SegmentType {
|
||||||
#[brw(pad_after = 512)] // empty
|
#[brw(pad_after = 512)] // empty
|
||||||
key: [u8; 4],
|
key: [u8; 4],
|
||||||
},
|
},
|
||||||
|
#[brw(magic = 0x3u32)]
|
||||||
|
IPC {
|
||||||
|
#[br(parse_with = decrypt, args(size, encryption_key))]
|
||||||
|
#[bw(ignore)]
|
||||||
|
data: IPCSegment,
|
||||||
|
},
|
||||||
|
|
||||||
|
// Server->Client Packets
|
||||||
#[brw(magic = 0x0Au32)]
|
#[brw(magic = 0x0Au32)]
|
||||||
InitializationEncryptionResponse {
|
InitializationEncryptionResponse {
|
||||||
#[br(count = 0x280)]
|
#[br(count = 0x280)]
|
||||||
data: Vec<u8>
|
data: Vec<u8>
|
||||||
}
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
|
@ -66,12 +104,14 @@ struct PacketHeader {
|
||||||
}
|
}
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
|
#[br(import(encryption_key: Option<&[u8]>))]
|
||||||
#[derive(Debug, Clone)]
|
#[derive(Debug, Clone)]
|
||||||
struct PacketSegment {
|
struct PacketSegment {
|
||||||
#[bw(calc = self.calc_size())]
|
#[bw(calc = self.calc_size())]
|
||||||
size: u32,
|
size: u32,
|
||||||
source_actor: u32,
|
source_actor: u32,
|
||||||
target_actor: u32,
|
target_actor: u32,
|
||||||
|
#[br(args(size, encryption_key))]
|
||||||
segment_type: SegmentType,
|
segment_type: SegmentType,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,15 +121,17 @@ impl PacketSegment {
|
||||||
return header as u32 + match &self.segment_type {
|
return header as u32 + match &self.segment_type {
|
||||||
SegmentType::InitializeEncryption { .. } => 616,
|
SegmentType::InitializeEncryption { .. } => 616,
|
||||||
SegmentType::InitializationEncryptionResponse { .. } => 640,
|
SegmentType::InitializationEncryptionResponse { .. } => 640,
|
||||||
|
SegmentType::IPC { .. } => todo!(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[binrw]
|
#[binrw]
|
||||||
|
#[br(import(encryption_key: Option<&[u8]>))]
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct Packet {
|
struct Packet {
|
||||||
header: PacketHeader,
|
header: PacketHeader,
|
||||||
#[br(count = header.segment_count)]
|
#[br(count = header.segment_count, args { inner: (encryption_key,) })]
|
||||||
segments: Vec<PacketSegment>,
|
segments: Vec<PacketSegment>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -143,11 +185,15 @@ async fn send_packet(socket: &mut WriteHalf<TcpStream>, segments: &[PacketSegmen
|
||||||
.expect("Failed to write packet!");
|
.expect("Failed to write packet!");
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn parse_packet(socket: &mut WriteHalf<TcpStream>, data: &[u8]) {
|
// temporary
|
||||||
|
pub struct State {
|
||||||
|
pub client_key: Option<[u8; 16]>
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn parse_packet(socket: &mut WriteHalf<TcpStream>, data: &[u8], state: &mut State) {
|
||||||
let mut cursor = Cursor::new(data);
|
let mut cursor = Cursor::new(data);
|
||||||
|
|
||||||
|
match Packet::read_le_args(&mut cursor, (state.client_key.as_ref().map(|s: &[u8; 16]| s.as_slice()),)) {
|
||||||
match Packet::read_le(&mut cursor) {
|
|
||||||
Ok(packet) => {
|
Ok(packet) => {
|
||||||
println!("{:#?}", packet);
|
println!("{:#?}", packet);
|
||||||
|
|
||||||
|
@ -162,9 +208,9 @@ pub async fn parse_packet(socket: &mut WriteHalf<TcpStream>, data: &[u8]) {
|
||||||
match &segment.segment_type {
|
match &segment.segment_type {
|
||||||
SegmentType::InitializeEncryption { phrase, key } => {
|
SegmentType::InitializeEncryption { phrase, key } => {
|
||||||
// Generate an encryption key for this client
|
// Generate an encryption key for this client
|
||||||
let client_key = generate_encryption_key(key, phrase);
|
state.client_key = Some(generate_encryption_key(key, phrase));
|
||||||
|
|
||||||
let blowfish = Blowfish::new(&client_key);
|
let blowfish = Blowfish::new(&state.client_key.unwrap());
|
||||||
let mut data = blowfish.encrypt(&0xE0003C2Au32.to_le_bytes()).unwrap();
|
let mut data = blowfish.encrypt(&0xE0003C2Au32.to_le_bytes()).unwrap();
|
||||||
data.resize(0x280, 0);
|
data.resize(0x280, 0);
|
||||||
|
|
||||||
|
@ -178,6 +224,9 @@ pub async fn parse_packet(socket: &mut WriteHalf<TcpStream>, data: &[u8]) {
|
||||||
send_packet(socket, &[response_packet]).await;
|
send_packet(socket, &[response_packet]).await;
|
||||||
},
|
},
|
||||||
SegmentType::InitializationEncryptionResponse { .. } => panic!("The server is recieving a response packet!"),
|
SegmentType::InitializationEncryptionResponse { .. } => panic!("The server is recieving a response packet!"),
|
||||||
|
SegmentType::IPC { .. } => {
|
||||||
|
// decrypt
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Reference in a new issue