// dnlib: See LICENSE.txt for more info using System.Text; using dnlib.IO; using dnlib.PE; namespace dnlib.DotNet.Writer { /// /// Import directory chunk /// public sealed class ImportDirectory : IChunk { readonly bool is64bit; FileOffset offset; RVA rva; bool isExeFile; uint length; RVA importLookupTableRVA; RVA corXxxMainRVA; RVA dllToImportRVA; int stringsPadding; string dllToImport; string entryPointName; /// /// Gets/sets the /// public ImportAddressTable ImportAddressTable { get; set; } /// /// Gets the RVA of _CorDllMain/_CorExeMain in the import lookup table /// public RVA CorXxxMainRVA => corXxxMainRVA; /// /// Gets RVA of _CorExeMain/_CorDllMain in the IAT /// public RVA IatCorXxxMainRVA => ImportAddressTable.RVA; /// /// Gets/sets a value indicating whether this is a EXE or a DLL file /// public bool IsExeFile { get => isExeFile; set => isExeFile = value; } /// public FileOffset FileOffset => offset; /// public RVA RVA => rva; internal bool Enable { get; set; } /// /// Gets/sets the name of the dll which should be imported. /// public string DllToImport { get => dllToImport ?? "mscoree.dll"; set => dllToImport = value; } /// /// Gets/sets the name of the entry point of the imported dll. /// public string EntryPointName { get => entryPointName ?? (IsExeFile ? "_CorExeMain" : "_CorDllMain"); set => entryPointName = value; } const uint STRINGS_ALIGNMENT = 16; /// /// Constructor /// /// true if it's a 64-bit PE file, false if it's a 32-bit PE file public ImportDirectory(bool is64bit) => this.is64bit = is64bit; /// public void SetOffset(FileOffset offset, RVA rva) { this.offset = offset; this.rva = rva; length = 0x28; importLookupTableRVA = rva + length; length += is64bit ? 16U : 8; stringsPadding = (int)(rva.AlignUp(STRINGS_ALIGNMENT) - rva); length += (uint)stringsPadding; corXxxMainRVA = rva + length; length += 2 + (uint)EntryPointName.Length + 1; dllToImportRVA = rva + length; length += (uint)DllToImport.Length + 1; length++; } /// public uint GetFileLength() { if (!Enable) return 0; return length; } /// public uint GetVirtualSize() => GetFileLength(); /// public uint CalculateAlignment() => 0; /// public void WriteTo(DataWriter writer) { if (!Enable) return; writer.WriteUInt32((uint)importLookupTableRVA); writer.WriteInt32(0); // DateTimeStamp writer.WriteInt32(0); // ForwarderChain writer.WriteUInt32((uint)dllToImportRVA); // Name writer.WriteUInt32((uint)ImportAddressTable.RVA); writer.WriteUInt64(0); writer.WriteUInt64(0); writer.WriteInt32(0); // ImportLookupTable if (is64bit) { writer.WriteUInt64((ulong)(uint)corXxxMainRVA); writer.WriteUInt64(0); } else { writer.WriteUInt32((uint)corXxxMainRVA); writer.WriteInt32(0); } writer.WriteZeroes(stringsPadding); writer.WriteUInt16(0); writer.WriteBytes(Encoding.UTF8.GetBytes(EntryPointName + "\0")); writer.WriteBytes(Encoding.UTF8.GetBytes(DllToImport + "\0")); writer.WriteByte(0); } } }