Skip to content

Commit

Permalink
Begin Elden Ring support
Browse files Browse the repository at this point in the history
  • Loading branch information
googleben committed Mar 10, 2022
1 parent 84bdc67 commit fe7cd3f
Show file tree
Hide file tree
Showing 15 changed files with 299 additions and 73 deletions.
14 changes: 10 additions & 4 deletions BinderTool.Core/Bdt5/Bdt5FileStream.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@ public Bdt5FileStream(Stream inputStream)
_inputStream = inputStream;
}

public MemoryStream Read(long fileOffset, long fileSize)
public Stream Read(long fileOffset, long fileSize)
{
if (fileOffset + fileSize > _inputStream.Length)
throw new EndOfStreamException();
_inputStream.Seek(fileOffset, SeekOrigin.Begin);

byte[] buffer = new byte[fileSize];
_inputStream.Read(buffer, 0, (int) fileSize);
return new MemoryStream(buffer);
if (fileSize < Bdt5InnerStream.MAX_STREAM_LEN)
{
byte[] buffer = new byte[fileSize];
_inputStream.Read(buffer, 0, (int)fileSize);
return new MemoryStream(buffer);
}
var ans = new Bdt5InnerStream(_inputStream, fileSize);
_inputStream.Seek(fileSize, SeekOrigin.Current);
return ans;
}

public static Bdt5FileStream OpenFile(string path, FileMode mode, FileAccess access)
Expand Down
102 changes: 102 additions & 0 deletions BinderTool.Core/Bdt5/Bdt5InnerStream.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO;

namespace BinderTool.Core.Bdt5
{
public class Bdt5InnerStream : Stream
{
public const int MAX_STREAM_LEN = 1_000_000;

private List<MemoryStream> streams;

private long length;


public override long Length => length;

public override long Position { get; set; }

public override bool CanRead => true;

public override bool CanSeek => true;

public override bool CanWrite => true;

public Bdt5InnerStream(Stream from, long length, long offset)
{
this.length = length;
this.streams = new List<MemoryStream>();
long startPos = from.Position;
for (long pos = 0; pos < length; pos += MAX_STREAM_LEN)
{
byte[] buf = new byte[MAX_STREAM_LEN];
from.Seek(offset + pos, SeekOrigin.Begin);
from.Read(buf, 0, (int)Math.Min(length - pos, MAX_STREAM_LEN));
streams.Add(new MemoryStream(buf));
}
from.Seek(startPos, SeekOrigin.Begin);
}
public Bdt5InnerStream(Stream from, long length) : this(from, length, 0) {}
public Bdt5InnerStream(long length)
{
this.length = length;
this.streams = new List<MemoryStream>();
for (long pos = 0; pos < length; pos += MAX_STREAM_LEN)
{
byte[] buf = new byte[MAX_STREAM_LEN];
streams.Add(new MemoryStream(buf));
}
}

public override void Flush() {}

public override int Read(byte[] buffer, int offset, int count)
{
if (this.Position >= this.length) return 0;
long startPos = this.Position;
long end = Math.Min(this.Position + count, this.length);
while (this.Position < end)
{
var s = this.streams[(int)(this.Position / MAX_STREAM_LEN)];
s.Seek(this.Position % MAX_STREAM_LEN, SeekOrigin.Begin);
var read = s.Read(buffer, offset, count);
this.Position += read;
offset += read;
count -= read;
}
return (int)(end - startPos);
}

public override long Seek(long offset, SeekOrigin origin)
{
if (origin == SeekOrigin.Begin) this.Position = offset;
if (origin == SeekOrigin.Current) this.Position += offset;
if (origin == SeekOrigin.End) this.Position = this.length + offset;
return this.Position;
}

public override void SetLength(long value)
{
this.length = value;
}

public override void Write(byte[] buffer, int offset, int count)
{
long end = this.Position + count;
while (this.Position < end)
{
var s = this.streams[(int)(this.Position / MAX_STREAM_LEN)];
s.Seek(this.Position % MAX_STREAM_LEN, SeekOrigin.Begin);
var toWrite = (int)Math.Min(s.Length - s.Position, count);
s.Write(buffer, offset, toWrite);
this.Position += toWrite;
offset += toWrite;
count -= toWrite;
}
}
}
}
24 changes: 11 additions & 13 deletions BinderTool.Core/Bhd5/Bhd5BucketEntry.cs
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
using System.IO;
using System;
using System.IO;

namespace BinderTool.Core.Bhd5
{
public class Bhd5BucketEntry
{
public uint FileNameHash { get; private set; }
public ulong FileNameHash { get; private set; }
public long FileSize { get; set; }
public long PaddedFileSize { get; set; }
public long FileOffset { get; private set; }
Expand All @@ -15,22 +16,19 @@ public class Bhd5BucketEntry
public static Bhd5BucketEntry Read(BinaryReader reader, GameVersion version)
{
Bhd5BucketEntry result = new Bhd5BucketEntry();
result.FileNameHash = reader.ReadUInt32();
result.FileNameHash = reader.ReadUInt64();
result.PaddedFileSize = reader.ReadUInt32();
result.FileSize = reader.ReadUInt32();
if (result.FileSize != 0)
{
//Console.WriteLine("FS not 0");
}
result.FileOffset = reader.ReadInt64();

long saltedHashOffset = reader.ReadInt64();
long aesKeyOffset = reader.ReadInt64();

switch (version)
{
case GameVersion.DarkSouls3:
case GameVersion.Sekiro:
result.FileSize = reader.ReadInt64();
break;
default:
result.FileSize = result.PaddedFileSize;
break;
}


if (saltedHashOffset != 0)
{
Expand Down
1 change: 1 addition & 0 deletions BinderTool.Core/BinderTool.Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
</ItemGroup>
<ItemGroup>
<Compile Include="Bdf4\Bdf4FileStream.cs" />
<Compile Include="Bdt5\Bdt5InnerStream.cs" />
<Compile Include="Bhd5\Bhd5Range.cs" />
<Compile Include="Bdt5\Bdt5FileStream.cs" />
<Compile Include="Bhd5\Bhd5AesKey.cs" />
Expand Down
8 changes: 6 additions & 2 deletions BinderTool.Core/Bnd4/Bnd4File.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,9 +83,13 @@ private void Read(Stream inputStream)
reader.Seek(fileNameOffset);
fileName = reader.ReadNullTerminatedString();
}
if (fileName.Contains("param")) Console.WriteLine($"{fileName} {fileEntrySize} {fileEntryOffset}");

reader.Seek(fileEntryOffset);
_entries.Add(Bnd4FileEntry.Read(inputStream, fileEntrySize, fileName));
if (fileName.Length > 0 && fileEntrySize > 0 && fileEntryOffset > 0)
{
reader.Seek(fileEntryOffset);
_entries.Add(Bnd4FileEntry.Read(inputStream, fileEntrySize, fileName));
}
reader.Seek(position);
}
}
Expand Down
65 changes: 37 additions & 28 deletions BinderTool.Core/CryptographyUtility.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.IO;
using BinderTool.Core.Bdt5;
using BinderTool.Core.Bhd5;
using Org.BouncyCastle.Crypto;
using Org.BouncyCastle.Crypto.Engines;
Expand All @@ -11,62 +12,65 @@ namespace BinderTool.Core
{
public static class CryptographyUtility
{
public static MemoryStream DecryptAesEcb(Stream inputStream, byte[] key)
public static Stream DecryptAesEcb(Stream inputStream, byte[] key)
{
var cipher = CreateAesEcbCipher(key);
return DecryptAes(inputStream, cipher, inputStream.Length);
}

public static MemoryStream DecryptAesCbc(Stream inputStream, byte[] key, byte[] iv)
public static Stream DecryptAesCbc(Stream inputStream, byte[] key, byte[] iv)
{
AesEngine engine = new AesEngine();
var engine = new CbcBlockCipher(new AesEngine());
KeyParameter keyParameter = new KeyParameter(key);
ICipherParameters parameters = new ParametersWithIV(keyParameter, iv);

BufferedBlockCipher cipher = new BufferedBlockCipher(new CbcBlockCipher(engine));
cipher.Init(false, parameters);
return DecryptAes(inputStream, cipher, inputStream.Length);
engine.Init(false, parameters);
return DecryptAes(inputStream, engine, inputStream.Length);
}

public static MemoryStream DecryptAesCtr(Stream inputStream, byte[] key, byte[] iv)
public static Stream DecryptAesCtr(Stream inputStream, byte[] key, byte[] iv)
{
AesEngine engine = new AesEngine();
SicBlockCipher engine = new SicBlockCipher(new AesEngine());
KeyParameter keyParameter = new KeyParameter(key);
ICipherParameters parameters = new ParametersWithIV(keyParameter, iv);

BufferedBlockCipher cipher = new BufferedBlockCipher(new SicBlockCipher(engine));
cipher.Init(false, parameters);
return DecryptAes(inputStream, cipher, inputStream.Length);
engine.Init(false, parameters);
return DecryptAes(inputStream, engine, inputStream.Length);
}

private static BufferedBlockCipher CreateAesEcbCipher(byte[] key)
private static IBlockCipher CreateAesEcbCipher(byte[] key)
{
AesEngine engine = new AesEngine();
KeyParameter parameter = new KeyParameter(key);
BufferedBlockCipher cipher = new BufferedBlockCipher(engine);
cipher.Init(false, parameter);
return cipher;
engine.Init(false, parameter);
return engine;
}

private static MemoryStream DecryptAes(Stream inputStream, BufferedBlockCipher cipher, long length)
private static Stream DecryptAes(Stream inputStream, IBlockCipher cipher, long length)
{
int blockSize = cipher.GetBlockSize();
int inputLength = (int)length;
int paddedLength = inputLength;
long inputLength = length;
long paddedLength = inputLength;
if (paddedLength % blockSize > 0)
{
paddedLength += blockSize - paddedLength % blockSize;
}

byte[] input = new byte[paddedLength];
byte[] output = new byte[cipher.GetOutputSize(paddedLength)];
byte[] input = new byte[blockSize];
byte[] output = new byte[blockSize];
var outputStream = new Bdt5.Bdt5InnerStream(paddedLength);

inputStream.Read(input, 0, inputLength);
int len = cipher.ProcessBytes(input, 0, input.Length, output, 0);
cipher.DoFinal(output, len);
for (long pos = 0; pos < inputLength; pos += blockSize)
{
int read = inputStream.Read(input, 0, blockSize);
if (read < blockSize)
{
for (int i = read; i < blockSize; i++) input[i] = 0;
}
cipher.ProcessBlock(input, 0, output, 0);
outputStream.Write(output, 0, blockSize);
}

MemoryStream outputStream = new MemoryStream();
outputStream.Write(output, 0, inputLength);
outputStream.Seek(0, SeekOrigin.Begin);
return outputStream;
}
Expand Down Expand Up @@ -135,7 +139,7 @@ public static AsymmetricKeyParameter GetKeyOrDefault(string key)
}
}

public static void DecryptAesEcb(MemoryStream inputStream, byte[] key, Bhd5Range[] ranges)
public static void DecryptAesEcb(Stream inputStream, byte[] key, Bhd5Range[] ranges)
{
var cipher = CreateAesEcbCipher(key);

Expand All @@ -148,9 +152,14 @@ public static void DecryptAesEcb(MemoryStream inputStream, byte[] key, Bhd5Range

inputStream.Position = range.StartOffset;
long length = range.EndOffset - range.StartOffset;
MemoryStream decryptedStream = DecryptAes(inputStream, cipher, length);
Stream decryptedStream = DecryptAes(inputStream, cipher, length);
inputStream.Position = range.StartOffset;
decryptedStream.WriteTo(inputStream);
byte[] buf = new byte[1000];
for (long pos = 0; pos < length; pos += buf.Length)
{
int read = decryptedStream.Read(buf, 0, 1000);
inputStream.Write(buf, 0, read);
}
}
}
}
Expand Down
2 changes: 1 addition & 1 deletion BinderTool.Core/Enc/EncFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ private EncFile(byte[] key)

private readonly byte[] _iv = new byte[EncryptionIvCbcSize];

public MemoryStream Data { get; private set; }
public Stream Data { get; private set; }

public static EncFile ReadEncFile(Stream inputStream, byte[] key, GameVersion version = GameVersion.Common)
{
Expand Down
3 changes: 2 additions & 1 deletion BinderTool.Core/GameVersion.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ public enum GameVersion
DarkSouls2,
DarkSouls3,
Bloodborne,
Sekiro
Sekiro,
EldenRing
}
}
6 changes: 4 additions & 2 deletions BinderTool.Core/Sl2/Sl2UserData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@ public Sl2UserData(byte[] key)

public byte[] EncryptedUserData { get; private set; }

public byte[] DecryptedUserData => CryptographyUtility.DecryptAesCbc(new MemoryStream(EncryptedUserData), _key, _iv).ToArray();

//public byte[] DecryptedUserData => CryptographyUtility.DecryptAesCbc(new MemoryStream(EncryptedUserData), _key, _iv).ToArray();
public byte[] DecryptedUserData => null;


public static Sl2UserData ReadSl2UserData(Stream inputStream, byte[] key, int size, string name)
{
Sl2UserData sl2UserData = new Sl2UserData(key);
Expand Down
5 changes: 5 additions & 0 deletions BinderTool/BinderTool.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<None Include="DictionaryER.csv">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
Expand Down

0 comments on commit fe7cd3f

Please sign in to comment.