public sealed class LoadConfigDirectoryParser
{
public LoadConfigInfo? Parse(byte[] rawBytes, NtHeaders nt, IReadOnlyList<SectionInfo> sections)
{
if (nt.OptionalHeader.DataDirectories.Count <= 10)
{
return null;
}
var dir = nt.OptionalHeader.DataDirectories[10];
if (dir.VirtualAddress == 0 || dir.Size == 0)
{
return null;
}
var offset = RvaMapper.RvaToFileOffset(dir.VirtualAddress, sections, nt.OptionalHeader.SizeOfHeaders);
if (offset is null)
{
return null;
}
var pos = offset.Value;
BoundsChecker.EnsureRange(pos, 16, rawBytes.Length, "load config directory");
uint size = BitConverter.ToUInt32(rawBytes, pos);
uint timeDateStamp = pos + 8 <= rawBytes.Length ? BitConverter.ToUInt32(rawBytes, pos + 4) : 0;
ushort major = pos + 10 <= rawBytes.Length ? BitConverter.ToUInt16(rawBytes, pos + 8) : (ushort)0;
ushort minor = pos + 12 <= rawBytes.Length ? BitConverter.ToUInt16(rawBytes, pos + 10) : (ushort)0;
ulong securityCookie = 0;
if (!nt.OptionalHeader.IsPe32Plus)
{
if (pos + 64 <= rawBytes.Length)
{
BoundsChecker.EnsureRange(pos + 60, 4, rawBytes.Length, "load config security cookie");
securityCookie = BitConverter.ToUInt32(rawBytes, pos + 60);
}
}
else
{
if (pos + 96 <= rawBytes.Length)
{
BoundsChecker.EnsureRange(pos + 88, 8, rawBytes.Length, "load config security cookie");
securityCookie = BitConverter.ToUInt64(rawBytes, pos + 88);
}
}
return new LoadConfigInfo(size, timeDateStamp, major, minor, securityCookie);
}
}