Added new entry

This commit is contained in:
Razmoth
2023-06-10 20:19:18 +04:00
parent 3806f1119e
commit f65451da33
3 changed files with 115 additions and 1 deletions

View File

@@ -169,6 +169,9 @@ namespace AssetStudio
case GameType.HelixWaltz2:
reader = ParseHelixWaltz2(reader);
break;
case GameType.AnchorPanic:
reader = DecryptAnchorPanic(reader);
break;
}
}
if (reader.FileType == FileType.BundleFile && game.Type.IsBlockFile())

View File

@@ -32,6 +32,7 @@ namespace AssetStudio
Games.Add(index++, new Game(GameType.ShiningNikki));
Games.Add(index++, new Game(GameType.HelixWaltz2));
Games.Add(index++, new Game(GameType.NetEase));
Games.Add(index++, new Game(GameType.AnchorPanic));
}
public static Game GetGame(GameType gameType) => GetGame((int)gameType);
public static Game GetGame(int index)
@@ -134,7 +135,8 @@ namespace AssetStudio
FantasyOfWind,
ShiningNikki,
HelixWaltz2,
NetEase
NetEase,
AnchorPanic
}
public static class GameTypes

View File

@@ -7,6 +7,7 @@ using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using static AssetStudio.BundleFile;
using static AssetStudio.Crypto;
@@ -421,5 +422,113 @@ namespace AssetStudio
return new FileReader(reader.FullPath, ms);
}
public static FileReader DecryptAnchorPanic(FileReader reader)
{
const int BlockSize = 0x800;
var data = reader.ReadBytes(0x1000);
reader.Position = 0;
var idx = data.Search("UnityFS");
if (idx != -1)
{
return ParseAlchemyStars(reader);
}
var key = GetKey(Path.GetFileNameWithoutExtension(reader.FileName));
var chunkIndex = 0;
MemoryStream ms = new();
while (reader.Remaining > 0)
{
var chunkSize = Math.Min((int)reader.Remaining, BlockSize);
var chunk = reader.ReadBytes(chunkSize);
if (IsEncrypt((int)reader.Length, chunkIndex++))
RC4(chunk, key);
ms.Write(chunk);
}
ms.Position = 0;
return new FileReader(reader.FullPath, ms);
bool IsEncrypt(int fileSize, int chunkIndex)
{
const int MaxEncryptChunkIndex = 4;
if (chunkIndex == 0)
return true;
if (fileSize / BlockSize == chunkIndex)
return true;
if (MaxEncryptChunkIndex < chunkIndex)
return false;
return fileSize % 2 == chunkIndex % 2;
}
byte[] GetKey(string fileName)
{
const string Key = "KxZKZolAT3QXvsUU";
string keyHash = CalculateMD5(Key);
string nameHash = CalculateMD5(fileName);
var key = $"{keyHash[..5]}leiyan{nameHash[Math.Max(0, nameHash.Length - 5)..]}";
return Encoding.UTF8.GetBytes(key);
string CalculateMD5(string str)
{
var bytes = Encoding.UTF8.GetBytes(str);
bytes = MD5.HashData(bytes);
return Convert.ToHexString(bytes).ToLowerInvariant();
}
}
void RC4(Span<byte> data, byte[] key)
{
int[] S = new int[0x100];
for (int _ = 0; _ < 0x100; _++)
{
S[_] = _;
}
int[] T = new int[0x100];
if (key.Length == 0x100)
{
Buffer.BlockCopy(key, 0, T, 0, key.Length);
}
else
{
for (int _ = 0; _ < 0x100; _++)
{
T[_] = key[_ % key.Length];
}
}
int i = 0;
int j = 0;
for (i = 0; i < 0x100; i++)
{
j = (j + S[i] + T[i]) % 0x100;
(S[j], S[i]) = (S[i], S[j]);
}
i = j = 0;
for (int iteration = 0; iteration < data.Length; iteration++)
{
i = (i + 1) % 0x100;
j = (j + S[i]) % 0x100;
(S[j], S[i]) = (S[i], S[j]);
var K = (uint)S[(S[j] + S[i]) % 0x100];
data[iteration] ^= Convert.ToByte(K);
}
}
}
}
}