/* * Outputs the specific XOR key for the given version. * * @param version The pack file version * @param key The outputted key block * */ public static void GetXorKey(PackVersion version, out byte[] key) { switch (version) { case PackVersion.MS2F: key = MS2F_XOR.Value; break; case PackVersion.NS2F: key = NS2F_XOR.Value; break; case PackVersion.OS2F: key = OS2F_XOR.Value; break; case PackVersion.PS2F: key = PS2F_XOR.Value; break; default: { // Nexon always defaults to MS2F here. key = MS2F_XOR.Value; break; } } }
public PackFileHeaderVer3(PackVersion version, BinaryReader reader) : this(version) { this.BufferFlag = (Encryption)reader.ReadUInt32(); //[ecx+8] this.FileIndex = reader.ReadInt32(); //[ecx+12] this.EncodedFileSize = reader.ReadUInt32(); //[ecx+16] this.reserved[0] = reader.ReadInt32(); //[ecx+20] this.CompressedFileSize = reader.ReadUInt64(); //[ecx+24] | [ecx+28] this.FileSize = reader.ReadUInt64(); //[ecx+32] | [ecx+36] this.Offset = reader.ReadUInt64(); //[ecx+40] | [ecx+44] }
public static PackStreamVer3 ParseHeader(BinaryReader reader, PackVersion version) { return(new PackStreamVer3(version) { FileListCount = reader.ReadUInt32(), reserved = reader.ReadUInt32(), CompressedDataSize = reader.ReadUInt64(), EncodedDataSize = reader.ReadUInt64(), CompressedHeaderSize = reader.ReadUInt64(), EncodedHeaderSize = reader.ReadUInt64(), DataSize = reader.ReadUInt64(), HeaderSize = reader.ReadUInt64() }); }
public static PackFileHeaderVer3 CreateHeader(PackVersion version, int index, Encryption flag, ulong offset, byte[] data) { CryptoManager.Encrypt(version, data, flag, out uint size, out uint compressedSize, out uint encodedSize); return(new PackFileHeaderVer3(version) { BufferFlag = flag, FileIndex = index, EncodedFileSize = encodedSize, CompressedFileSize = compressedSize, FileSize = size, Offset = offset }); }
/* * Outputs the Key and IV blocks for the specified version. * * @param version The pack file version * @param uKeyOffset The key index to output (this is compressedSize) * @param userKey The outputted Key block * @param ivChain The outputted IV (CTR) block * */ public static void GetKeyAndIV(PackVersion version, uint keyOffset, out byte[] userKey, out byte[] ivChain) { IMultiArray key; IMultiArray iv; switch (version) { case PackVersion.MS2F: key = MS2F_KEY; iv = MS2F_IV; break; case PackVersion.NS2F: key = NS2F_KEY; iv = NS2F_IV; break; case PackVersion.OS2F: key = OS2F_KEY; iv = OS2F_IV; break; case PackVersion.PS2F: key = PS2F_KEY; iv = PS2F_IV; break; default: { throw new Exception("ERROR generating Key/IV: the specified package version does not exist!"); } } userKey = new byte[KEY_LEN]; ivChain = new byte[IV_LEN]; for (int i = 0; i < KEY_LEN; i++) { userKey[i] = key[(keyOffset & 0x7F)][i]; if (i < IV_LEN) { ivChain[i] = iv[(keyOffset & 0x7F)][i]; } } }
private static byte[] EncryptXor(PackVersion version, byte[] src, uint size, uint sizeCompressed) { CipherKeys.GetXorKey(version, out byte[] key); uint uBlock = size >> 2; uint uBlockOffset = 0; int nKeyOffset = 0; if (uBlock != 0) { while (uBlockOffset < uBlock) { uint pBlockData = BitConverter.ToUInt32(src, (int)(4 * uBlockOffset)) ^ BitConverter.ToUInt32(key, 4 * nKeyOffset); Buffer.BlockCopy(BitConverter.GetBytes(pBlockData), 0, src, (int)(4 * uBlockOffset), sizeof(uint)); nKeyOffset = ((ushort)nKeyOffset + 1) & 0x1FF; uBlockOffset++; } } uBlock = (size & 3); if (uBlock != 0) { int nStart = (int)(4 * uBlockOffset); uBlockOffset = 0; nKeyOffset = 0; while (uBlockOffset < uBlock) { src[nStart + uBlockOffset++] ^= (byte)(key[nKeyOffset]); nKeyOffset = ((ushort)nKeyOffset + 1) & 0x7FF; } } return(src); }
// Decryption Routine: Base64 -> AES -> Zlib private static byte[] Decrypt(PackVersion version, uint size, uint sizeCompressed, Encryption flag, byte[] src) { if (flag.HasFlag(Encryption.Aes)) { // Get the AES Key/IV for transformation CipherKeys.GetKeyAndIV(version, sizeCompressed, out byte[] key, out byte[] iv); // Decode the base64 encoded string src = Convert.FromBase64String(Encoding.UTF8.GetString(src)); // Decrypt the AES encrypted block AESCipher pCipher = new AESCipher(key, iv); pCipher.TransformBlock(src, 0, size, src, 0); } else if (flag.HasFlag(Encryption.Xor)) { // Decrypt the XOR encrypted block src = EncryptXor(version, src, size, sizeCompressed); } return(flag.HasFlag(Encryption.Zlib) ? ZlibStream.UncompressBuffer(src) : src); }
// Encryption Routine: Zlib -> AES -> Base64 public static byte[] Encrypt(PackVersion version, byte[] src, Encryption flag, out uint size, out uint sizeCompressed, out uint sizeEncoded) { byte[] pEncrypted; if (flag.HasFlag(Encryption.Zlib)) { pEncrypted = ZlibStream.CompressBuffer(src); } else { pEncrypted = new byte[src.Length]; Buffer.BlockCopy(src, 0, pEncrypted, 0, src.Length); } size = (uint)src.Length; sizeCompressed = (uint)pEncrypted.Length; if (flag.HasFlag(Encryption.Aes)) { // Get the AES Key/IV for transformation CipherKeys.GetKeyAndIV(version, sizeCompressed, out byte[] key, out byte[] iv); // Perform AES block encryption var pCipher = new AESCipher(key, iv); pCipher.TransformBlock(pEncrypted, 0, size, pEncrypted, 0); // Encode the encrypted data into a base64 encoded string pEncrypted = Encoding.UTF8.GetBytes(Convert.ToBase64String(pEncrypted)); } else if (flag.HasFlag(Encryption.Xor)) { // Perform XOR block encryption pEncrypted = EncryptXor(version, pEncrypted, size, sizeCompressed); } sizeEncoded = (uint)pEncrypted.Length; return(pEncrypted); }
private PackFileHeaderVer3(PackVersion version) { this.Version = version; this.reserved = new int[1]; }
private PackStreamVer3(PackVersion version) { this.Version = version; this.FileList = new List <PackFileEntry>(); }
private PackFileHeaderVer3(PackVersion version) { Version = version; Reserved = new int[1]; }