guess keys of DXA archives.

This commit is contained in:
morkt 2016-03-18 06:23:51 +04:00
parent 5bbd10789e
commit 9af7f41ef5
2 changed files with 52 additions and 5 deletions

View File

@ -61,13 +61,15 @@ namespace GameRes.Formats.DxLib
public DxOpener ()
{
Extensions = new string[] { "dxa", "hud", "usi", "med", "dat" };
Signatures = new uint[] { 0x19EF8ED4, 0xA9FCCEDD, 0x0AEE0FD3, 0 };
Signatures = new uint[] { 0x19EF8ED4, 0xA9FCCEDD, 0x0AEE0FD3, 0x5523F211, 0 };
}
public static IList<byte[]> KnownKeys = new List<byte[]>();
public override ArcFile TryOpen (ArcView file)
{
if (file.MaxOffset < 0x1C)
return null;
uint signature = file.View.ReadUInt32 (0);
foreach (var key in KnownKeys)
{
@ -79,13 +81,53 @@ namespace GameRes.Formats.DxLib
var dir = ReadIndex (file, version, key);
if (null != dir)
{
// move last used key to the top of the known keys list
KnownKeys.Remove (key);
if (KnownKeys[0] != key)
{
// move last used key to the top of the known keys list
KnownKeys.Remove (key);
KnownKeys.Insert (0, key);
}
return new DxArchive (file, this, dir, key);
}
return null;
}
}
return GuessKey (file);
}
ArcFile GuessKey (ArcView file)
{
if (file.MaxOffset > uint.MaxValue)
return null;
var key = new byte[12];
for (short version = 4; version >= 1; --version)
{
file.View.Read (0, key, 0, 12);
key[0] ^= (byte)'D';
key[1] ^= (byte)'X';
key[2] ^= (byte)version;
int base_offset = version > 3 ? 0x1C : 0x18;
key[8] ^= (byte)base_offset;
uint key0 = LittleEndian.ToUInt32 (key, 0);
uint index_offset = file.View.ReadUInt32 (12) ^ key0;
if (index_offset <= base_offset || index_offset >= file.MaxOffset)
continue;
uint index_size = (uint)(file.MaxOffset - index_offset);
if (index_size > 0xFFFFFF)
continue;
key[4] ^= (byte)index_size;
key[5] ^= (byte)(index_size >> 8);
key[6] ^= (byte)(index_size >> 16);
try
{
var dir = ReadIndex (file, version, key);
if (null != dir)
{
KnownKeys.Insert (0, key);
return new DxArchive (file, this, dir, key);
}
break;
}
catch { /* ignore parse errors */ }
}
return null;
}
@ -184,6 +226,8 @@ namespace GameRes.Formats.DxLib
FileTable = LittleEndian.ToUInt32 (header, 0x0c),
DirTable = LittleEndian.ToUInt32 (header, 0x10),
};
if (dx.DirTable >= dx.IndexSize || dx.FileTable >= dx.IndexSize)
return null;
using (var encrypted = file.CreateStream (dx.IndexOffset, dx.IndexSize))
using (var index = new EncryptedStream (encrypted, dx.IndexOffset, key))
using (var reader = new IndexReader (dx, version, index))

View File

@ -34,6 +34,7 @@ Remember11<br/>
11gatsu no Arcadia<br/>
Chou Dengeki Stryker<br/>
Chou Jikuu Bakuren Monogatari ~door pi chu~<br/>
Eiken Kikaku<br/>
H2O -Footprints in the Sand-<br/>
Melty Moment<br/>
Traveling Stars<br/>
@ -424,6 +425,7 @@ X Change 2<br/>
X Change 2R<br/>
Ryoujoku Gojuusou<br/>
Hissatsu Chikannin II<br/>
Tokumei Sentai Sirenger<br/>
Tokumei Sentai Yuzu Ranger<br/>
</td></tr>
<tr class="odd"><td>*.cwp</td><td><tt>CWDP</tt></td><td>Yes</td></tr>
@ -455,7 +457,7 @@ Gakuen ~Nerawareta Chitai~<br/>
Kimon Youitan<br/>
Unbalance<br/>
</td></tr>
<tr class="odd"><td>*.lib<br/>*.dat</td><td><tt>LIB</tt><br/><tt>LIBP</tt><br/><tt>LIBU</tt></td><td>No</td><td rowspan="2">Malie</td><td rowspan="2">
<tr class="odd"><td>*.lib<br/>*.dat</td><td><tt>LIB</tt><br/><tt>LIBP</tt><br/><tt>LIBU</tt><span class="footnote">encrypted</span></td><td>No</td><td rowspan="2">Malie</td><td rowspan="2">
Angel Crown<br/>
Dies irae<br/>
Dies irae ~Amantes amentes~<br/>
@ -577,6 +579,7 @@ Soukai no Valkyria <br/>
Ashita wa Kitto, Haremasu you ni<br/>
Cross Quartz<br/>
Hyakki Yakou<br/>
Saikyou Goshujin-sama! -Mighty My Master-<br/>
</td></tr>
<tr class="odd"><td>*.tcd</td><td><tt>TCD3</tt></td><td>No</td><td rowspan="2">TopCat</td><td rowspan="2">
Atori no Sora to Shinchuu no Tsuki<br/>