From 72e54eb50d05375550b4e7916ff100d11e66cfcd Mon Sep 17 00:00:00 2001 From: morkt Date: Fri, 14 Sep 2018 00:09:12 +0400 Subject: [PATCH] (Ai5Win): guess obfuscation scheme. --- ArcFormats/elf/ArcAi5Win.cs | 50 ++++++++++++++++++++++++++++--------- 1 file changed, 38 insertions(+), 12 deletions(-) diff --git a/ArcFormats/elf/ArcAi5Win.cs b/ArcFormats/elf/ArcAi5Win.cs index 87b7ced5..a0d168e7 100644 --- a/ArcFormats/elf/ArcAi5Win.cs +++ b/ArcFormats/elf/ArcAi5Win.cs @@ -2,7 +2,7 @@ //! \date Mon Jun 29 04:41:29 2015 //! \brief Ai5Win engine resource archive. // -// Copyright (C) 2015 by morkt +// Copyright (C) 2015-2018 by morkt // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to @@ -57,17 +57,13 @@ namespace GameRes.Formats.Elf public override bool IsHierarchic { get { return false; } } public override bool CanWrite { get { return false; } } - public static Dictionary KnownSchemes = new Dictionary(); - - public ArcAI5Opener () - { - Extensions = new string[] { "arc" }; - } + static Ai5Scheme DefaultScheme = new Ai5Scheme { KnownSchemes = new Dictionary() }; + public Dictionary KnownSchemes { get { return DefaultScheme.KnownSchemes; } } public override ResourceScheme Scheme { - get { return new Ai5Scheme { KnownSchemes = KnownSchemes }; } - set { KnownSchemes = ((Ai5Scheme)value).KnownSchemes; } + get { return DefaultScheme; } + set { DefaultScheme = (Ai5Scheme)value; } } public override ArcFile TryOpen (ArcView file) @@ -79,9 +75,11 @@ namespace GameRes.Formats.Elf return null; var reader = new Ai5ArcIndexReader (file, count); var dir = reader.TrySchemes (KnownSchemes.Values); - if (dir != null) - return new ArcFile (file, this, dir); - return null; + if (null == dir) + dir = reader.TrySchemes (reader.GuessSchemes()); + if (null == dir) + return null; + return new ArcFile (file, this, dir); } public override Stream OpenEntry (ArcFile arc, Entry entry) @@ -167,5 +165,33 @@ namespace GameRes.Formats.Elf else return null; } + + internal IEnumerable GuessSchemes () + { + if (m_count < 2) + yield break; + foreach (int name_length in NameLengths) + { + uint data_offset = (uint)((name_length + 8) * m_count + 4); + byte name_key = m_file.View.ReadByte (3 + name_length); + uint first_size = m_file.View.ReadUInt32 (4 + name_length); + uint first_offset = m_file.View.ReadUInt32 (8 + name_length); + uint offset_key = data_offset ^ first_offset; + uint second_offset = m_file.View.ReadUInt32 ((name_length+8) * 2) ^ offset_key; + if (second_offset < data_offset || second_offset >= m_file.MaxOffset) + continue; + uint size_key = (second_offset - data_offset) ^ first_size; + if (0 == offset_key || 0 == size_key) + continue; + yield return new ArcIndexScheme { + NameLength = name_length, + NameKey = name_key, + SizeKey = size_key, + OffsetKey = offset_key, + }; + } + } + + static readonly int[] NameLengths = { 0x14, 0x1E, 0x20, 0x100 }; } }