Skip to content

Commit 60ac496

Browse files
committed
[Common] added: Cryptography files. Attention! There is bad decryption of packets. Do your own encryption research
[Game] update: DoodadManager
1 parent 06dbdd2 commit 60ac496

File tree

14 files changed

+519
-31
lines changed

14 files changed

+519
-31
lines changed

.gitignore

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
AAEmu.Commons/obj/
44
AAEmu.Game/obj/
55
AAEmu.Stream/obj/
6-
/AAEmu.Commons/Cryptography
7-
/AAEmu.Commons/Compression
8-
/AAEmu.Game/Core/Packets/C2G/CSRSAEncryptAESkeyXORkeyPacket.cs
96

107
.idea/
118
AAEmu.Commons/bin/
@@ -16,3 +13,5 @@ AAEmu.Game/Config.json
1613
AAEmu.Login/Config.json
1714
publish/
1815
*.old
16+
/AAEmu.Commons/Cryptography/DecryptCS0.cs
17+
/AAEmu.Commons/Cryptography/DecryptCS1.cs
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<PropertyGroup>
4+
<ShowAllFiles>false</ShowAllFiles>
5+
</PropertyGroup>
6+
</Project>
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
using System.IO;
2+
using System.IO.Compression;
3+
4+
namespace AAEmu.Commons.Compression
5+
{
6+
public static class Сompressing
7+
{
8+
/// <summary>
9+
/// Decompress DD04 packets
10+
/// author: Atelo
11+
/// </summary>
12+
/// <param name="data"></param>
13+
/// <returns></returns>
14+
public static Stream DecompressA(byte[] data)
15+
{
16+
var output = new MemoryStream();
17+
using (var compressedStream = new MemoryStream(data))
18+
using (var zipStream = new DeflateStream(compressedStream, CompressionMode.Decompress))
19+
{
20+
zipStream.CopyTo(output);
21+
zipStream.Close();
22+
output.Position = 0;
23+
return output;
24+
}
25+
}
26+
/// <summary>
27+
/// Decompress DD04 packets
28+
/// author: Atelo
29+
/// </summary>
30+
public static byte[] ReadFullyA(Stream input)
31+
{
32+
var buffer = new byte[16 * 1024];
33+
using (var ms = new MemoryStream())
34+
{
35+
int read;
36+
while ((read = input.Read(buffer, 0, buffer.Length)) > 0)
37+
{
38+
ms.Write(buffer, 0, read);
39+
}
40+
return ms.ToArray();
41+
}
42+
}
43+
//======================================================================================================
44+
//Функции для работы со сжатием строк
45+
/// <summary>
46+
/// Упаковка(архивирование) строки.
47+
/// На входе — данные. На выходе — сжатая строка.
48+
/// Compress DD04 и DD03 packets
49+
/// </summary>
50+
/// <param name="data"></param>
51+
/// <returns></returns>
52+
public static byte[] Compress(byte[] data)
53+
{
54+
var output = new MemoryStream();
55+
using (var dstream = new DeflateStream(output, CompressionMode.Compress))
56+
{
57+
dstream.Write(data, 0, data.Length);
58+
dstream.Close();
59+
}
60+
61+
return output.ToArray();
62+
}
63+
/// <summary>
64+
/// Распаковка(разархивирование) сжатой строки.
65+
/// На входе — данные, предварительно сжатые предыдущей функцией. На выходе — распакованная строка.
66+
/// Decompress DD04 packets. На вход подавать пакет без длины, начиная с DD04
67+
/// Decompress DD03 packets. На вход подавать пакет без длины и DD, начиная с 03
68+
/// </summary>
69+
/// <param name="data"></param>
70+
/// <returns></returns>
71+
public static byte[] Decompress(byte[] data)
72+
{
73+
var input = new MemoryStream(data);
74+
var output = new MemoryStream();
75+
using (var dstream = new DeflateStream(input, CompressionMode.Decompress))
76+
{
77+
dstream.CopyTo(output);
78+
dstream.Close();
79+
}
80+
81+
return output.ToArray();
82+
}
83+
}
84+
}
85+
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* by uranusq https://github.com/NL0bP/aaa_emulator
3+
*
4+
* by NLObP: метод шифрации для ВСЕХ
5+
*/
6+
7+
using System.Security.Cryptography;
8+
9+
namespace AAEmu.Commons.Cryptography
10+
{
11+
public class CryptRSA
12+
{
13+
public byte[] PubKey { get; set; }
14+
public byte[] PrivKey { get; set; }
15+
public byte[] Modulus { get; set; }
16+
public byte[] Exponent { get; set; }
17+
public byte[] AesKey { get; set; }
18+
public byte[] Iv { get; set; }
19+
public uint XorKey { get; set; }
20+
public RSACryptoServiceProvider Rsa { get; set; }
21+
22+
public CryptRSA()
23+
{
24+
Rsa = new RSACryptoServiceProvider(1024);
25+
PubKey = Rsa.ExportCspBlob(false); //сохраним открытый ключ в byte[]
26+
PrivKey = Rsa.ExportCspBlob(true); //сохраним приватный ключ в byte[]
27+
AesKey = new byte[16];
28+
Iv = new byte[16];
29+
XorKey = 0;
30+
}
31+
32+
/// <summary>
33+
/// GetAesKey ... extracts AES key
34+
/// </summary>
35+
public void GetAesKey(byte[] raw)
36+
{
37+
Rsa.ImportCspBlob(PrivKey); //получить приватный ключ
38+
AesKey = Rsa.Decrypt(raw, false); //расшифровать с секретным ключом
39+
}
40+
41+
/// <summary>
42+
/// GetXorKey ... extracts XOR key
43+
/// </summary>
44+
public void GetXorKey(byte[] raw)
45+
{
46+
Rsa.ImportCspBlob(PrivKey); //получить секретный ключ
47+
var keyXoRraw = Rsa.Decrypt(raw, false); //расшифровать с секретным ключом
48+
49+
var head = System.BitConverter.ToUInt32(keyXoRraw, 0);
50+
XorKey = (head ^ 0x15a0248e) * head ^ 0x070f1f23 & 0xffffffff; // 3.0.3.0 archerage.to
51+
}
52+
}
53+
}
Lines changed: 212 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,212 @@
1+
/*
2+
* by uranusq https://github.com/NL0bP/aaa_emulator
3+
*
4+
* by NLObP: метод шифрации для ВСЕХ
5+
*/
6+
7+
using System;
8+
using System.Collections.Generic;
9+
using System.IO;
10+
using System.Security.Cryptography;
11+
12+
namespace AAEmu.Commons.Cryptography
13+
{
14+
public class DecryptCs
15+
{
16+
public static byte[] Decode(byte[] data, uint xorKey, byte[] aesKey, byte[] iv, uint num)
17+
{
18+
//------------------------------
19+
//здесь распаковка пакетов от клиента 0005
20+
//для дешифрации следующих пакетов iv = шифрованный предыдущий пакет
21+
byte[] plaintext;
22+
byte[] ciphertext;
23+
var data5 = new byte[data.Length];
24+
var mIv = new byte[16];
25+
var cnt = new int[16];
26+
Buffer.BlockCopy(iv, 0, mIv, 0, 16); // сохраним
27+
//подбираем наилучшее смещение для правильной дешифровки пакета
28+
for (var offset = 0; offset < 16; offset++)
29+
{
30+
Buffer.BlockCopy(data, 0, data5, 0, data.Length); //получим тело пакета
31+
Buffer.BlockCopy(mIv, 0, iv, 0, 16); // восстановим IV
32+
ciphertext = DecodeXor(data5, xorKey, offset);
33+
plaintext = DecodeAes(ciphertext, aesKey, iv);
34+
cnt[offset] = CountZero(plaintext);
35+
}
36+
//окончательный вывод
37+
Buffer.BlockCopy(data, 0, data5, 0, data.Length); //получим тело пакета
38+
Buffer.BlockCopy(mIv, 0, iv, 0, 16); // восстановим IV
39+
var offs = IndexMaxCountZero(cnt);
40+
if (num == 0) { Seq = 0; }
41+
ciphertext = DecodeXor(data, xorKey, offs);
42+
plaintext = DecodeAes(ciphertext, aesKey, iv);
43+
return plaintext;
44+
}
45+
46+
//--------------------------------------------------------------------------------------
47+
private static int CountZero(byte[] pck)
48+
{
49+
var countZero = 0;
50+
for (var i = 2; i < pck.Length; i++)
51+
{
52+
if (pck[i] == 0)
53+
{
54+
countZero++;
55+
}
56+
}
57+
return countZero;
58+
}
59+
//--------------------------------------------------------------------------------------
60+
private static int IndexMaxCountZero(int[] countZero)
61+
{
62+
var index = 0;
63+
var n = 0;
64+
for (var i = 0; i < countZero.Length; i++)
65+
{
66+
if (countZero[i] <= n)
67+
{
68+
continue;
69+
}
70+
71+
n = countZero[i];
72+
index = i;
73+
}
74+
return index;
75+
}
76+
//--------------------------------------------------------------------------------------
77+
/// <summary>
78+
/// toClientEncr help function
79+
/// </summary>
80+
/// <param name="key"></param>
81+
/// <returns></returns>
82+
private static byte Add(ref uint cry)
83+
{
84+
cry += 0x2FCBD5;
85+
var n = (byte)(cry >> 0x10);
86+
n = (byte)(n & 0x0F7);
87+
return (byte)(n == 0 ? 0x0FE : n);
88+
}
89+
//--------------------------------------------------------------------------------------
90+
internal static uint XorKey;
91+
internal static byte Seq;
92+
//--------------------------------------------------------------------------------------
93+
/// <summary>
94+
/// decXor packet
95+
/// </summary>
96+
/// <param name="bodyPacket">packet data, starting after message-key byte</param>
97+
/// <param name="msgKey">unique key for each message</param>
98+
/// <param name="xorKey">xor key </param>
99+
/// <param name="offset">xor decryption can start from some offset)</param>
100+
/// <returns>xor decrypted packet</returns>
101+
//--------------------------------------------------------------------------------------
102+
private static byte[] DeXor(byte[] bodyPacket, uint xorKey, uint msgKey, int offset = 0)
103+
{
104+
var length = bodyPacket.Length;
105+
var array = new byte[length];
106+
107+
XorKey = xorKey * xorKey & 0xffffffff;
108+
var mul = XorKey * msgKey;
109+
110+
var cry = (0x75a024a4 ^ mul) ^ 0xC3903b6a; // 3.0.3.0 archerage.to
111+
var n = 4 * (length / 4);
112+
for (var i = n - 1 - offset; i >= 0; i--)
113+
{
114+
array[i] = (byte)(bodyPacket[i] ^ (uint)Add(ref cry));
115+
}
116+
117+
for (var i = n - offset; i < length; i++)
118+
{
119+
array[i] = (byte)(bodyPacket[i] ^ (uint)Add(ref cry));
120+
}
121+
122+
return array;
123+
}
124+
//--------------------------------------------------------------------------------------
125+
/// <summary>
126+
/// DecodeXor: расшифровка пакета от клиента XOR ключом
127+
/// </summary>
128+
/// <param name="bodyPacket">тело пакета начиная сразу за 0005</param>
129+
/// <param name="xorKey"></param>
130+
/// <param name="offset"></param>
131+
/// <returns></returns>
132+
//--------------------------------------------------------------------------------------
133+
public static byte[] DecodeXor(byte[] bodyPacket, uint xorKey, int offset)
134+
{
135+
var map = new Dictionary<int, int>
136+
{
137+
{0x30, 0x01}, {0x31, 0x02}, {0x32, 0x03}, {0x33, 0x04}, {0x34, 0x05}, {0x35, 0x06}, {0x36, 0x07}, {0x37, 0x08},
138+
{0x38, 0x09}, {0x39, 0x0a}, {0x3a, 0x0b}, {0x3b, 0x0c}, {0x3c, 0x0d}, {0x3d, 0x0e}, {0x3e, 0x0f}, {0x3f, 0x10}
139+
};
140+
var length = bodyPacket.Length;
141+
var mBodyPacket = new byte[length - 3];
142+
Buffer.BlockCopy(bodyPacket, 3, mBodyPacket, 0, length - 3);
143+
var packet = new byte[mBodyPacket.Length];
144+
var msgKey = (uint)(bodyPacket.Length / 16 - 1) << 4;
145+
msgKey += (uint)map[bodyPacket[2]];
146+
packet = DeXor(mBodyPacket, xorKey, msgKey, offset);
147+
return packet;
148+
}
149+
//--------------------------------------------------------------------------------------
150+
private const int Size = 16;
151+
//--------------------------------------------------------------------------------------
152+
private static RijndaelManaged CryptAes(byte[] aesKey, byte[] iv)
153+
{
154+
var rm = new RijndaelManaged
155+
{
156+
KeySize = 128,
157+
BlockSize = 128,
158+
Padding = PaddingMode.None,
159+
Mode = CipherMode.CBC,
160+
Key = aesKey,
161+
IV = iv
162+
};
163+
return rm;
164+
}
165+
//--------------------------------------------------------------------------------------
166+
/// <summary>
167+
/// DecodeAes: расшифровка пакета от клиента AES ключом
168+
/// </summary>
169+
/// <param name="cipherData"></param>
170+
/// <param name="aesKey"></param>
171+
/// <param name="iv"></param>
172+
/// <returns></returns>
173+
//--------------------------------------------------------------------------------------
174+
public static byte[] DecodeAes(byte[] cipherData, byte[] aesKey, byte[] iv)
175+
{
176+
var mIv = new byte[16];
177+
Buffer.BlockCopy(iv, 0, mIv, 0, Size);
178+
var len = cipherData.Length / Size;
179+
//Save last 16 bytes in IV
180+
Buffer.BlockCopy(cipherData, (len - 1) * Size, iv, 0, Size);
181+
// Create a MemoryStream that is going to accept the decrypted bytes
182+
using (var memoryStream = new MemoryStream())
183+
{
184+
// Create a symmetric algorithm.
185+
// We are going to use RijndaelRijndael because it is strong and available on all platforms.
186+
// You can use other algorithms, to do so substitute the next line with something like
187+
// TripleDES alg = TripleDES.Create();
188+
using (var alg = CryptAes(aesKey, mIv))
189+
{
190+
// Create a CryptoStream through which we are going to be pumping our data.
191+
// CryptoStreamMode.Write means that we are going to be writing data to the stream
192+
// and the output will be written in the MemoryStream we have provided.
193+
using (var cs = new CryptoStream(memoryStream, alg.CreateDecryptor(), CryptoStreamMode.Write))
194+
{
195+
// Write the data and make it do the decryption
196+
cs.Write(cipherData, 0, cipherData.Length);
197+
198+
// Close the crypto stream (or do FlushFinalBlock).
199+
// This will tell it that we have done our decryption and there is no more data coming in,
200+
// and it is now a good time to remove the padding and finalize the decryption process.
201+
cs.FlushFinalBlock();
202+
cs.Close();
203+
}
204+
}
205+
// Now get the decrypted data from the MemoryStream.
206+
// Some people make a mistake of using GetBuffer() here, which is not the right way.
207+
var decryptedData = memoryStream.ToArray();
208+
return decryptedData;
209+
}
210+
}
211+
}
212+
}

0 commit comments

Comments
 (0)