mirror of
https://github.com/sebastian-heinz/mhf-server.git
synced 2025-04-04 05:48:29 +08:00
401 lines
39 KiB
C#
401 lines
39 KiB
C#
![]() |
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using Arrowgene.Services.Buffers;
|
|||
|
using Arrowgene.Services.Logging;
|
|||
|
using Mhf.Server.Common;
|
|||
|
using Mhf.Server.Logging;
|
|||
|
using Mhf.Server.Setting;
|
|||
|
|
|||
|
namespace Mhf.Server.Packet
|
|||
|
{
|
|||
|
public class PacketFactory
|
|||
|
{
|
|||
|
public const int PacketHeaderSize = 14;
|
|||
|
public const int InitPacketSize = 8;
|
|||
|
public const uint CryptoInit = 995117;
|
|||
|
|
|||
|
public static byte[] EncryptKey = new byte[]
|
|||
|
{
|
|||
|
0x90, 0x51, 0x26, 0x25, 0x04, 0xBF, 0xCF, 0x4C, 0x92, 0x02, 0x52, 0x7A, 0x70, 0x1A, 0x41, 0x88, 0x8C, 0xC2,
|
|||
|
0xCE, 0xB8, 0xF6, 0x57, 0x7E, 0xBA, 0x83, 0x63, 0x2C, 0x24, 0x9A, 0x67, 0x86, 0x0C, 0xBE, 0x72, 0xFD, 0xB6,
|
|||
|
0x7B, 0x79, 0xB0, 0x22, 0x5A, 0x60, 0x5C, 0x4F, 0x49, 0xE2, 0x0E, 0xF5, 0x3A, 0x81, 0xAE, 0x11, 0x6B, 0xF0,
|
|||
|
0xA1, 0x01, 0xE8, 0x65, 0x8D, 0x5B, 0xDC, 0xCC, 0x93, 0x18, 0xB3, 0xAB, 0x77, 0xF7, 0x8E, 0xEC, 0xEF, 0x05,
|
|||
|
0x00, 0xCA, 0x4E, 0xA7, 0xBC, 0xB5, 0x10, 0xC6, 0x6C, 0xC0, 0xC4, 0xE5, 0x87, 0x3F, 0xC1, 0x82, 0x29, 0x96,
|
|||
|
0x45, 0x73, 0x07, 0xCB, 0x43, 0xF9, 0xF3, 0x08, 0x89, 0xD0, 0x99, 0x6A, 0x3B, 0x37, 0x19, 0xD4, 0x40, 0xEA,
|
|||
|
0xD7, 0x85, 0x16, 0x66, 0x1E, 0x9C, 0x39, 0xBB, 0xEE, 0x4A, 0x03, 0x8A, 0x36, 0x2D, 0x13, 0x1D, 0x56, 0x48,
|
|||
|
0xC7, 0x0D, 0x59, 0xB2, 0x44, 0xA3, 0xFE, 0x8B, 0x32, 0x1B, 0x84, 0xA0, 0x2E, 0x62, 0x17, 0x42, 0xB9, 0x9B,
|
|||
|
0x2B, 0x75, 0xD8, 0x1C, 0x3C, 0x4D, 0x76, 0x27, 0x6E, 0x28, 0xD3, 0x33, 0xC3, 0x21, 0xAF, 0x34, 0x23, 0xDD,
|
|||
|
0x68, 0x9F, 0xF1, 0xAD, 0xE1, 0xB4, 0xE7, 0xA6, 0x74, 0x15, 0x4B, 0xFA, 0x3D, 0x5F, 0x7C, 0xDA, 0x2F, 0x0A,
|
|||
|
0xE3, 0x7D, 0xC8, 0xB7, 0x12, 0x6F, 0x9E, 0xA9, 0x14, 0x53, 0x97, 0x8F, 0x64, 0xF4, 0xF8, 0xA2, 0xA4, 0x2A,
|
|||
|
0xD2, 0x47, 0x9D, 0x71, 0xC5, 0xE9, 0x06, 0x98, 0x20, 0x54, 0x80, 0xAA, 0xF2, 0xAC, 0x50, 0xD6, 0x7F, 0xD9,
|
|||
|
0xC9, 0xCD, 0x69, 0x46, 0x6D, 0x30, 0xB1, 0x58, 0x0B, 0x55, 0xD1, 0x5D, 0xD5, 0xBD, 0x31, 0xDE, 0xA5, 0xE4,
|
|||
|
0x91, 0x0F, 0x61, 0x38, 0xDF, 0xA8, 0xE6, 0x3E, 0x1F, 0x35, 0xED, 0xDB, 0x94, 0xEB, 0x09, 0x5E, 0x95, 0xFB,
|
|||
|
0xFC, 0xE0, 0x78, 0xFF
|
|||
|
};
|
|||
|
|
|||
|
public static byte[] DecryptKey = new byte[]
|
|||
|
{
|
|||
|
0x48, 0x37, 0x09, 0x76, 0x04, 0x47, 0xCC, 0x5C, 0x61, 0xF8, 0xB3, 0xE0, 0x1F, 0x7F, 0x2E, 0xEB, 0x4E, 0x33,
|
|||
|
0xB8, 0x7A, 0xBC, 0xAB, 0x6E, 0x8C, 0x3F, 0x68, 0x0D, 0x87, 0x93, 0x7B, 0x70, 0xF2, 0xCE, 0x9D, 0x27, 0xA0,
|
|||
|
0x1B, 0x03, 0x02, 0x97, 0x99, 0x58, 0xC5, 0x90, 0x1A, 0x79, 0x8A, 0xB2, 0xDD, 0xE6, 0x86, 0x9B, 0x9F, 0xF3,
|
|||
|
0x78, 0x67, 0xED, 0x72, 0x30, 0x66, 0x94, 0xAE, 0xF1, 0x55, 0x6A, 0x0E, 0x8D, 0x5E, 0x82, 0x5A, 0xDB, 0xC7,
|
|||
|
0x7D, 0x2C, 0x75, 0xAC, 0x07, 0x95, 0x4A, 0x2B, 0xD4, 0x01, 0x0A, 0xBD, 0xCF, 0xE1, 0x7C, 0x15, 0xDF, 0x80,
|
|||
|
0x28, 0x3B, 0x2A, 0xE3, 0xF9, 0xAF, 0x29, 0xEC, 0x8B, 0x19, 0xC0, 0x39, 0x6F, 0x1D, 0xA2, 0xDA, 0x65, 0x34,
|
|||
|
0x50, 0xDC, 0x98, 0xB9, 0x0C, 0xC9, 0x21, 0x5B, 0xAA, 0x91, 0x96, 0x42, 0xFE, 0x25, 0x0B, 0x24, 0xB0, 0xB5,
|
|||
|
0x16, 0xD6, 0xD0, 0x31, 0x57, 0x18, 0x88, 0x6D, 0x1E, 0x54, 0x0F, 0x62, 0x77, 0x85, 0x10, 0x3A, 0x44, 0xBF,
|
|||
|
0x00, 0xEA, 0x08, 0x3E, 0xF6, 0xFA, 0x59, 0xBE, 0xCD, 0x64, 0x1C, 0x8F, 0x71, 0xC8, 0xBA, 0xA3, 0x89, 0x36,
|
|||
|
0xC3, 0x83, 0xC4, 0xE8, 0xA9, 0x4B, 0xEF, 0xBB, 0xD1, 0x41, 0xD3, 0xA5, 0x32, 0x9E, 0x26, 0xDE, 0x81, 0x40,
|
|||
|
0xA7, 0x4D, 0x23, 0xB7, 0x13, 0x8E, 0x17, 0x73, 0x4C, 0xE5, 0x20, 0x05, 0x51, 0x56, 0x11, 0x9C, 0x52, 0xCA,
|
|||
|
0x4F, 0x7E, 0xB6, 0xD8, 0x49, 0x5D, 0x3D, 0xD9, 0x12, 0x06, 0x63, 0xE2, 0xC6, 0x9A, 0x69, 0xE4, 0xD5, 0x6C,
|
|||
|
0x92, 0xD7, 0xB1, 0xF5, 0x3C, 0xA1, 0xE7, 0xEE, 0xFD, 0xA6, 0x2D, 0xB4, 0xE9, 0x53, 0xF0, 0xA8, 0x38, 0xCB,
|
|||
|
0x6B, 0xF7, 0x45, 0xF4, 0x74, 0x46, 0x35, 0xA4, 0xD2, 0x60, 0xC1, 0x2F, 0x14, 0x43, 0xC2, 0x5F, 0xAD, 0xFB,
|
|||
|
0xFC, 0x22, 0x84, 0xFF
|
|||
|
};
|
|||
|
|
|||
|
public static byte[] SharedCryptKey = new byte[]
|
|||
|
{
|
|||
|
0xDD, 0xA8, 0x5F, 0x1E, 0x57, 0xAF, 0xC0, 0xCC, 0x43, 0x35, 0x8F, 0xBB, 0x6F, 0xE6, 0xA1, 0xD6, 0x60, 0xB9,
|
|||
|
0x1A, 0xAE, 0x20, 0x49, 0x24, 0x81, 0x21, 0xFE, 0x86, 0x2B, 0x98, 0xB7, 0xB3, 0xD2, 0x91, 0x01, 0x3A, 0x4C,
|
|||
|
0x65, 0x92, 0x1C, 0xF4, 0xBE, 0xDD, 0xD9, 0x08, 0xE6, 0x81, 0x98, 0x1B, 0x8D, 0x60, 0xF3, 0x6F, 0xA1, 0x47,
|
|||
|
0x24, 0xF1, 0x53, 0x45, 0xC8, 0x7B, 0x88, 0x80, 0x4E, 0x36, 0xC3, 0x0D, 0xC9, 0xD6, 0x8B, 0x08, 0x19, 0x0B,
|
|||
|
0xA5, 0xC1, 0x11, 0x4C, 0x60, 0xF8, 0x5D, 0xFC, 0x15, 0x68, 0x7E, 0x32, 0xC0, 0x50, 0xAB, 0x64, 0x1F, 0x8A,
|
|||
|
0xD4, 0x08, 0x39, 0x7F, 0xC2, 0xFB, 0xBA, 0x6C, 0xF0, 0xE6, 0xB0, 0x31, 0x10, 0xC1, 0xBF, 0x75, 0x43, 0xBB,
|
|||
|
0x18, 0x04, 0x0D, 0xD1, 0x97, 0xF7, 0x23, 0x21, 0x83, 0x8B, 0xCA, 0x25, 0x2B, 0xA3, 0x03, 0x13, 0xEA, 0xAE,
|
|||
|
0xFE, 0xF0, 0xEB, 0xFD, 0x85, 0x57, 0x53, 0x65, 0x41, 0x2A, 0x40, 0x99, 0xC0, 0x94, 0x65, 0x7E, 0x7C, 0x93,
|
|||
|
0x82, 0xB0, 0xB3, 0xE5, 0xC0, 0x21, 0x09, 0x84, 0xD5, 0xEF, 0x9F, 0xD1, 0x7E, 0xDC, 0x4D, 0xF5, 0x7E, 0xCD,
|
|||
|
0x45, 0x3C, 0x7F, 0xF5, 0x59, 0x98, 0xC6, 0x55, 0xFC, 0x9F, 0xA3, 0xB7, 0x74, 0xEE, 0x31, 0x98, 0xE6, 0xB7,
|
|||
|
0xBE, 0x26, 0xF4, 0x3C, 0x76, 0xF1, 0x23, 0x7E, 0x02, 0x4E, 0x3C, 0xD1, 0xC7, 0x28, 0x23, 0x73, 0xC4, 0xD9,
|
|||
|
0x5E, 0x0D, 0xA1, 0x80, 0xA5, 0xAA, 0x26, 0x0A, 0xA3, 0x44, 0x82, 0x74, 0xE6, 0x3C, 0x44, 0x27, 0x51, 0x0D,
|
|||
|
0x5F, 0xC7, 0x9C, 0xD6, 0x63, 0x67, 0xA5, 0x27, 0x97, 0x38, 0xFB, 0x2D, 0xD3, 0xD6, 0x60, 0x25, 0x83, 0x4D,
|
|||
|
0x37, 0x5B, 0x40, 0x59, 0x11, 0x77, 0x51, 0x11, 0x14, 0x18, 0x07, 0x63, 0xB1, 0x34, 0x3D, 0xB8, 0x60, 0x13,
|
|||
|
0xC2, 0xE8, 0x13, 0x82
|
|||
|
};
|
|||
|
|
|||
|
private readonly MhfLogger _logger;
|
|||
|
private readonly MhfSetting _setting;
|
|||
|
|
|||
|
private int _position;
|
|||
|
private IBuffer _buffer;
|
|||
|
private PacketHeader _header;
|
|||
|
|
|||
|
private uint _readKeyRot;
|
|||
|
private uint _sendKeyRot;
|
|||
|
|
|||
|
private uint _sentPackets;
|
|||
|
private ushort _combinedCheck;
|
|||
|
|
|||
|
public PacketFactory(MhfSetting setting)
|
|||
|
{
|
|||
|
_logger = LogProvider.Logger<MhfLogger>(this);
|
|||
|
_setting = setting;
|
|||
|
_readKeyRot = CryptoInit;
|
|||
|
_sendKeyRot = CryptoInit;
|
|||
|
_sentPackets = 0;
|
|||
|
_header = null;
|
|||
|
Reset();
|
|||
|
}
|
|||
|
|
|||
|
public byte[] Write(MhfPacket packet)
|
|||
|
{
|
|||
|
if (packet.Data.Size > ushort.MaxValue)
|
|||
|
{
|
|||
|
_logger.Error(
|
|||
|
$"Packet Size: {packet.Data.Size} exceeds maximum size of {ushort.MaxValue} for PacketId: {packet.Id}");
|
|||
|
return null;
|
|||
|
}
|
|||
|
|
|||
|
byte[] data = packet.Data.GetAllBytes();
|
|||
|
|
|||
|
|
|||
|
byte keyRotDelta = 2;
|
|||
|
// Update the rolling key index.
|
|||
|
if (keyRotDelta != 0)
|
|||
|
{
|
|||
|
_sendKeyRot = keyRotDelta * (_sendKeyRot + 1);
|
|||
|
}
|
|||
|
|
|||
|
data = Encrypt(data, _sendKeyRot,
|
|||
|
out ushort combinedCheck, out ushort check0,
|
|||
|
out ushort check1, out ushort check2);
|
|||
|
|
|||
|
packet.Header.DataSize = (ushort)data.Length;
|
|||
|
packet.Header.Pf0 = (byte) (((packet.Header.DataSize >> 12) & 0xF3) | 3);
|
|||
|
packet.Header.KeyRotDelta = keyRotDelta;
|
|||
|
packet.Header.CombinedCheck = 0;
|
|||
|
packet.Header.Check0 = check0;
|
|||
|
packet.Header.Check1 = check1;
|
|||
|
packet.Header.Check2 = check2;
|
|||
|
|
|||
|
Console.WriteLine(packet.Header.ToLogText());
|
|||
|
|
|||
|
IBuffer buffer = BufferProvider.Provide();
|
|||
|
buffer.WriteByte(packet.Header.Pf0);
|
|||
|
buffer.WriteByte(packet.Header.KeyRotDelta);
|
|||
|
buffer.WriteInt16(packet.Header.Id, Endianness.Big);
|
|||
|
buffer.WriteInt16(packet.Header.DataSize, Endianness.Big);
|
|||
|
buffer.WriteInt16(packet.Header.CombinedCheck, Endianness.Big);
|
|||
|
buffer.WriteInt16(packet.Header.Check0, Endianness.Big);
|
|||
|
buffer.WriteInt16(packet.Header.Check1, Endianness.Big);
|
|||
|
buffer.WriteInt16(packet.Header.Check2, Endianness.Big);
|
|||
|
buffer.WriteBytes(data);
|
|||
|
byte[] final = buffer.GetAllBytes();
|
|||
|
return final;
|
|||
|
}
|
|||
|
|
|||
|
public List<MhfPacket> Read(byte[] data)
|
|||
|
{
|
|||
|
List<MhfPacket> packets = new List<MhfPacket>();
|
|||
|
if (_buffer == null)
|
|||
|
{
|
|||
|
_buffer = BufferProvider.Provide(data);
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_buffer.SetPositionEnd();
|
|||
|
_buffer.WriteBytes(data);
|
|||
|
}
|
|||
|
|
|||
|
_buffer.Position = _position;
|
|||
|
|
|||
|
bool read = true;
|
|||
|
while (read)
|
|||
|
{
|
|||
|
read = false;
|
|||
|
|
|||
|
if (_header == null && _buffer.Size - _buffer.Position >= PacketHeaderSize)
|
|||
|
{
|
|||
|
byte pf0 = _buffer.ReadByte();
|
|||
|
byte keyRotDelta = _buffer.ReadByte();
|
|||
|
ushort id = _buffer.ReadUInt16(Endianness.Big);
|
|||
|
ushort dataSize = _buffer.ReadUInt16(Endianness.Big);
|
|||
|
ushort combinedCheck = _buffer.ReadUInt16(Endianness.Big);
|
|||
|
ushort check0 = _buffer.ReadUInt16(Endianness.Big);
|
|||
|
ushort check1 = _buffer.ReadUInt16(Endianness.Big);
|
|||
|
ushort check2 = _buffer.ReadUInt16(Endianness.Big);
|
|||
|
_header = new PacketHeader(id, pf0, keyRotDelta, dataSize, combinedCheck, check0, check1, check2);
|
|||
|
Console.WriteLine(_header.ToLogText());
|
|||
|
// Update the rolling key index.
|
|||
|
if (_header.KeyRotDelta != 0)
|
|||
|
{
|
|||
|
_readKeyRot = _header.KeyRotDelta * (_readKeyRot + 1);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (_header == null && _buffer.Size - _buffer.Position == InitPacketSize)
|
|||
|
{
|
|||
|
byte[] payload = _buffer.ReadBytes(InitPacketSize);
|
|||
|
_logger.Debug($"Ignoring Data: {Util.ToHexString(payload, ' ')}");
|
|||
|
}
|
|||
|
|
|||
|
if (_header != null && _buffer.Size - _buffer.Position >= _header.DataSize)
|
|||
|
{
|
|||
|
byte[] packetData = _buffer.ReadBytes(_header.DataSize);
|
|||
|
packetData = Decrypt(packetData, _readKeyRot,
|
|||
|
out ushort combinedCheck, out ushort check0,
|
|||
|
out ushort check1, out ushort check2);
|
|||
|
|
|||
|
IBuffer buffer = BufferProvider.Provide(packetData);
|
|||
|
MhfPacket packet = new MhfPacket(_header, buffer);
|
|||
|
packets.Add(packet);
|
|||
|
_header = null;
|
|||
|
read = _buffer.Position != _buffer.Size;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (_buffer.Position == _buffer.Size)
|
|||
|
{
|
|||
|
Reset();
|
|||
|
}
|
|||
|
else
|
|||
|
{
|
|||
|
_position = _buffer.Position;
|
|||
|
}
|
|||
|
|
|||
|
return packets;
|
|||
|
}
|
|||
|
|
|||
|
private void Reset()
|
|||
|
{
|
|||
|
_header = null;
|
|||
|
_position = 0;
|
|||
|
_buffer = null;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
public void Test()
|
|||
|
{
|
|||
|
byte[] me = Util.FromHexString(
|
|||
|
"010201011E952C4F6D66366B414C5765553248535635755DD6002F0C75306D68662D672E6A70000C6C302E6D682D672E6A7000143130362E3138352E342E36313A3533333130002175A5E90000005DD0AE99000100010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000010000028B3C424F44593E3C43455445523E3C53495A455F333E3C435F3E918D93FC8DB03490E7969C8DB09290AC82C582A882BD82DF82B58FAC9482663939399687947A957A81493C423E3C424F44593E91E631343789F18E906C8DD581758F9F82BF836C83528282E782CC92A790ED8FF38176936F988DD53C42523E3C424F44593E3C42523C424F44593E3C42523E3C424F44593C4C4546543E3C435F373E3C53495A5F323E8DA189F182C58DC58CE382C6C882E98EEB906C8DD581758F9F82BF6C835282A982E782CC92A790ED8FF3768A4A8DC381493C42523E3C424F443E3C42523E3C424F44593E3C4C45463E3C435F333E3C53495A455F323E81936F985E8DD58A4A8DC38AFA8AD4813C435F373E3C42523E3C424F44593E318C8E323093FA2890852920816020318C8E323793FA2890852983818393658369839383588A4A8E6E82DC82C5435F373E3C42523E3C424F44593E3C523E3C424F44593E91E631343789F1EB906C8DD582C582CD81418354815B6F815B918D93FC8DB0909482C9899EB682C481413C42523E3C424F44593E435F353E82A882BD82DF82B58FAC9482663939399687815E8A6C93BE9166DE90943130947B81413C42523E3C4244593E8F9F82BF9167834E834783586782F08343837883938367834E834758836782C682B582C4947A904D3C43373E82C882C73C42523E3C424F445993C195CA82C8964A8FDC82F092698A934982C982B2977088D382B582C48282E882DC82B781423C42523E3C424F593E3C42523E3C424F44593E836E83835E815B82CC8A46976C81418DC58C82CC8EEB906C8DD582C982BA82D08E89C182B582C482AD82BE82B382A28100000000000000000E2A64736D63000C00003D0000008181000000000000000000816A000000000000280000006900000000000021000000814900000000002F000000815E000000000000000000817B0000000000002600000095000000000000825000003100000000000082DA0000837B0000CE00DE00D9DE00837ADE0082D9814A837A814A00814A0000000082D700008378000000DE0082D6DE008377DE0082D6814A00814A8377814A0000000082C50000660000C300DE0082C4DE008365DE00C4814A8365814AC300814A81A7814AA7DE0089B3DE0089B3814A00000000D1000083720000CB00DE0082D0DE0071DE0082D0814A8371814ACB00814A00000082C7000083680000C400DE00C6DE008367DE0082C6814A8367814A00814A84B0DE0084B0814A84A5DE00A5814A0000000082CE0000836F000000DE0082CDDE00836EDE0094AADE00CD814A836E814ACA00814A94AA814A00000082C2DE00836400008363DE00C2814A8363814AC200DE00C200814AC3000082C1DE008362DE00AF00DE00C1814A8362814AAF00814A00000000D4000083750000CC00DE008394000000DE0082A4814A82A4DE008345DE0000DE0082A3DE0082D3DE008374DE0000814A0000000082C000008361000000DE0082BFDE008360DE0082BF814A60814AC100814A90E7814A90E7DE0000000082BE0000835F0000C000DE00BDDE00835EDE00975BDE0082BD814A5E814AC000814A975B814A00000000BC0000835D0000BF00DE0082BBDE005CDE0082BB814A835C814ABF00814A93DE008393814ADD00814ADD00DE008ADE00D800DE00D800814A838A814A00000082BA0000BE00DE0082B9DE005ADE0082B9814A835A814ABE00814A5B00000000000082B800008359000000DE0082B7DE008358DE0082B7814A58814ABD00814A0000000082B60000570000BC00DE0082B5DE008356DE00B5814A8356814ABC00814A00000000B4000083550000BB00DE0082B3DE0054DE0082B3814A8354814ABB00814A00000082B2000083530000BA00DE00B1DE008352DE0082B1814A8352814A00814A0000000082B000008351000000DE0082AFDE008350DE0082AF814A50814AB900814A8396DE008396814A00000082AE0000834F0000B800DE00ADDE00834EDE0082AD814A834E814A00814A0000000082AC0000834D000000DE0082ABDE00834CDE0082AB814A4C814AB700814A0000000082AA00004B0000B600DE008395DE00834ADE00A9DE0097CDDE008395814A834A814AA9814A97CD814AB600814A00000000F0000083920000A600000000000000ED0000838F0000DC000000838E000000000082EB0000838D0000DB000000A000008CFB00000000000082EA00008C0000DA0000000000000082E900008B0000D90000000000000082E800008A0000D80000000000000082E70000890000D70000000000000082E60000880000D6000000AE00000082E500008700000000000082E4000083860000000000AD00000082E300008385000000000082E2000083840000D400000000000082E100008383000000000000E0000083820000D300000000000000DF000083810000D20000004D00450000000082DE000083800000D100000000000082DD0000837E0000D000000000000082DC0000837D0000CF00000000000082D90000837A0000CE00000000000082D6000083770000CD00000000000082D3000083740000CC00000000000082D0000083710000CB00000000000082CD0000836E0000CA000000AA00000000000082CC0000836D00
|
|||
|
|
|||
|
|
|||
|
byte[] packetData = Util.FromHexString(
|
|||
|
"444C54534B45595349474E3A313030007465737400736B3030242E546676664B2E487646356E6C317436624338555843536352766538524249704D4D4E395537524C786A6B2D0000");
|
|||
|
|
|||
|
|
|||
|
byte[] packetData1 = Enc(packetData, (byte) (995118 & 0xFF));
|
|||
|
Console.WriteLine("Enc " + Util.ToHexString(packetData1, ' '));
|
|||
|
|
|||
|
byte[] packetData2 = Encrypt(packetData, 2,
|
|||
|
out ushort combinedCheck, out ushort check0,
|
|||
|
out ushort check1, out ushort check2);
|
|||
|
Console.WriteLine("Enc " + Util.ToHexString(packetData2, ' '));
|
|||
|
|
|||
|
|
|||
|
// packetData = Decrypt(packetData);
|
|||
|
// Console.WriteLine("Dec " + Util.ToHexString(packetData, ' '));
|
|||
|
// Console.WriteLine("Dec " + Util.ToAsciiString(packetData, true));
|
|||
|
}
|
|||
|
|
|||
|
private byte[] Decrypt(byte[] input, uint key, out ushort cc, out ushort c0, out ushort c1, out ushort c2)
|
|||
|
{
|
|||
|
uint size = (uint) input.Length;
|
|||
|
byte[] output = new byte[size];
|
|||
|
|
|||
|
byte unkCryptkeyRotArg = (byte) ((key >> 1) % 999983);
|
|||
|
uint unkDerivedCryptkeyRot = (uint) (size * (unkCryptkeyRotArg + 1));
|
|||
|
|
|||
|
byte sharedBufIdx = 1;
|
|||
|
uint accumulator0 = 0;
|
|||
|
uint accumulator1 = 0;
|
|||
|
uint accumulator2 = 0;
|
|||
|
|
|||
|
for (int i = 0; i < size; i++)
|
|||
|
{
|
|||
|
// Do the decryption for this iteration
|
|||
|
byte oldSharedBufIdx = sharedBufIdx;
|
|||
|
byte tIdx = (byte) (input[i] ^ SharedCryptKey[sharedBufIdx]);
|
|||
|
uint decKeyByte = DecryptKey[tIdx];
|
|||
|
sharedBufIdx = (byte) ((unkDerivedCryptkeyRot >> 10) ^ decKeyByte);
|
|||
|
|
|||
|
// Update the checksum accumulators.
|
|||
|
accumulator0 = (uint) (accumulator0 + (tIdx << (i & 7)));
|
|||
|
accumulator1 = accumulator1 + decKeyByte;
|
|||
|
accumulator2 = (uint) (accumulator2 + (oldSharedBufIdx * sharedBufIdx));
|
|||
|
|
|||
|
// Append the output.
|
|||
|
output[i] = sharedBufIdx;
|
|||
|
|
|||
|
// Update the key pos for next iteration.
|
|||
|
unkDerivedCryptkeyRot = 0x4FD * (unkDerivedCryptkeyRot + 1);
|
|||
|
}
|
|||
|
|
|||
|
ushort combinedCheck = (ushort) (accumulator1 + (accumulator0 >> 1) + (accumulator2 >> 2));
|
|||
|
ushort check0 = (ushort) (accumulator0 ^ (accumulator0 >> 16));
|
|||
|
ushort check1 = (ushort) (accumulator1 ^ (accumulator1 >> 16));
|
|||
|
ushort check2 = (ushort) (accumulator2 ^ (accumulator2 >> 16));
|
|||
|
|
|||
|
cc = combinedCheck;
|
|||
|
c0 = check0;
|
|||
|
c1 = check1;
|
|||
|
c2 = check2;
|
|||
|
return output;
|
|||
|
}
|
|||
|
|
|||
|
private byte[] Encrypt(byte[] input, uint key, out ushort cc, out ushort c0, out ushort c1, out ushort c2)
|
|||
|
{
|
|||
|
uint size = (uint) input.Length;
|
|||
|
byte[] output = new byte[size];
|
|||
|
|
|||
|
byte unkCryptkeyRotArg = (byte) ((key >> 1) % 999983);
|
|||
|
uint unkDerivedCryptkeyRot = (uint) (size * (unkCryptkeyRotArg + 1));
|
|||
|
|
|||
|
byte sharedBufIdx = 1;
|
|||
|
uint accumulator0 = 0;
|
|||
|
uint accumulator1 = 0;
|
|||
|
uint accumulator2 = 0;
|
|||
|
|
|||
|
for (int i = 0; i < size; i++)
|
|||
|
{
|
|||
|
// Do the encryption for this iteration
|
|||
|
byte encKeyIdx = (byte) ((unkDerivedCryptkeyRot >> 10) ^ input[i]);
|
|||
|
unkDerivedCryptkeyRot = 0x4FD * (unkDerivedCryptkeyRot + 1);
|
|||
|
byte encKeyByte = EncryptKey[encKeyIdx];
|
|||
|
|
|||
|
// Update the checksum accumulators.
|
|||
|
accumulator2 = (uint) (accumulator2 + (sharedBufIdx * input[i]));
|
|||
|
accumulator1 = accumulator1 + encKeyIdx;
|
|||
|
accumulator0 = (uint) (accumulator0 + (encKeyByte << (i & 7)));
|
|||
|
|
|||
|
// Append the output.
|
|||
|
output[i] = (byte) (SharedCryptKey[sharedBufIdx] ^ encKeyByte);
|
|||
|
|
|||
|
// Update the shared_buf_idx for the next iteration.
|
|||
|
sharedBufIdx = input[i];
|
|||
|
}
|
|||
|
|
|||
|
ushort combinedCheck = (ushort) (accumulator1 + (accumulator0 >> 1) + (accumulator2 >> 2));
|
|||
|
ushort check0 = (ushort) (accumulator0 ^ (accumulator0 >> 16));
|
|||
|
ushort check1 = (ushort) (accumulator1 ^ (accumulator1 >> 16));
|
|||
|
ushort check2 = (ushort) (accumulator2 ^ (accumulator2 >> 16));
|
|||
|
|
|||
|
cc = combinedCheck;
|
|||
|
c0 = check0;
|
|||
|
c1 = check1;
|
|||
|
c2 = check2;
|
|||
|
return output;
|
|||
|
}
|
|||
|
|
|||
|
byte[] Enc(byte[] input, byte a5)
|
|||
|
{
|
|||
|
byte v12;
|
|||
|
uint v13;
|
|||
|
uint v14;
|
|||
|
uint inputSize = (uint) input.Length;
|
|||
|
byte outputIndex = 0;
|
|||
|
byte inputIndex = 0;
|
|||
|
uint v5 = inputSize * (a5 + 1u);
|
|||
|
uint v6 = 0;
|
|||
|
uint v7 = 0;
|
|||
|
uint v8 = 0;
|
|||
|
uint v9 = 0;
|
|||
|
byte v10 = 1;
|
|||
|
uint v19 = 0;
|
|||
|
uint v18 = 0;
|
|||
|
uint v17 = 0;
|
|||
|
byte[] output = new byte[inputSize];
|
|||
|
if (inputSize > 0)
|
|||
|
{
|
|||
|
do
|
|||
|
{
|
|||
|
v12 = input[inputIndex];
|
|||
|
v19 += (uint) v10 * input[inputIndex];
|
|||
|
v13 = (byte) ((v5 >> 10) ^ input[inputIndex]);
|
|||
|
v18 += v13;
|
|||
|
v13 = ReplaceByte(0, v13, EncryptKey[v13]);
|
|||
|
v14 = (uint) ((byte) v13 << ((int) v9 & 7));
|
|||
|
v9++;
|
|||
|
v5 = 1277 * (v5 + 1);
|
|||
|
v17 += v14;
|
|||
|
output[outputIndex] = (byte) (SharedCryptKey[v10] ^ v13);
|
|||
|
inputIndex = (byte) (outputIndex + 1);
|
|||
|
v10 = v12;
|
|||
|
++outputIndex;
|
|||
|
} while (v9 < inputSize);
|
|||
|
|
|||
|
v6 = v19;
|
|||
|
v7 = v18;
|
|||
|
v8 = v17;
|
|||
|
}
|
|||
|
|
|||
|
uint a6 = v6 ^ (v6 >> 16);
|
|||
|
uint a4 = v7 ^ (v7 >> 16);
|
|||
|
uint result = (uint) (v7 + ((int) v8 >> 1) + ((int) v6 >> 2));
|
|||
|
uint a2 = v8 ^ (v8 >> 16);
|
|||
|
ushort check3 = (ushort) a6;
|
|||
|
ushort check2 = (ushort) a4;
|
|||
|
ushort check1 = (ushort) a2;
|
|||
|
ushort res = (ushort) result;
|
|||
|
byte resB = (byte) result;
|
|||
|
|
|||
|
return output;
|
|||
|
}
|
|||
|
|
|||
|
uint ReplaceByte(uint index, uint value, byte replaceByte)
|
|||
|
{
|
|||
|
var shiftBits = 8 * index;
|
|||
|
var mask = ~(0xff << (int) shiftBits);
|
|||
|
return (uint) (value & mask | (replaceByte << (int) shiftBits));
|
|||
|
}
|
|||
|
}
|
|||
|
}
|