Update OPFP
This commit is contained in:
@@ -1,39 +1,71 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace AssetStudio
|
namespace AssetStudio
|
||||||
{
|
{
|
||||||
public static class OPFPUtils
|
public static class OPFPUtils
|
||||||
{
|
{
|
||||||
public static readonly string[] EncrytpedFolders = { "UITexture", "DynamicAtlas", "UI", "Atlas" };
|
private static readonly string BaseFolder = "BundleResources";
|
||||||
|
private static readonly string[] V0_Prefixes = { "UI/", "Atlas/", "UITexture/" };
|
||||||
|
private static readonly string[] V1_Prefixes = { "DynamicAtlas/", "Atlas/Skill", "Atlas/PlayerTitle", "UITexture/HeroCardEP12", "UITexture/HeroCardEP13" };
|
||||||
|
|
||||||
public static void Decrypt(Span<byte> data, string path)
|
public static void Decrypt(Span<byte> data, string path)
|
||||||
{
|
{
|
||||||
if (IsEncryptionBundle(path, out var key))
|
if (IsEncryptionBundle(path, out var key, out var version))
|
||||||
{
|
{
|
||||||
|
switch (version)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
data[0] ^= key;
|
data[0] ^= key;
|
||||||
for (int i = 1; i < data.Length; i++)
|
for (int i = 1; i < data.Length; i++)
|
||||||
{
|
{
|
||||||
data[i] ^= data[i - 1];
|
data[i] ^= data[i - 1];
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
for (int i = 1; i < data.Length; i++)
|
||||||
|
{
|
||||||
|
var idx = (i + data.Length + key * key) % (i + 1);
|
||||||
|
(data[i], data[idx]) = (data[idx], data[i]);
|
||||||
|
data[i] ^= key;
|
||||||
|
data[idx] ^= key;
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
private static bool IsEncryptionBundle(string path, out byte key)
|
}
|
||||||
|
private static bool IsEncryptionBundle(string path, out byte key, out int version)
|
||||||
{
|
{
|
||||||
path = path.Replace("\\", "/");
|
if (IsFixedPath(path, out var relativePath))
|
||||||
foreach(var encryptedFolder in EncrytpedFolders)
|
|
||||||
{
|
{
|
||||||
var index = path.IndexOf(encryptedFolder, 0, path.Length, StringComparison.OrdinalIgnoreCase);
|
if (V1_Prefixes.Any(prefix => relativePath.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
|
||||||
if (index != -1)
|
|
||||||
{
|
{
|
||||||
var assetPath = path[index..];
|
key = (byte)Path.GetFileName(relativePath).Length;
|
||||||
if (assetPath.StartsWith(encryptedFolder, StringComparison.OrdinalIgnoreCase))
|
version = 1;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else if (V0_Prefixes.Any(prefix => relativePath.StartsWith(prefix, StringComparison.OrdinalIgnoreCase)))
|
||||||
{
|
{
|
||||||
key = (byte)assetPath.Length;
|
key = (byte)relativePath.Length;
|
||||||
|
version = 0;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
key = 0x00;
|
key = 0x00;
|
||||||
|
version = 0;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
private static bool IsFixedPath(string path, out string fixedPath)
|
||||||
|
{
|
||||||
|
var dirs = path.Split(Path.DirectorySeparatorChar);
|
||||||
|
if (dirs.Contains(BaseFolder))
|
||||||
|
{
|
||||||
|
var idx = Array.IndexOf(dirs, BaseFolder);
|
||||||
|
fixedPath = string.Join(Path.DirectorySeparatorChar, dirs[(idx+1)..]).Replace("\\", "/");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
fixedPath = string.Empty;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user