diff --git a/Src/Demo Application/Program.cs b/Src/Demo Application/Program.cs index 3c45e3f..eb4107d 100644 --- a/Src/Demo Application/Program.cs +++ b/Src/Demo Application/Program.cs @@ -18,12 +18,12 @@ static void Main(string[] args) //string file_name = Environment.GetCommandLineArgs()[0]; //string file_name = Assembly.GetEntryAssembly().Location; //string file_name = @"C:\Windows\SysWOW64\kernel32.dll"; - string file_name = @"C:\Windows\System32\kernel32.dll"; + //string file_name = @"C:\Windows\System32\kernel32.dll"; //string file_name = @"C:\Windows\SysWOW64\shell32.dll"; //string file_name = @"C:\Windows\System32\shell32.dll"; //string file_name = @"C:\Windows\SysWOW64\xpsservices.dll"; //string file_name = @"c:\windows\system32\advapi32.dll"; - //string file_name = @"P:\Workshell\dotNET Dependency Walker\Bin\Release\netdepends.exe"; + string file_name = @"P:\Workshell\dotNET Dependency Walker\Bin\Debug\netdepends.exe"; //string file_name = @"C:\Users\Lloyd\Desktop\PE Related\Tools\PeInternals\x64\PeInternals.exe"; //string file_name = @"D:\Lloyd\Downloads\Win32DiskImager-0.9.5-install.exe"; string error_message; @@ -37,6 +37,7 @@ static void Main(string[] args) ExecutableImage image = ExecutableImage.FromFile(file_name); + /* LoadConfigDirectory load_config = LoadConfigDirectory.Get(image); Certificate cert = Certificate.Get(image); DebugDirectory debug_dir = DebugDirectory.Get(image); @@ -55,6 +56,11 @@ static void Main(string[] args) Imports imports = Imports.Get(ilt,hint_name_table); Resources resources = Resources.Get(image); + */ + + CLR clr = CLR.Get(image); + CLRHeader header = CLRHeader.Get(clr); + CLRMetaData meta_data = CLRMetaData.Get(header); Console.ReadKey(); } diff --git a/Src/Workshell.PE/Content/CLR/CLR.cs b/Src/Workshell.PE/Content/CLR/CLR.cs new file mode 100644 index 0000000..1fd8b83 --- /dev/null +++ b/Src/Workshell.PE/Content/CLR/CLR.cs @@ -0,0 +1,131 @@ +using System; +using System.Collections.Generic; +using System.IO; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Workshell.PE.Native; + +namespace Workshell.PE +{ + + public sealed class CLR : ExecutableImageContent + { + + internal CLR(DataDirectory dataDirectory, Location dataLocation) : base(dataDirectory,dataLocation) + { + } + + #region Static Methods + + public static CLR Get(ExecutableImage image) + { + if (!image.NTHeaders.DataDirectories.Exists(DataDirectoryType.CLRRuntimeHeader)) + return null; + + DataDirectory directory = image.NTHeaders.DataDirectories[DataDirectoryType.CLRRuntimeHeader]; + + if (DataDirectory.IsNullOrEmpty(directory)) + return null; + + LocationCalculator calc = directory.Directories.Image.GetCalculator(); + Section section = calc.RVAToSection(directory.VirtualAddress); + ulong file_offset = calc.RVAToOffset(section, directory.VirtualAddress); + ulong image_base = directory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; + Location location = new Location(file_offset, directory.VirtualAddress, image_base + directory.VirtualAddress, directory.Size, directory.Size, section); + CLR result = new CLR(directory, location); + + return result; + } + + /* + public static CLRMetaData GetMetaData(CLRHeader header) + { + LocationCalculator calc = header.CLR.DataDirectory.Directories.Image.GetCalculator(); + ulong image_base = header.CLR.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; + uint rva = header.MetaDataAddress; + ulong va = image_base + rva; + ulong offset = calc.RVAToOffset(rva); + uint size = header.MetaDataSize; + Section section = calc.RVAToSection(rva); + Location location = new Location(offset, rva, va, size, size, section); + + //CLRMetaDataHeader meta_data_header = new CLRMetaDataHeader(this, header); + //CLRMetaDataStreamTable stream_table = new CLRMetaDataStreamTable(this, imageBase); + //CLRMetaDataStreamCollection streams = new CLRMetaDataStreamCollection(this, imageBase); + CLRMetaData meta_data = new CLRMetaData(header.CLR, location, header); + + return meta_data; + } + */ + + #endregion + + } + + /* + + public sealed class CLRContent : DataDirectoryContent + { + + private CLRHeader header; + private CLRMetaData meta_data; + + internal CLRContent(DataDirectory dataDirectory, ulong imageBase) : base(dataDirectory, imageBase) + { + LocationCalculator calc = DataDirectory.Directories.Reader.GetCalculator(); + Stream stream = DataDirectory.Directories.Reader.GetStream(); + + LoadHeader(calc, stream, imageBase); + LoadMetaData(calc, stream, imageBase); + } + + #region Methods + + private void LoadHeader(LocationCalculator calc, Stream stream, ulong imageBase) + { + ulong offset = calc.RVAToOffset(DataDirectory.VirtualAddress); + uint size = Convert.ToUInt32(Utils.SizeOf()); + Location location = new Location(offset,DataDirectory.VirtualAddress,imageBase + DataDirectory.VirtualAddress,size,size); + Section section = calc.RVAToSection(DataDirectory.VirtualAddress); + + stream.Seek(Convert.ToInt64(offset),SeekOrigin.Begin); + + IMAGE_COR20_HEADER clr_header = Utils.Read(stream,Convert.ToInt32(size)); + + header = new CLRHeader(this,clr_header,location,section); + } + + private void LoadMetaData(LocationCalculator calc, Stream stream, ulong imageBase) + { + meta_data = new CLRMetaData(this,imageBase); + } + + #endregion + + #region Properties + + public CLRHeader Header + { + get + { + return header; + } + } + + public CLRMetaData MetaData + { + get + { + return meta_data; + } + } + + #endregion + + } + + */ + +} diff --git a/Src/Workshell.PE/Content/CLR/CLRContent.cs b/Src/Workshell.PE/Content/CLR/CLRContent.cs deleted file mode 100644 index 57c4c5b..0000000 --- a/Src/Workshell.PE/Content/CLR/CLRContent.cs +++ /dev/null @@ -1,77 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -using Workshell.PE.Native; - -namespace Workshell.PE -{ - - /* - - public sealed class CLRContent : DataDirectoryContent - { - - private CLRHeader header; - private CLRMetaData meta_data; - - internal CLRContent(DataDirectory dataDirectory, ulong imageBase) : base(dataDirectory, imageBase) - { - LocationCalculator calc = DataDirectory.Directories.Reader.GetCalculator(); - Stream stream = DataDirectory.Directories.Reader.GetStream(); - - LoadHeader(calc, stream, imageBase); - LoadMetaData(calc, stream, imageBase); - } - - #region Methods - - private void LoadHeader(LocationCalculator calc, Stream stream, ulong imageBase) - { - ulong offset = calc.RVAToOffset(DataDirectory.VirtualAddress); - uint size = Convert.ToUInt32(Utils.SizeOf()); - Location location = new Location(offset,DataDirectory.VirtualAddress,imageBase + DataDirectory.VirtualAddress,size,size); - Section section = calc.RVAToSection(DataDirectory.VirtualAddress); - - stream.Seek(Convert.ToInt64(offset),SeekOrigin.Begin); - - IMAGE_COR20_HEADER clr_header = Utils.Read(stream,Convert.ToInt32(size)); - - header = new CLRHeader(this,clr_header,location,section); - } - - private void LoadMetaData(LocationCalculator calc, Stream stream, ulong imageBase) - { - meta_data = new CLRMetaData(this,imageBase); - } - - #endregion - - #region Properties - - public CLRHeader Header - { - get - { - return header; - } - } - - public CLRMetaData MetaData - { - get - { - return meta_data; - } - } - - #endregion - - } - - */ - -} diff --git a/Src/Workshell.PE/Content/CLR/CLRHeader.cs b/Src/Workshell.PE/Content/CLR/CLRHeader.cs index ba906e1..d06fabf 100644 --- a/Src/Workshell.PE/Content/CLR/CLRHeader.cs +++ b/Src/Workshell.PE/Content/CLR/CLRHeader.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Workshell.PE.Annotations; +using Workshell.PE.Extensions; using Workshell.PE.Native; namespace Workshell.PE @@ -33,24 +34,60 @@ public enum COMImageFlags : int public sealed class CLRHeader : ISupportsLocation, ISupportsBytes { - private CLRContent content; - private IMAGE_COR20_HEADER header; + private CLR clr; private Location location; - private Section section; + private IMAGE_COR20_HEADER header; + private Version runtime_version; + private CLRDataDirectory meta_data; + private CLRDataDirectory resources; + private CLRDataDirectory sn_sig; + private CLRDataDirectory code_man_table; + private CLRDataDirectory vtable_fixups; + private CLRDataDirectory export_address_table; + private CLRDataDirectory native_header; + + internal CLRHeader(CLR clrContent, Location clrLocation, IMAGE_COR20_HEADER clrHeader) + { + clr = clrContent; + location = clrLocation; + header = clrHeader; + runtime_version = null; + meta_data = null; + resources = null; + sn_sig = null; + code_man_table = null; + vtable_fixups = null; + export_address_table = null; + native_header = null; + } + + #region Static Methods - internal CLRHeader(CLRContent clrContent, IMAGE_COR20_HEADER clrHeader, Location clrLocation, Section clrSection) + public static CLRHeader Get(CLR clr) { - content = clrContent; - header = clrHeader; - location = clrLocation; - section = clrSection; + LocationCalculator calc = clr.DataDirectory.Directories.Image.GetCalculator(); + ulong offset = calc.RVAToOffset(clr.DataDirectory.VirtualAddress); + uint size = Utils.SizeOf().ToUInt32(); + ulong image_base = clr.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; + Section section = calc.RVAToSection(clr.DataDirectory.VirtualAddress); + Location location = new Location(offset, clr.DataDirectory.VirtualAddress, image_base + clr.DataDirectory.VirtualAddress, size, size, section); + Stream stream = clr.DataDirectory.Directories.Image.GetStream(); + + stream.Seek(offset.ToInt64(), SeekOrigin.Begin); + + IMAGE_COR20_HEADER clr_header = Utils.Read(stream, Convert.ToInt32(size)); + CLRHeader result = new CLRHeader(clr, location, clr_header); + + return result; } + #endregion + #region Methods public byte[] GetBytes() { - Stream stream = content.DataDirectory.Directories.Reader.GetStream(); + Stream stream = clr.DataDirectory.Directories.Image.GetStream(); byte[] buffer = Utils.ReadBytes(stream,location); return buffer; @@ -58,12 +95,18 @@ public byte[] GetBytes() public Version GetRuntimeVersion() { - return new Version(header.MajorRuntimeVersion,header.MinorRuntimeVersion); + if (runtime_version == null) + runtime_version = new Version(header.MajorRuntimeVersion, header.MinorRuntimeVersion); + + return runtime_version; } public CLRDataDirectory GetMetaData() { - return new CLRDataDirectory(header.MetaData); + if (meta_data == null) + meta_data = new CLRDataDirectory(header.MetaData); + + return meta_data; } public COMImageFlags GetFlags() @@ -73,43 +116,61 @@ public COMImageFlags GetFlags() public CLRDataDirectory GetResources() { - return new CLRDataDirectory(header.Resources); + if (resources == null) + resources = new CLRDataDirectory(header.Resources); + + return resources; } public CLRDataDirectory GetStrongNameSignature() { - return new CLRDataDirectory(header.StrongNameSignature); + if (sn_sig == null) + sn_sig = new CLRDataDirectory(header.StrongNameSignature); + + return sn_sig; } public CLRDataDirectory GetCodeManagerTable() { - return new CLRDataDirectory(header.CodeManagerTable); + if (code_man_table == null) + code_man_table = new CLRDataDirectory(header.CodeManagerTable); + + return code_man_table; } public CLRDataDirectory GetVTableFixups() { - return new CLRDataDirectory(header.VTableFixups); + if (vtable_fixups == null) + vtable_fixups = new CLRDataDirectory(header.VTableFixups); + + return vtable_fixups; } public CLRDataDirectory GetExportAddressTableJumps() { - return new CLRDataDirectory(header.ExportAddressTableJumps); + if (export_address_table == null) + export_address_table = new CLRDataDirectory(header.ExportAddressTableJumps); + + return export_address_table; } public CLRDataDirectory GetManagedNativeHeader() { - return new CLRDataDirectory(header.ManagedNativeHeader); + if (native_header == null) + native_header = new CLRDataDirectory(header.ManagedNativeHeader); + + return native_header; } #endregion #region Properties - public CLRContent Content + public CLR CLR { get { - return content; + return clr; } } @@ -121,14 +182,6 @@ public Location Location } } - public Section Section - { - get - { - return section; - } - } - [FieldAnnotation("Header Size")] public uint HeaderSize { diff --git a/Src/Workshell.PE/Content/CLR/CLRMetaData.cs b/Src/Workshell.PE/Content/CLR/CLRMetaData.cs index a02e300..33993fb 100644 --- a/Src/Workshell.PE/Content/CLR/CLRMetaData.cs +++ b/Src/Workshell.PE/Content/CLR/CLRMetaData.cs @@ -11,37 +11,40 @@ namespace Workshell.PE public sealed class CLRMetaData : ISupportsLocation, ISupportsBytes { - private CLRContent content; - private Location location; - private Section section; - private ulong image_base; - private CLRMetaDataHeader header; - private CLRMetaDataStreamTable stream_table; - private CLRMetaDataStreamCollection streams; - - internal CLRMetaData(CLRContent mdContent, ulong imageBase) + internal CLRMetaData(CLR clr, Location location, CLRHeader header) { - LocationCalculator calc = mdContent.DataDirectory.Directories.Reader.GetCalculator(); - uint rva = mdContent.Header.MetaDataAddress; - ulong va = imageBase + rva; + CLR = clr; + Location = location; + Header = new CLRMetaDataHeader(this); + StreamTable = new CLRMetaDataStreamTable(this); + Streams = new CLRMetaDataStreams(this); + } + + #region Static Methods + + public static CLRMetaData Get(CLRHeader header) + { + LocationCalculator calc = header.CLR.DataDirectory.Directories.Image.GetCalculator(); + ulong image_base = header.CLR.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; + uint rva = header.MetaDataAddress; + ulong va = image_base + rva; ulong offset = calc.RVAToOffset(rva); - uint size = mdContent.Header.MetaDataSize; - - content = mdContent; - location = new Location(offset,rva,va,size,size); - section = calc.RVAToSection(rva); - image_base = imageBase; - header = new CLRMetaDataHeader(this,imageBase); - stream_table = new CLRMetaDataStreamTable(this,imageBase); - streams = new CLRMetaDataStreamCollection(this,imageBase); + uint size = header.MetaDataSize; + Section section = calc.RVAToSection(rva); + Location location = new Location(offset, rva, va, size, size, section); + CLRMetaData meta_data = new CLRMetaData(header.CLR, location, header); + + return meta_data; } + #endregion + #region Methods public byte[] GetBytes() { - Stream stream = content.DataDirectory.Directories.Reader.GetStream(); - byte[] buffer = Utils.ReadBytes(stream,location); + Stream stream = CLR.DataDirectory.Directories.Image.GetStream(); + byte[] buffer = Utils.ReadBytes(stream,Location); return buffer; } @@ -50,52 +53,34 @@ public byte[] GetBytes() #region Properties - public CLRContent Content + public CLR CLR { - get - { - return content; - } + get; + private set; } public Location Location { - get - { - return location; - } - } - - public Section Section - { - get - { - return section; - } + get; + private set; } public CLRMetaDataHeader Header { - get - { - return header; - } + get; + private set; } public CLRMetaDataStreamTable StreamTable { - get - { - return stream_table; - } + get; + private set; } - public CLRMetaDataStreamCollection Streams + public CLRMetaDataStreams Streams { - get - { - return streams; - } + get; + private set; } #endregion diff --git a/Src/Workshell.PE/Content/CLR/CLRMetaDataHeader.cs b/Src/Workshell.PE/Content/CLR/CLRMetaDataHeader.cs index 64720e2..54a36e0 100644 --- a/Src/Workshell.PE/Content/CLR/CLRMetaDataHeader.cs +++ b/Src/Workshell.PE/Content/CLR/CLRMetaDataHeader.cs @@ -6,6 +6,7 @@ using System.Threading.Tasks; using Workshell.PE.Annotations; +using Workshell.PE.Extensions; namespace Workshell.PE { @@ -15,42 +16,43 @@ public sealed class CLRMetaDataHeader : ISupportsLocation, ISupportsBytes private const uint CLR_METADATA_SIGNATURE = 0x424A5342; - internal CLRMetaDataHeader(CLRMetaData metaData, ulong imageBase) + internal CLRMetaDataHeader(CLRMetaData metaData) { - LocationCalculator calc = metaData.Content.DataDirectory.Directories.Reader.GetCalculator(); - Stream stream = metaData.Content.DataDirectory.Directories.Reader.GetStream(); - - uint rva = metaData.Content.Header.MetaDataAddress; - ulong va = imageBase + rva; + LocationCalculator calc = metaData.CLR.DataDirectory.Directories.Image.GetCalculator(); + Stream stream = metaData.CLR.DataDirectory.Directories.Image.GetStream(); + ulong image_base = metaData.CLR.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; + uint rva = metaData.Location.RelativeVirtualAddress; + ulong va = metaData.Location.VirtualAddress; + ulong offset = metaData.Location.FileOffset; uint size = 0; - ulong offset = calc.RVAToOffset(rva); + Section section = metaData.Location.Section; - stream.Seek(Convert.ToInt64(offset),SeekOrigin.Begin); + stream.Seek(offset.ToInt64(), SeekOrigin.Begin); MetaData = metaData; Signature = Utils.ReadUInt32(stream); if (Signature != CLR_METADATA_SIGNATURE) - throw new ImageReaderException("Incorrect signature found in CLR meta-data header."); + throw new ExecutableImageException("Incorrect signature found in CLR meta-data header."); MajorVersion = Utils.ReadUInt16(stream); MinorVersion = Utils.ReadUInt16(stream); Reserved = Utils.ReadUInt32(stream); VersionLength = Utils.ReadUInt32(stream); - Version = Utils.ReadString(stream,VersionLength); + Version = Utils.ReadString(stream, VersionLength); Flags = Utils.ReadUInt16(stream); Streams = Utils.ReadUInt16(stream); size = sizeof(uint) + sizeof(ushort) + sizeof(ushort) + sizeof(uint) + sizeof(uint) + VersionLength + sizeof(ushort) + sizeof(ushort); - Location = new Location(offset,rva,va,size,size); + Location = new Location(offset, rva, va, size, size, section); } #region Methods public byte[] GetBytes() { - Stream stream = MetaData.Content.DataDirectory.Directories.Reader.GetStream(); + Stream stream = MetaData.CLR.DataDirectory.Directories.Image.GetStream(); byte[] buffer = Utils.ReadBytes(stream,Location); return buffer; diff --git a/Src/Workshell.PE/Content/CLR/CLRMetaDataStream.cs b/Src/Workshell.PE/Content/CLR/CLRMetaDataStream.cs index e7d83a4..97cbe1e 100644 --- a/Src/Workshell.PE/Content/CLR/CLRMetaDataStream.cs +++ b/Src/Workshell.PE/Content/CLR/CLRMetaDataStream.cs @@ -13,12 +13,12 @@ namespace Workshell.PE public sealed class CLRMetaDataStream : ISupportsLocation, ISupportsBytes { - internal CLRMetaDataStream(CLRMetaDataStreamCollection streams, CLRMetaDataStreamTableEntry tableEntry, ulong imageBase) + internal CLRMetaDataStream(CLRMetaDataStreams streams, CLRMetaDataStreamTableEntry tableEntry, ulong imageBase) { Streams = streams; TableEntry = tableEntry; - LocationCalculator calc = streams.MetaData.Content.DataDirectory.Directories.Reader.GetCalculator(); + LocationCalculator calc = streams.MetaData.CLR.DataDirectory.Directories.Image.GetCalculator(); ulong offset = streams.MetaData.Location.FileOffset + tableEntry.Offset; uint rva = calc.OffsetToRVA(offset); ulong va = imageBase + rva; @@ -36,7 +36,7 @@ public override string ToString() public byte[] GetBytes() { - Stream stream = Streams.MetaData.Content.DataDirectory.Directories.Reader.GetStream(); + Stream stream = Streams.MetaData.CLR.DataDirectory.Directories.Image.GetStream(); byte[] buffer = Utils.ReadBytes(stream,Location); return buffer; @@ -46,7 +46,7 @@ public byte[] GetBytes() #region Properties - public CLRMetaDataStreamCollection Streams + public CLRMetaDataStreams Streams { get; private set; @@ -74,51 +74,58 @@ public string Name } - public sealed class CLRMetaDataStreamCollection : IEnumerable, IReadOnlyCollection, ISupportsLocation, ISupportsBytes + public sealed class CLRMetaDataStreams : IEnumerable, ISupportsLocation, ISupportsBytes { private CLRMetaData meta_data; - private List streams; + private CLRMetaDataStream[] streams; private Location location; - internal CLRMetaDataStreamCollection(CLRMetaData metaData, ulong imageBase) + internal CLRMetaDataStreams(CLRMetaData metaData) { + ulong image_base = metaData.CLR.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; + meta_data = metaData; - streams = new List(); + streams = new CLRMetaDataStream[metaData.StreamTable.Count]; - foreach(CLRMetaDataStreamTableEntry entry in metaData.StreamTable) + for(var i = 0; i < streams.Length; i++) { - CLRMetaDataStream stream = new CLRMetaDataStream(this,entry,imageBase); + CLRMetaDataStreamTableEntry entry = metaData.StreamTable[i]; + CLRMetaDataStream stream = new CLRMetaDataStream(this, entry, image_base); - streams.Add(stream); + streams[i] = stream; } - LocationCalculator calc = metaData.Content.DataDirectory.Directories.Reader.GetCalculator(); + Section section = null; + uint rva = 0; + ulong va = 0; ulong offset = 0; + ulong size = 0; - if (streams.Count > 0) + if (streams.Length > 0) { CLRMetaDataStream stream = streams.MinBy(s => s.Location.FileOffset); + section = stream.Location.Section; + rva = stream.Location.RelativeVirtualAddress; + va = stream.Location.VirtualAddress; offset = stream.Location.FileOffset; } - ulong size = 0; - foreach (var stream in streams) size += stream.Location.FileSize; - uint rva = calc.OffsetToRVA(offset); - ulong va = imageBase + rva; - - location = new Location(offset,rva,va,size,size); + location = new Location(offset, rva, va, size, size, section); } #region Methods public IEnumerator GetEnumerator() { - return streams.GetEnumerator(); + for(var i = 0; i < streams.Length; i++) + { + yield return streams[i]; + } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() @@ -128,12 +135,12 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() public override string ToString() { - return String.Format("Stream Count: {0}",streams.Count); + return String.Format("Stream Count: {0}",streams.Length); } public byte[] GetBytes() { - Stream stream = meta_data.Content.DataDirectory.Directories.Reader.GetStream(); + Stream stream = meta_data.CLR.DataDirectory.Directories.Image.GetStream(); byte[] buffer = Utils.ReadBytes(stream,location); return buffer; @@ -163,7 +170,7 @@ public int Count { get { - return streams.Count; + return streams.Length; } } diff --git a/Src/Workshell.PE/Content/CLR/CLRMetaDataStreamTable.cs b/Src/Workshell.PE/Content/CLR/CLRMetaDataStreamTable.cs index daf95a4..71f778d 100644 --- a/Src/Workshell.PE/Content/CLR/CLRMetaDataStreamTable.cs +++ b/Src/Workshell.PE/Content/CLR/CLRMetaDataStreamTable.cs @@ -5,6 +5,8 @@ using System.Text; using System.Threading.Tasks; +using Workshell.PE.Extensions; + namespace Workshell.PE { @@ -29,7 +31,7 @@ public override string ToString() public byte[] GetBytes() { - Stream stream = Table.MetaData.Content.DataDirectory.Directories.Reader.GetStream(); + Stream stream = Table.MetaData.CLR.DataDirectory.Directories.Image.GetStream(); byte[] buffer = Utils.ReadBytes(stream,Location); return buffer; @@ -73,39 +75,43 @@ public string Name } - public sealed class CLRMetaDataStreamTable : IEnumerable, IReadOnlyCollection, ISupportsLocation, ISupportsBytes + public sealed class CLRMetaDataStreamTable : IEnumerable, ISupportsLocation, ISupportsBytes { private CLRMetaData meta_data; - private List streams; + private CLRMetaDataStreamTableEntry[] entries; private Location location; - internal CLRMetaDataStreamTable(CLRMetaData metaData, ulong imageBase) + internal CLRMetaDataStreamTable(CLRMetaData metaData) { - LocationCalculator calc = metaData.Content.DataDirectory.Directories.Reader.GetCalculator(); - Stream stream = metaData.Content.DataDirectory.Directories.Reader.GetStream(); + LocationCalculator calc = metaData.CLR.DataDirectory.Directories.Image.GetCalculator(); + Stream stream = metaData.CLR.DataDirectory.Directories.Image.GetStream(); + ulong image_base = metaData.CLR.DataDirectory.Directories.Image.NTHeaders.OptionalHeader.ImageBase; ulong offset = metaData.Header.Location.FileOffset + metaData.Header.Location.FileSize; meta_data = metaData; - streams = new List(); - - LoadTable(metaData,calc,stream,offset,imageBase); + entries = LoadTable(metaData,calc,stream,offset,image_base); uint rva = calc.OffsetToRVA(offset); - ulong va = imageBase + rva; + ulong va = image_base + rva; ulong size = 0; - foreach (var s in streams) - size += s.Location.FileSize; + foreach (var strm in entries) + size += strm.Location.FileSize; - location = new Location(offset,rva,va,size,size); + Section section = calc.RVAToSection(rva); + + location = new Location(offset,rva,va,size,size,section); } #region Methods public IEnumerator GetEnumerator() { - return streams.GetEnumerator(); + for(var i = 0; i < entries.Length; i++) + { + yield return entries[i]; + } } System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() @@ -115,21 +121,22 @@ System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() public override string ToString() { - return String.Format("Stream Entry Count: {0}",streams.Count); + return String.Format("Stream Entry Count: {0}",entries.Length); } public byte[] GetBytes() { - Stream stream = meta_data.Content.DataDirectory.Directories.Reader.GetStream(); + Stream stream = meta_data.CLR.DataDirectory.Directories.Image.GetStream(); byte[] buffer = Utils.ReadBytes(stream,location); return buffer; } - private void LoadTable(CLRMetaData metaData, LocationCalculator calc, Stream stream, ulong baseOffset, ulong imageBase) + private CLRMetaDataStreamTableEntry[] LoadTable(CLRMetaData metaData, LocationCalculator calc, Stream stream, ulong baseOffset, ulong imageBase) { - stream.Seek(Convert.ToInt64(baseOffset),SeekOrigin.Begin); + stream.Seek(baseOffset.ToInt64(),SeekOrigin.Begin); + List entries = new List(); ulong offset = baseOffset; for(int i = 0; i < metaData.Header.Streams; i++) @@ -143,7 +150,7 @@ private void LoadTable(CLRMetaData metaData, LocationCalculator calc, Stream str size += sizeof(uint); - StringBuilder stream_name = new StringBuilder(); + StringBuilder stream_name = new StringBuilder(256); while (true) { @@ -171,13 +178,15 @@ private void LoadTable(CLRMetaData metaData, LocationCalculator calc, Stream str uint rva = calc.OffsetToRVA(offset); ulong va = imageBase + rva; - - Location entry_location = new Location(offset,rva,va,size,size); + Section section = calc.RVAToSection(rva); + Location entry_location = new Location(offset,rva,va,size,size,section); CLRMetaDataStreamTableEntry entry = new CLRMetaDataStreamTableEntry(this,entry_location,stream_offset,stream_size,stream_name.ToString()); - streams.Add(entry); + entries.Add(entry); offset += size; } + + return entries.ToArray(); } #endregion @@ -204,7 +213,7 @@ public int Count { get { - return streams.Count; + return entries.Length; } } @@ -212,7 +221,7 @@ public CLRMetaDataStreamTableEntry this[int index] { get { - return streams[index]; + return entries[index]; } } @@ -220,7 +229,7 @@ public CLRMetaDataStreamTableEntry this[string name] { get { - CLRMetaDataStreamTableEntry entry = streams.FirstOrDefault(stream => String.Compare(name,stream.Name,StringComparison.OrdinalIgnoreCase) == 0); + CLRMetaDataStreamTableEntry entry = entries.FirstOrDefault(stream => String.Compare(name,stream.Name,StringComparison.OrdinalIgnoreCase) == 0); return entry; } diff --git a/Src/Workshell.PE/Workshell.PE.csproj b/Src/Workshell.PE/Workshell.PE.csproj index adc40ef..31e5d4d 100644 --- a/Src/Workshell.PE/Workshell.PE.csproj +++ b/Src/Workshell.PE/Workshell.PE.csproj @@ -45,6 +45,13 @@ + + + + + + +