mirror of
https://github.com/BtbN/ClanServer.git
synced 2026-09-07 16:05:14 -05:00
KBinXml start
This commit is contained in:
41
eAmuseCore/KBinXML/Helpers.cs
Normal file
41
eAmuseCore/KBinXML/Helpers.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace eAmuseCore.KBinXML
|
||||
{
|
||||
static class EnumHelpers
|
||||
{
|
||||
public static uint FirstU32(this IEnumerable<byte> input)
|
||||
{
|
||||
input = input.Take(4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
input = input.Reverse();
|
||||
return BitConverter.ToUInt32(input.ToArray(), 0);
|
||||
}
|
||||
|
||||
public static int FirstI32(this IEnumerable<byte> input)
|
||||
{
|
||||
input = input.Take(4);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
input = input.Reverse();
|
||||
return BitConverter.ToInt32(input.ToArray(), 0);
|
||||
}
|
||||
|
||||
public static ushort FirstU16(this IEnumerable<byte> input)
|
||||
{
|
||||
input = input.Take(2);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
input = input.Reverse();
|
||||
return BitConverter.ToUInt16(input.ToArray(), 0);
|
||||
}
|
||||
|
||||
public static short FirstI16(this IEnumerable<byte> input)
|
||||
{
|
||||
input = input.Take(2);
|
||||
if (BitConverter.IsLittleEndian)
|
||||
input = input.Reverse();
|
||||
return BitConverter.ToInt16(input.ToArray(), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
155
eAmuseCore/KBinXML/KBinXML.cs
Normal file
155
eAmuseCore/KBinXML/KBinXML.cs
Normal file
@@ -0,0 +1,155 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Xml.Linq;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace eAmuseCore.KBinXML
|
||||
{
|
||||
public class KBinXML
|
||||
{
|
||||
const byte SIGNATURE = 0xA0;
|
||||
const byte SIG_COMPRESSED = 0x42;
|
||||
const byte SIG_UNCOMPRESSED = 0x45;
|
||||
|
||||
static KBinXML()
|
||||
{
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
}
|
||||
|
||||
private static Encoding GetEncoding(byte sig)
|
||||
{
|
||||
switch (sig)
|
||||
{
|
||||
case 0x00:
|
||||
case 0x80:
|
||||
return Encoding.GetEncoding(932);
|
||||
case 0x20:
|
||||
return Encoding.ASCII;
|
||||
case 0x40:
|
||||
return Encoding.GetEncoding("iso-8859-1");
|
||||
case 0x60:
|
||||
return Encoding.GetEncoding("EUC-JP");
|
||||
case 0xA0:
|
||||
return Encoding.UTF8;
|
||||
}
|
||||
|
||||
throw new ArgumentException("Unsupported encoding", "sig");
|
||||
}
|
||||
|
||||
private static byte GetEncodingSig(Encoding enc)
|
||||
{
|
||||
if (Encoding.UTF8.Equals(enc))
|
||||
return 0xA0;
|
||||
if (Encoding.GetEncoding(932).Equals(enc))
|
||||
return 0x80;
|
||||
if (Encoding.ASCII.Equals(enc))
|
||||
return 0x20;
|
||||
if (Encoding.GetEncoding("iso-8859-1").Equals(enc))
|
||||
return 0x40;
|
||||
if (Encoding.GetEncoding("EUC-JP").Equals(enc))
|
||||
return 0x60;
|
||||
|
||||
throw new ArgumentException("Unsupported encoding", "enc");
|
||||
}
|
||||
|
||||
private XDocument doc;
|
||||
private Encoding encoding;
|
||||
|
||||
public KBinXML(IEnumerable<byte> input)
|
||||
{
|
||||
|
||||
Parse(input);
|
||||
}
|
||||
|
||||
public KBinXML(XDocument doc)
|
||||
{
|
||||
this.doc = doc;
|
||||
}
|
||||
|
||||
private void Parse(IEnumerable<byte> input)
|
||||
{
|
||||
doc = new XDocument();
|
||||
|
||||
if (input.First() != SIGNATURE)
|
||||
throw new ArgumentException("Invalid signature", "input");
|
||||
input = input.Skip(1);
|
||||
|
||||
bool compressed;
|
||||
switch (input.First())
|
||||
{
|
||||
case SIG_COMPRESSED:
|
||||
compressed = true;
|
||||
break;
|
||||
case SIG_UNCOMPRESSED:
|
||||
compressed = false;
|
||||
break;
|
||||
default:
|
||||
throw new ArgumentException("Invalud compression info", "input");
|
||||
}
|
||||
input = input.Skip(1);
|
||||
|
||||
Console.WriteLine("Compressed: " + compressed);
|
||||
|
||||
byte encodingSig = input.First();
|
||||
input = input.Skip(1);
|
||||
|
||||
if (input.First() != (0xFF ^ encodingSig))
|
||||
throw new ArgumentException("Encoding signature failed to verify", "input");
|
||||
input = input.Skip(1);
|
||||
|
||||
encoding = GetEncoding(encodingSig);
|
||||
|
||||
uint nodeEnd = input.FirstU32();
|
||||
input = input.Skip(4);
|
||||
|
||||
IEnumerable<byte> nodeBuf = input.Take((int)nodeEnd);
|
||||
IEnumerable<byte> dataBuf = input.Skip((int)nodeEnd);
|
||||
|
||||
ParseNodes(nodeBuf, dataBuf, compressed);
|
||||
}
|
||||
|
||||
private void ParseNodes(IEnumerable<byte> nodeBuf, IEnumerable<byte> dataBuf, bool compressed)
|
||||
{
|
||||
uint dataSize = dataBuf.FirstU32();
|
||||
dataBuf = dataBuf.Skip(4);
|
||||
|
||||
XElement node = doc.Root;
|
||||
|
||||
bool nodesLeft = true;
|
||||
while (nodesLeft && nodeBuf.Any())
|
||||
{
|
||||
nodeBuf = nodeBuf.SkipWhile(b => b == 0);
|
||||
|
||||
byte nodeType = nodeBuf.First();
|
||||
nodeBuf = nodeBuf.Skip(1);
|
||||
|
||||
bool isArray = (nodeType & 64) != 0;
|
||||
nodeType = (byte)(nodeType & ~64);
|
||||
|
||||
XmlTypes.Entry nodeTypeEntry = XmlTypes.GetEntryByType(nodeType);
|
||||
|
||||
string name = null;
|
||||
if (nodeType != XmlTypes.NodeEnd.type && nodeType != XmlTypes.EndSection.type)
|
||||
{
|
||||
if (compressed)
|
||||
{
|
||||
name = SixBit.Unpack(ref nodeBuf);
|
||||
}
|
||||
else
|
||||
{
|
||||
int length = (nodeBuf.First() & ~64) + 1;
|
||||
nodeBuf = nodeBuf.Skip(1);
|
||||
|
||||
byte[] nameBytes = nodeBuf.Take(length).ToArray();
|
||||
nodeBuf = nodeBuf.Skip(length);
|
||||
|
||||
name = encoding.GetString(nameBytes);
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine("Name: " + name);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
37
eAmuseCore/KBinXML/SixBit.cs
Normal file
37
eAmuseCore/KBinXML/SixBit.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System;
|
||||
|
||||
namespace eAmuseCore.KBinXML
|
||||
{
|
||||
static class SixBit
|
||||
{
|
||||
static readonly string charmap = "0123456789:ABCDEFGHIJKLMNOPQRSTUVWXYZ_abcdefghijklmnopqrstuvwxyz";
|
||||
|
||||
public static string Unpack(ref IEnumerable<byte> nodeBuf)
|
||||
{
|
||||
int length = nodeBuf.First();
|
||||
nodeBuf = nodeBuf.Skip(1);
|
||||
|
||||
int length_bits = length * 6;
|
||||
int length_bytes = (length_bits + 7) / 8;
|
||||
|
||||
BitArray barr = new BitArray(nodeBuf.Take(length_bytes).ToArray());
|
||||
nodeBuf = nodeBuf.Skip(length_bytes);
|
||||
|
||||
StringBuilder res = new StringBuilder();
|
||||
for (int i = 0, pos = length_bits - 1; i < length; ++i)
|
||||
{
|
||||
int resI = 0;
|
||||
for (int j = 0; j < 6; ++j, --pos)
|
||||
if (barr.Get(pos))
|
||||
resI |= 1 << j;
|
||||
|
||||
res.Append(charmap[resI]);
|
||||
}
|
||||
return res.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
80
eAmuseCore/KBinXML/XmlTypes.cs
Normal file
80
eAmuseCore/KBinXML/XmlTypes.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
|
||||
namespace eAmuseCore.KBinXML
|
||||
{
|
||||
public static class XmlTypes
|
||||
{
|
||||
public class Entry
|
||||
{
|
||||
public byte type;
|
||||
public int size;
|
||||
public int count;
|
||||
public string[] names;
|
||||
}
|
||||
|
||||
public static readonly Entry NodeStart = new Entry
|
||||
{
|
||||
type = 1
|
||||
};
|
||||
|
||||
public static readonly Entry Attr = new Entry
|
||||
{
|
||||
type = 46
|
||||
};
|
||||
|
||||
public static readonly Entry NodeEnd = new Entry
|
||||
{
|
||||
type = 190
|
||||
};
|
||||
|
||||
public static readonly Entry EndSection = new Entry
|
||||
{
|
||||
type = 191
|
||||
};
|
||||
|
||||
private static Dictionary<string, Entry> nameLookupMap = new Dictionary<string, Entry>();
|
||||
private static Dictionary<byte, Entry> typeLookupMap = new Dictionary<byte, Entry>();
|
||||
|
||||
public static Entry GetEntryByName(string name)
|
||||
{
|
||||
if (nameLookupMap.ContainsKey(name))
|
||||
return nameLookupMap[name];
|
||||
|
||||
foreach (FieldInfo info in typeof(XmlTypes).GetFields())
|
||||
{
|
||||
if (!info.IsStatic)
|
||||
continue;
|
||||
Entry res = info.GetValue(null) as Entry;
|
||||
if (res == null || !res.names.Contains(name))
|
||||
continue;
|
||||
nameLookupMap[name] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Entry GetEntryByType(byte type)
|
||||
{
|
||||
if (typeLookupMap.ContainsKey(type))
|
||||
return typeLookupMap[type];
|
||||
|
||||
foreach (FieldInfo info in typeof(XmlTypes).GetFields())
|
||||
{
|
||||
if (!info.IsStatic)
|
||||
continue;
|
||||
Entry res = info.GetValue(null) as Entry;
|
||||
if (res == null || res.type != type)
|
||||
continue;
|
||||
typeLookupMap[type] = res;
|
||||
return res;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="System.Security.Cryptography.Algorithms" Version="4.3.1" />
|
||||
<PackageReference Include="System.Text.Encoding.CodePages" Version="4.5.1" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Linq;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
using eAmuseCore.Crypto;
|
||||
using eAmuseCore.Compression;
|
||||
using System.Collections;
|
||||
using eAmuseCore.KBinXML;
|
||||
|
||||
namespace eAmuseTest
|
||||
{
|
||||
@@ -36,13 +37,18 @@ namespace eAmuseTest
|
||||
0x4b, 0x66, 0x07, 0xc0, 0xd0, 0xb3
|
||||
};
|
||||
|
||||
var decryptedData = RC4.ApplyEAmuseInfo(eamuse_info, data).ToArray();
|
||||
compress = compress.ToLower();
|
||||
|
||||
Console.WriteLine(BytesToString(decryptedData));
|
||||
var decryptedData = RC4.ApplyEAmuseInfo(eamuse_info, data);
|
||||
var rawData = decryptedData;
|
||||
if (compress == "lz77")
|
||||
rawData = LZ77.Decompress(decryptedData);
|
||||
else if (compress != "none")
|
||||
throw new ArgumentException("Unsupported compression algorithm");
|
||||
|
||||
Console.WriteLine("Ok go");
|
||||
Console.WriteLine(BytesToString(rawData));
|
||||
|
||||
var rawData = LZ77.Decompress(decryptedData).ToArray();
|
||||
KBinXML kbinxml = new KBinXML(rawData);
|
||||
}
|
||||
|
||||
private static string BytesToString(IEnumerable<byte> bytes)
|
||||
|
||||
Reference in New Issue
Block a user