public sealed class BoundImportDirectoryParser
{
public IReadOnlyList<BoundImportInfo> Parse(byte[] rawBytes, NtHeaders nt, IReadOnlyList<SectionInfo> sections)
{
if (nt.OptionalHeader.DataDirectories.Count <= 11)
{
return Array.Empty<BoundImportInfo>();
}
var dir = nt.OptionalHeader.DataDirectories[11];
if (dir.VirtualAddress == 0 || dir.Size == 0)
{
return Array.Empty<BoundImportInfo>();
}
var baseOffset = RvaMapper.RvaToFileOffset(dir.VirtualAddress, sections, nt.OptionalHeader.SizeOfHeaders);
if (baseOffset is null)
{
return Array.Empty<BoundImportInfo>();
}
var items = new List<BoundImportInfo>();
var pos = baseOffset.Value;
var end = Math.Min(rawBytes.Length, baseOffset.Value + (int)dir.Size);
while (pos + 8 <= end)
{
var tds = BitConverter.ToUInt32(rawBytes, pos);
var offsetModuleName = BitConverter.ToUInt16(rawBytes, pos + 4);
var forwardRefs = BitConverter.ToUInt16(rawBytes, pos + 6);
if (tds == 0 && offsetModuleName == 0 && forwardRefs == 0)
{
break;
}
var nameOffset = baseOffset.Value + offsetModuleName;
var name = nameOffset < rawBytes.Length
? BinaryReaderExtensions.ReadAsciiStringAt(rawBytes, nameOffset, 512)
: string.Empty;
items.Add(new BoundImportInfo(tds, offsetModuleName, forwardRefs, name));
pos += 8;
}
return items;
}
}