Skip to content

Commit

Permalink
client packet crypto and checksum
Browse files Browse the repository at this point in the history
  • Loading branch information
shnok committed Jun 30, 2024
1 parent 7aaafa6 commit 84cc88f
Show file tree
Hide file tree
Showing 15 changed files with 289 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,17 @@ public class AsynchronousClient {
private ClientPacketHandler _clientPacketHandler;
private ServerPacketHandler _serverPacketHandler;
private DefaultClient _client;


private bool _cryptEnabled = false;
private bool _initPacket = true;
private RSACrypt _rsa;
private byte[] _blowfishKey;
private BlowfishEngine _decryptBlowfish;
private BlowfishEngine _encryptBlowfish;
public bool InitPacket { get { return _initPacket; } set { _initPacket = value; } }

public RSACrypt RSACrypt { get { return _rsa; } }
public BlowfishEngine DecryptBlowFish { get { return _decryptBlowfish; } }
public BlowfishEngine EncryptBlowFish { get { return _encryptBlowfish; } }
public byte[] BlowfishKey { get { return _blowfishKey; } }

public bool InitPacket { get { return _initPacket; } set { _initPacket = value; } }
public bool CryptEnabled {
get { return _cryptEnabled; }
set {
Debug.Log("Crypt" + (value ? " enabled." : " disabled."));
_cryptEnabled = value;
}
}
public int Ping { get; set; }

public AsynchronousClient(string ip, int port, DefaultClient client, ClientPacketHandler clientPacketHandler,
Expand All @@ -42,28 +39,10 @@ public AsynchronousClient(string ip, int port, DefaultClient client, ClientPacke
_initPacket = enableInitPacket;
}

public void SetBlowFishKey(byte[] blowfishKey) {
_blowfishKey = blowfishKey;

_decryptBlowfish = new BlowfishEngine();
_decryptBlowfish.init(false, blowfishKey);

_encryptBlowfish = new BlowfishEngine();
_encryptBlowfish.init(true, blowfishKey);

Debug.Log("Blowfish key set.");
}

public void SetRSAKey(byte[] rsaKey) {
_rsa = new RSACrypt(rsaKey, true);
Debug.Log("RSA Key set.");
}

public bool Connect() {
IPHostEntry ipHostInfo = Dns.GetHostEntry(_ipAddress);
IPAddress ipAddress = ipHostInfo.AddressList[0];
_socket = new Socket(ipAddress.AddressFamily, SocketType.Stream, ProtocolType.Tcp);

_initPacket = true;

Debug.Log("Connecting...");
Expand Down Expand Up @@ -92,6 +71,8 @@ public void Disconnect() {
return;
}

Debug.Log("Disconnect");

try {
_serverPacketHandler.CancelTokens();
_connected = false;
Expand Down
118 changes: 118 additions & 0 deletions l2-unity/Assets/Scripts/Networking/ClientLibrary/Crypto/GameCrypt.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace L2_login {
/// <summary>
/// Summary description for Crypt.
/// </summary>
public class GameCrypt {
private byte[] _key = new byte[16];//8];

public GameCrypt() {
}

public void setKey(byte[] key) {
_key[0] = key[0];
_key[1] = key[1];
_key[2] = key[2];
_key[3] = key[3];
_key[4] = key[4];
_key[5] = key[5];
_key[6] = key[6];
_key[7] = key[7];
_key[8] = key[8];
_key[9] = key[9];
_key[10] = key[10];
_key[11] = key[11];
_key[12] = key[12];
_key[13] = key[13];
_key[14] = key[14];
_key[15] = key[15];
}

public void decrypt(byte[] raw) {
uint temp = 0;
for (int i = 0; i < raw.Length; i++) {
uint temp2 = raw[i] & (uint)0xff;
raw[i] = (byte)(temp2 ^ _key[i & 15] ^ temp);
temp = temp2;
}

uint old = _key[8] & (uint)0xff;//0
old |= ((uint)_key[9]) << 8 & 0xff00;//1
old |= ((uint)_key[10]) << 0x10 & 0xff0000;//2
old |= ((uint)_key[11]) << 0x18 & 0xff000000;//3

old += (uint)raw.Length;

_key[8] = (byte)(old & 0xff);//0
_key[9] = (byte)(old >> 0x08 & 0xff);//1
_key[10] = (byte)(old >> 0x10 & 0xff);//2
_key[11] = (byte)(old >> 0x18 & 0xff);//3
}

public void decrypt(byte[] raw, uint size) {
uint temp = 0;
for (uint i = 0; i < size; i++) {
uint temp2 = raw[i] & (uint)0xff;
raw[i] = (byte)(temp2 ^ _key[i & 15] ^ temp);
temp = temp2;
}

uint old = _key[8] & (uint)0xff;//0
old |= ((uint)_key[9]) << 8 & 0xff00;//1
old |= ((uint)_key[10]) << 0x10 & 0xff0000;//2
old |= ((uint)_key[11]) << 0x18 & 0xff000000;//3

old += size;

_key[8] = (byte)(old & 0xff);//0
_key[9] = (byte)(old >> 0x08 & 0xff);//1
_key[10] = (byte)(old >> 0x10 & 0xff);//2
_key[11] = (byte)(old >> 0x18 & 0xff);//3
}

public void encrypt(byte[] raw) {
uint temp = 0;
for (int i = 0; i < raw.Length; i++) {
uint temp2 = raw[i] & (uint)0xff;
temp = temp2 ^ _key[i & 15] ^ temp;
raw[i] = (byte)temp;
}

uint old = _key[8] & (uint)0xff;
old |= ((uint)_key[9]) << 8 & 0xff00;
old |= ((uint)_key[10] << 0x10) & 0xff0000;
old |= ((uint)_key[11] << 0x18) & 0xff000000;

old += (uint)raw.Length;

_key[8] = (byte)(old & 0xff);
_key[9] = (byte)(old >> 0x08 & 0xff);
_key[10] = (byte)(old >> 0x10 & 0xff);
_key[11] = (byte)(old >> 0x18 & 0xff);
}

public void encrypt(byte[] raw, uint size) {
uint temp = 0;
for (uint i = 0; i < size; i++) {
uint temp2 = raw[i] & (uint)0xff;
temp = temp2 ^ _key[i & 15] ^ temp;
raw[i] = (byte)temp;
}

uint old = _key[8] & (uint)0xff;
old |= ((uint)_key[9]) << 8 & 0xff00;
old |= ((uint)_key[10] << 0x10) & 0xff0000;
old |= ((uint)_key[11] << 0x18) & 0xff000000;

old += size;

_key[8] = (byte)(old & 0xff);
_key[9] = (byte)(old >> 0x08 & 0xff);
_key[10] = (byte)(old >> 0x10 & 0xff);
_key[11] = (byte)(old >> 0x18 & 0xff);
}
}//end of class
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ private void Write(byte[] data) {
protected void BuildPacket() {
_buffer.Insert(0, _packetType);

// Padding for checksum
WriteI(0);

PadBuffer();

byte[] array = _buffer.ToArray();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class GameAuthRequestPacket : ClientPacket
{
public GameAuthRequestPacket(string account, int playKey1, int playKey2, int loginKey1, int loginKey2) : base((byte)GameClientPacketType.AuthRequest) {
WriteS(account);
WriteI(playKey1);
WriteI(playKey2);
WriteI(loginKey1);
WriteI(loginKey2);

BuildPacket();
}
}

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using L2_login;
using System.Collections;
using System.Collections.Generic;
using System.Threading;
Expand All @@ -13,14 +14,9 @@ public void SetClient(AsynchronousClient client) {

public abstract void SendPacket(ClientPacket packet);

protected void EncryptPacket(ClientPacket packet) {
protected virtual void EncryptPacket(ClientPacket packet) {
byte[] data = packet.GetData();
Debug.Log("CLEAR: " + StringUtils.ByteArrayToString(data));

_client.EncryptBlowFish.processBigBlock(data, 0, data, 0, data.Length);

Debug.Log("ENCRYPTED: " + StringUtils.ByteArrayToString(data));

packet.SetData(data);
NewCrypt.appendChecksum(data);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@

public class GameClientPacketHandler : ClientPacketHandler
{
protected override void EncryptPacket(ClientPacket packet) {
base.EncryptPacket(packet);

byte[] data = packet.GetData();

Debug.Log("CLEAR: " + StringUtils.ByteArrayToString(data));

GameClient.Instance.GameCrypt.encrypt(data);

Debug.Log("ENCRYPTED: " + StringUtils.ByteArrayToString(data));

packet.SetData(data);
}

public void SendPing() {
PingPacket packet = new PingPacket();
SendPacket(packet);
Expand All @@ -13,6 +27,15 @@ public void SendProtocolVersion() {
SendPacket(packet);
}

public void SendAuth() {
GameAuthRequestPacket authPacket =
new GameAuthRequestPacket(LoginClient.Instance.Account, GameClient.Instance.PlayKey1, GameClient.Instance.PlayKey2,
GameClient.Instance.SessionKey1, GameClient.Instance.SessionKey2);


SendPacket(authPacket);
}

public void SendMessage(string message) {
SendMessagePacket packet = new SendMessagePacket(message);
SendPacket(packet);
Expand Down Expand Up @@ -66,7 +89,7 @@ public override void SendPacket(ClientPacket packet) {
}
}

if (_client.BlowfishKey != null) {
if (_client.CryptEnabled) {
EncryptPacket(packet);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,16 @@ public override void HandlePacket(byte[] data) {
}
}

protected override byte[] DecryptPacket(byte[] data) {
Debug.Log("ENCRYPTED: " + StringUtils.ByteArrayToString(data));

GameClient.Instance.GameCrypt.decrypt(data);

Debug.Log("DECRYPTED: " + StringUtils.ByteArrayToString(data));

return data;
}

private void OnPingReceive() {
long now = DateTimeOffset.Now.ToUnixTimeMilliseconds();
int ping = _timestamp != 0 ? (int)(now - _timestamp) : 0;
Expand Down Expand Up @@ -101,12 +111,16 @@ private void OnPingReceive() {
private void OnKeyReceive(byte[] data) {
KeyPacket packet = new KeyPacket(data);

if(packet.AuthAllowed) {
_client.Disconnect();
if (!packet.AuthAllowed) {
Debug.LogError("Gameserver connect not allowed.");
EventProcessor.Instance.QueueEvent(() => GameClient.Instance.Disconnect());
EventProcessor.Instance.QueueEvent(() => LoginClient.Instance.Disconnect());
return;
}

GameClient.Instance.SetBlowFishKey(packet.BlowFishKey);
GameClient.Instance.EnableCrypt(packet.BlowFishKey);

_eventProcessor.QueueEvent(() => ((GameClientPacketHandler)_clientPacketHandler).SendAuth());
}

private void OnCharSelectionInfoReceive(byte[] data) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,20 @@
using UnityEngine;

public class LoginClientPacketHandler : ClientPacketHandler {
protected override void EncryptPacket(ClientPacket packet) {
base.EncryptPacket(packet);

byte[] data = packet.GetData();

Debug.Log("CLEAR: " + StringUtils.ByteArrayToString(data));

LoginClient.Instance.EncryptBlowFish.processBigBlock(data, 0, data, 0, data.Length);

Debug.Log("ENCRYPTED: " + StringUtils.ByteArrayToString(data));

packet.SetData(data);
}

public void SendPing() {
PingPacket packet = new PingPacket();
_client.SendPacket(packet);
Expand Down Expand Up @@ -44,7 +58,7 @@ public void SendAuth() {
Debug.Log($"Combined byte array length: {rsaBlock.Length}");
Debug.Log($"Clear RSA block: {StringUtils.ByteArrayToString(rsaBlock)}");

rsaBlock = _client.RSACrypt.EncryptRSANoPadding(rsaBlock);
rsaBlock = LoginClient.Instance.RSACrypt.EncryptRSANoPadding(rsaBlock);

Debug.Log($"Encrypted RSA block: {StringUtils.ByteArrayToString(rsaBlock)}");

Expand Down
Loading

0 comments on commit 84cc88f

Please sign in to comment.