Skip to content

Commit

Permalink
Merge pull request #1506 from SteamRE/v4-manifest
Browse files Browse the repository at this point in the history
Fix parsing v4 depot manifests, add test for it
  • Loading branch information
xPaw authored Feb 7, 2025
2 parents 293a0ce + d57b867 commit 39c6a3a
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 8 deletions.
6 changes: 5 additions & 1 deletion SteamKit2/SteamKit2/Types/DepotManifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,10 @@ void InternalDeserialize( Stream stream )
uint marker = br.ReadUInt32();
if ( marker != magic )
throw new InvalidDataException( "Unable to find end of message marker for depot manifest" );
break;

// This is an intentional return because v4 manifest does not have the separate sections
// and it will be parsed by ParseBinaryManifest. If we get here, the entire buffer has been already processed.
return;

case DepotManifest.PROTOBUF_PAYLOAD_MAGIC:
uint payload_length = br.ReadUInt32();
Expand Down Expand Up @@ -393,6 +396,7 @@ void ParseBinaryManifest(Steam3Manifest manifest)
CreationTime = manifest.CreationTime;
TotalUncompressedSize = manifest.TotalUncompressedSize;
TotalCompressedSize = manifest.TotalCompressedSize;
EncryptedCRC = manifest.EncryptedCRC;

foreach (var file_mapping in manifest.Mapping)
{
Expand Down
5 changes: 5 additions & 0 deletions SteamKit2/SteamKit2/Types/Manifest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,11 @@ internal void Deserialize( BinaryReader ds )

Version = ds.ReadUInt32();

if ( Version != CURRENT_VERSION )
{
throw new NotImplementedException( $"Only version {CURRENT_VERSION} is supported." );
}

DepotID = ds.ReadUInt32();

ManifestGID = ds.ReadUInt64();
Expand Down
48 changes: 41 additions & 7 deletions SteamKit2/Tests/DepotManifestFacts.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,34 @@ namespace Tests
{
public class DepotManifestFacts
{
private static readonly byte[] Depot440DecryptionKey =
[
0x44, 0xCE, 0x5C, 0x52, 0x97, 0xA4, 0x15, 0xA1,
0xA6, 0xF6, 0x9C, 0x85, 0x60, 0x37, 0xA5, 0xA2,
0xFD, 0xD8, 0x2C, 0xD4, 0x74, 0xFA, 0x65, 0x9E,
0xDF, 0xB4, 0xD5, 0x9B, 0x2A, 0xBC, 0x55, 0xFC,
];

[Fact]
public void ParsesAndDecryptsManifestVersion4()
{
var assembly = Assembly.GetExecutingAssembly();
using var stream = assembly.GetManifestResourceStream( "Tests.Files.depot_440_1118032470228587934_v4.manifest" );
using var ms = new MemoryStream();
stream.CopyTo( ms );

var manifestData = ms.ToArray();

var depotManifest = DepotManifest.Deserialize( manifestData );

Assert.True( depotManifest.FilenamesEncrypted );
Assert.Equal( 1195249848u, depotManifest.EncryptedCRC );

depotManifest.DecryptFilenames( Depot440DecryptionKey );

TestDecryptedManifest( depotManifest );
}

[Fact]
public void ParsesAndDecryptsManifest()
{
Expand All @@ -23,13 +51,9 @@ public void ParsesAndDecryptsManifest()
var depotManifest = DepotManifest.Deserialize( manifestData );

Assert.True( depotManifest.FilenamesEncrypted );
Assert.Equal( 1606273976u, depotManifest.EncryptedCRC );

depotManifest.DecryptFilenames( [
0x44, 0xCE, 0x5C, 0x52, 0x97, 0xA4, 0x15, 0xA1,
0xA6, 0xF6, 0x9C, 0x85, 0x60, 0x37, 0xA5, 0xA2,
0xFD, 0xD8, 0x2C, 0xD4, 0x74, 0xFA, 0x65, 0x9E,
0xDF, 0xB4, 0xD5, 0x9B, 0x2A, 0xBC, 0x55, 0xFC
] );
depotManifest.DecryptFilenames( Depot440DecryptionKey );

TestDecryptedManifest( depotManifest );
}
Expand Down Expand Up @@ -112,8 +136,8 @@ private static void TestDecryptedManifest( DepotManifest depotManifest )
Assert.Equal( 1118032470228587934ul, depotManifest.ManifestGID );
Assert.Equal( 825745u, depotManifest.TotalUncompressedSize );
Assert.Equal( 43168u, depotManifest.TotalCompressedSize );
Assert.Equal( 1606273976u, depotManifest.EncryptedCRC );
Assert.Equal( 7, depotManifest.Files.Count );
Assert.Equal( new DateTime( 2013, 4, 17, 20, 39, 24, DateTimeKind.Utc ), depotManifest.CreationTime );

Assert.Equal( Path.Join( "bin", "dxsupport.cfg" ), depotManifest.Files[ 0 ].FileName );
Assert.Equal( Path.Join( "bin", "dxsupport.csv" ), depotManifest.Files[ 1 ].FileName );
Expand All @@ -125,11 +149,21 @@ private static void TestDecryptedManifest( DepotManifest depotManifest )

Assert.Equal( ( EDepotFileFlag )0, depotManifest.Files[ 0 ].Flags );
Assert.Equal( 398709u, depotManifest.Files[ 0 ].TotalSize );
Assert.Equal( Convert.FromHexString( "BAC8E2657470B2EB70D6DDCD6C07004BE8738697" ), depotManifest.Files[ 2 ].FileHash );

foreach ( var file in depotManifest.Files )
{
Assert.Equal( file.FileNameHash, SHA1.HashData( Encoding.UTF8.GetBytes( file.FileName.Replace( '/', '\\' ) ) ) );
Assert.NotNull( file.LinkTarget );
Assert.Single( file.Chunks );
}

var chunk = depotManifest.Files[ 6 ].Chunks[ 0 ];
Assert.Equal( 963249608u, chunk.Checksum );
Assert.Equal( 144u, chunk.CompressedLength );
Assert.Equal( 17u, chunk.UncompressedLength );
Assert.Equal( 0u, chunk.Offset );
Assert.Equal( Convert.FromHexString( "94020BDE145A521EDEC9A9424E7A90FD042481E9" ), chunk.ChunkID );
}
}
}
Binary file not shown.

0 comments on commit 39c6a3a

Please sign in to comment.