Created
January 1, 2023 13:38
-
-
Save bopin2020/d2d7b8a411c36bdd713975e95f95e294 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#define HEADER | |
#define OutputSection_Info | |
#define RELOCATION | |
#define SymbolTable | |
#define StringTable | |
using System; | |
using System.Collections.Generic; | |
using System.IO; | |
using System.Linq; | |
using System.Reflection; | |
using System.Runtime.InteropServices; | |
using System.Text; | |
namespace COFFParser | |
{ | |
internal class Program | |
{ | |
static void Main(string[] args) | |
{ | |
COFFStructs cOFFStructs = new COFFStructs(); | |
cOFFStructs.Parse(File.ReadAllBytes(args[0]), true); | |
Console.ReadKey(); | |
} | |
} | |
public class Generic | |
{ | |
/// <summary> | |
/// Fork from ThreatCheck @RastaMouse | |
/// </summary> | |
/// <param name="bytes"></param> | |
public static void HexDump(byte[] bytes) | |
{ | |
if (bytes == null) | |
{ | |
return; | |
} | |
if (bytes.Length > 10000000) | |
{ | |
return; | |
} | |
var bytesPerLine = 16; | |
var hexChars = "0123456789ABCDEF".ToCharArray(); | |
var firstHexColumn = | |
8 // 8 characters for the address | |
+ 3; // 3 spaces | |
var firstCharColumn = firstHexColumn | |
+ bytesPerLine * 3 // - 2 digit for the hexadecimal value and 1 space | |
+ (bytesPerLine - 1) / 8 // - 1 extra space every 8 characters from the 9th | |
+ 2; // 2 spaces | |
var lineLength = firstCharColumn | |
+ bytesPerLine // - characters to show the ascii value | |
+ Environment.NewLine.Length; // Carriage return and line feed (should normally be 2) | |
var line = (new string(' ', lineLength - Environment.NewLine.Length) + Environment.NewLine).ToCharArray(); | |
var expectedLines = (bytes.Length + bytesPerLine - 1) / bytesPerLine; | |
var result = new StringBuilder(expectedLines * lineLength); | |
for (int i = 0; i < bytes.Length; i += bytesPerLine) | |
{ | |
line[0] = hexChars[(i >> 28) & 0xF]; | |
line[1] = hexChars[(i >> 24) & 0xF]; | |
line[2] = hexChars[(i >> 20) & 0xF]; | |
line[3] = hexChars[(i >> 16) & 0xF]; | |
line[4] = hexChars[(i >> 12) & 0xF]; | |
line[5] = hexChars[(i >> 8) & 0xF]; | |
line[6] = hexChars[(i >> 4) & 0xF]; | |
line[7] = hexChars[(i >> 0) & 0xF]; | |
var hexColumn = firstHexColumn; | |
var charColumn = firstCharColumn; | |
for (var j = 0; j < bytesPerLine; j++) | |
{ | |
if (j > 0 && (j & 7) == 0) hexColumn++; | |
if (i + j >= bytes.Length) | |
{ | |
line[hexColumn] = ' '; | |
line[hexColumn + 1] = ' '; | |
line[charColumn] = ' '; | |
} | |
else | |
{ | |
var b = bytes[i + j]; | |
line[hexColumn] = hexChars[(b >> 4) & 0xF]; | |
line[hexColumn + 1] = hexChars[b & 0xF]; | |
line[charColumn] = (b < 32 ? '·' : (char)b); | |
} | |
hexColumn += 3; | |
charColumn++; | |
} | |
if (result.Length < result.MaxCapacity) | |
{ | |
result.Append(line); | |
} | |
} | |
Console.WriteLine(result.ToString()); | |
} | |
public static string centeredString(string s, int width) | |
{ | |
if (String.IsNullOrEmpty(s)) | |
{ | |
s = "N/A (null)"; | |
} | |
if (s.Length >= width) | |
{ | |
return s; | |
} | |
int leftPadding = (width - s.Length) / 2; | |
int rightPadding = width - s.Length - leftPadding; | |
return new string(' ', leftPadding) + s + new string(' ', rightPadding); | |
} | |
public static void PrintTableList<T>(List<T> objects)// where T: IPrint | |
{ | |
string title = ""; | |
string values = ""; | |
foreach (var item in objects) | |
{ | |
string title_tmp = ""; | |
Type t = item.GetType(); | |
foreach (PropertyInfo property in t.GetProperties()) | |
{ | |
title_tmp += property.Name + "\t"; | |
values += property.GetValue(item) + "\t"; | |
} | |
title_tmp = title_tmp.Substring(0, title_tmp.Length - 1); | |
title = title_tmp + "\n"; | |
values = values.Substring(0, values.Length - 1); | |
values += "\n"; | |
} | |
string finallys = title + values.Substring(0, values.Length - 1); | |
PrintTable(finallys); | |
} | |
/// <summary> | |
/// 参考SharpSploitResult 格式化输出 | |
/// </summary> | |
/// <param name="result"></param> | |
public static void PrintTable(string result) | |
{ | |
List<List<string>> one = new List<List<string>>(); | |
string[] results = result.Split('\n'); | |
for (int i = 0; i < results.Length; i++) | |
{ | |
string[] resultes = results[i].Split('\t'); | |
List<string> two = new List<string>(); | |
foreach (var item in resultes) | |
{ | |
two.Add(item); | |
} | |
one.Add(two); | |
} | |
PrintTable(one); | |
} | |
/// <summary> | |
/// 数据格式化 | |
/// 按照表格打印 | |
/// </summary> | |
/// <param name="results"></param> | |
public static void PrintTable(IEnumerable<string> results) | |
{ | |
List<IEnumerable<string>> resultes = new List<IEnumerable<string>>(); | |
resultes.Add(results); | |
PrintTable(resultes); | |
} | |
// 3 * 5 | |
private static int[][] indexes; | |
public static void PrintTable(IEnumerable<IEnumerable<string>> results) | |
{ | |
StringBuilder sb = new StringBuilder(); | |
List<int> Maxrow = new List<int>(); | |
List<string> s = new List<string>(); | |
int rowLen = 0; | |
int rowNumber = 0; | |
foreach (var items in results) | |
{ | |
rowNumber = 0; | |
foreach (var item in items) | |
{ | |
rowNumber++; | |
if (item.Length > rowLen) | |
{ | |
rowLen = item.Length; | |
} | |
} | |
} | |
int linesLen = 0; | |
foreach (var items in results) | |
{ | |
string tmp = ""; | |
foreach (var item in items) | |
{ | |
tmp += $"|{centeredString(item, rowLen)}"; | |
} | |
tmp += "|\r\n"; | |
sb.Append(Multiplication("-", tmp.Length - 2) + "\n"); | |
sb.Append(tmp); | |
linesLen = tmp.Length - 2; | |
} | |
sb.Append(Multiplication("-", linesLen)); | |
Console.WriteLine(sb.ToString()); | |
} | |
private static string Multiplication(string flag, int num) | |
{ | |
string result = ""; | |
for (int i = 0; i < num; i++) | |
{ | |
result += flag; | |
} | |
return result; | |
} | |
public static string CharArrayToString(char[] chars) | |
{ | |
return String.Join("", chars); | |
} | |
} | |
public sealed class RandomThings | |
{ | |
public static int RandomInt() | |
{ | |
Random rnd = new Random(); | |
int n = rnd.Next(100000, 999998); | |
if (n % 2 == 1) | |
{ | |
n = n + 1; | |
} | |
return n; | |
} | |
private static Random random = new Random(); | |
public static string RandomString(int length) | |
{ | |
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; | |
return new string(Enumerable.Repeat(chars, length) | |
.Select(s => s[random.Next(s.Length)]).ToArray()); | |
} | |
public static byte[] RandomBytes(int length) | |
{ | |
const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; | |
return Encoding.ASCII.GetBytes(new string(Enumerable.Repeat(chars, length) | |
.Select(s => s[random.Next(s.Length)]).ToArray())); | |
} | |
} | |
/// <summary> | |
/// https://www.codeproject.com/Articles/63745/From-Binary-to-Data-Structures#heading0003 | |
/// </summary> | |
public class COFFStructs | |
{ | |
private const int PeSignatureOffsetLocation = 0x3c; | |
private const int PeSignatureSize = 4; | |
private const string PeSignatureContent = "PE"; | |
public CoffHeader Coffheader; | |
public CoffOptionalHeader CoffOptionalheader; | |
public Dictionary<String, CoffSectionHeader> Sections = new Dictionary<String, CoffSectionHeader>(); | |
public CoffSectionHeader section; | |
// 对应节具备的重定位信息 | |
public Dictionary<String, List<CoffRelocation>> Relocations = new Dictionary<String, List<CoffRelocation>>(); | |
public CoffRelocation relocation; | |
public List<CoffSymbolTable> symboltables = new List<CoffSymbolTable>(); | |
public CoffSymbolTable symboltable; | |
private List<IntPtr> Disposes = new List<IntPtr>(); | |
private void Free(List<IntPtr> Disposes) | |
{ | |
foreach (var item in Disposes) | |
{ | |
Marshal.FreeHGlobal(item); | |
} | |
} | |
private IntPtr IntPtrAdd(IntPtr a, int b) | |
{ | |
IntPtr ptr = new IntPtr(a.ToInt64() + b); | |
return ptr; | |
} | |
public void Parse(byte[] PEBytes, bool IsOnlyParse) | |
{ | |
using (MemoryStream stream = new MemoryStream(PEBytes, 0, PEBytes.Length)) | |
{ | |
#region Read | |
BinaryReader br = new BinaryReader(stream); | |
#if PE | |
SeekToPeSignature(br); | |
if (!IsValidPeSignature(br)) | |
{ | |
throw new BadImageFormatException(); | |
} | |
#endif | |
Coffheader = FromBinaryReader<CoffHeader>(br); | |
#if HEADER | |
Console.WriteLine("Machine: {0} \n", Coffheader.Machine); | |
Console.WriteLine("NumberOfSections {0} \n", Coffheader.NumberOfSections); | |
Console.WriteLine("TimeDateStamp {0} \n", Coffheader.TimeDateStamp); | |
Console.WriteLine("PointerToSymbolTable {0} \n", Coffheader.PointerToSymbolTable); | |
Console.WriteLine("NumberOfSymbols {0} \n", Coffheader.NumberOfSymbols); | |
Console.WriteLine("SizeOfOptionalHeader {0} \n", Coffheader.SizeOfOptionalHeader); | |
Console.WriteLine("Characteristics {0} \n", Coffheader.Characteristics); | |
#endif | |
stream.Seek(Marshal.SizeOf(Coffheader), SeekOrigin.Begin); | |
if (Coffheader.SizeOfOptionalHeader == 28) | |
{ | |
// 如果存在可选头 | |
CoffOptionalheader = FromBinaryReader<CoffOptionalHeader>(br); | |
stream.Seek(Marshal.SizeOf(Coffheader) + Marshal.SizeOf(CoffOptionalheader), SeekOrigin.Begin); | |
} | |
// Iteration for parse section information | |
byte[] textCode; // 获取.text的内容后面会用到 | |
for (int i = 0; i < Coffheader.NumberOfSections; i++) | |
{ | |
section = FromBinaryReader<CoffSectionHeader>(br); | |
string sectionName = new string(section.Name); | |
if (Sections.ContainsKey(sectionName)) | |
{ | |
Sections.Add(sectionName + "_" + RandomThings.RandomString(5), section); | |
} | |
else | |
{ | |
Sections.Add(sectionName, section); | |
} | |
// 超过8字节的section name 则这里的值指向字符串表的指针 | |
#if OutputSection_Info | |
Console.WriteLine(new string(section.Name) + "\t" + section.RawdataPtr.ToString("x")); | |
Generic.HexDump(ReadBytes(PEBytes,section.RawdataPtr,section.SectionSize)); | |
if (new string(section.Name).Contains(".text")) | |
{ | |
textCode = ReadBytes(PEBytes, section.RawdataPtr, section.SectionSize); | |
} | |
#endif | |
} | |
// 根据 Section Header RelocationPtr 指向重定位表地址不为空 | |
// 说明该节具备同时 Number Of Relocations重定位条目的数目则可遍历 | |
foreach (var item in Sections) | |
{ | |
if (item.Value.RelocationPtr != 0) | |
{ | |
#if RELOCATION | |
Console.WriteLine(item.Key + "===>\n"); | |
#endif | |
stream.Position = item.Value.RelocationPtr; | |
List<CoffRelocation> res = new List<CoffRelocation>(); | |
for (int i = 0; i < item.Value.RelocationsNumber; i++) | |
{ | |
relocation = FromBinaryReader<CoffRelocation>(br); | |
res.Add(relocation); | |
#if RELOCATION | |
Console.WriteLine(relocation.VirtualAddress.ToString("x") + "\t" + relocation.SymbolTableIndex + "\t" + relocation.RelocationType); | |
#endif | |
} | |
Relocations.Add(item.Key, res); | |
res.Clear(); | |
} | |
} | |
// 解析符号表 | |
stream.Position = Coffheader.PointerToSymbolTable; | |
#if SymbolTable | |
// Console.WriteLine("Index" + ": \t\t" + "Name" + "\t" + "Value" + "\t" + "SectionNumber" + "\t" + "Type" + "\t" + "StorageClass" + "\t" + "NumberOfAuxSymbols"); | |
string tmp = "Index" + "\t" + "Name" + "\t" + "Value" + "\t" + "SectionNumber" + "\t" + "Type" + "\t" + "StorageClass" + "\t" + "NumberOfAuxSymbols\t\n"; | |
#endif | |
for (int i = 0; i < Coffheader.NumberOfSymbols; i++) | |
{ | |
symboltable = FromBinaryReader<CoffSymbolTable>(br); | |
#if SymbolTable | |
// Console.WriteLine(i + ": \t" + new string(symboltable.Name) + "\t" + symboltable.Value + "\t" + symboltable.SectionNumber.ToString("x") + "\t" + symboltable.Type + "\t" + (byte)symboltable.StorageClass + "\t" + (byte)symboltable.NumberOfAuxSymbols); | |
tmp += (i + "\t" + new string(symboltable.Name) + "\t" + symboltable.Value + "\t" + symboltable.SectionNumber.ToString("x") + "\t" + symboltable.Type + "\t" + (byte)symboltable.StorageClass + "\t" + (byte)symboltable.NumberOfAuxSymbols + "\t\n"); | |
symboltables.Add(symboltable); | |
#endif | |
} | |
Generic.PrintTable(tmp); | |
// 通过符号表的数目 HEADER_TABLE 定位字符串表位置 总是位于SymBolTable之后 | |
// 解析玩符号表最后 读取四字节作为字符串表的长度 | |
int len = br.ReadInt32(); | |
// 解析字符串表 | |
// 前面提到过 如果节表名超过8字节 则存储到字符串表的地址 | |
byte[] StringTables = br.ReadBytes(len); | |
#if StringTable | |
Generic.HexDump(StringTables); | |
#endif | |
#endregion | |
// only parse coff file without invoking | |
if (IsOnlyParse) | |
{ | |
return; | |
} | |
// Invoke-Bof 1229 lines | |
// Heap segment分配 RW权限内存 | |
IntPtr UnmanagedCoffBytes = Marshal.AllocHGlobal(PEBytes.Length); Disposes.Add(UnmanagedCoffBytes); | |
Marshal.Copy(PEBytes, 0, UnmanagedCoffBytes, PEBytes.Length); | |
CoffHeader coffheader = (CoffHeader)Marshal.PtrToStructure(UnmanagedCoffBytes, typeof(CoffHeader)); | |
// 第一个节位置 偏移一个 Coff header大小 | |
IntPtr SectionHeaderPtr = IntPtrAdd(UnmanagedCoffBytes, Marshal.SizeOf(typeof(CoffHeader))); | |
IntPtr SymbolTablePtr = IntPtrAdd(UnmanagedCoffBytes, (int)coffheader.PointerToSymbolTable); | |
IntPtr SymbolValuePtr = IntPtrAdd(SymbolTablePtr, (int)coffheader.NumberOfSymbols * Marshal.SizeOf(typeof(CoffSymbolTable))); | |
List<CoffSectionHeader> sections = new List<CoffSectionHeader>(); | |
// Loading all sections | |
for (int i = 0; i < coffheader.NumberOfSections; i++) | |
{ | |
IntPtr CurrentSectionHeaderPtr = IntPtr.Zero; | |
CurrentSectionHeaderPtr = IntPtrAdd(SectionHeaderPtr, i * Marshal.SizeOf(typeof(CoffSectionHeader))); | |
CoffSectionHeader SectionHeader = (CoffSectionHeader)Marshal.PtrToStructure(CurrentSectionHeaderPtr, typeof(CoffSectionHeader)); | |
sections.Add(SectionHeader); | |
string CurrentSectionName = new string(SectionHeader.Name); | |
Console.WriteLine(CurrentSectionName); | |
if (SectionHeader.SectionSize != 0) | |
{ | |
IntPtr handle = Marshal.AllocHGlobal((int)SectionHeader.SectionSize); | |
// ignore .bss section because already initialized with zeros | |
if (!CurrentSectionName.StartsWith(".bss")) | |
{ | |
Marshal.Copy(PEBytes, (int)SectionHeader.RawdataPtr, handle, (int)SectionHeader.SectionSize); | |
} | |
Console.WriteLine($"[+] Mapping of {CurrentSectionName} at: {handle.ToString("x")}"); | |
} | |
} | |
// 将节导入到内存中后 记录一个节中在重定位表中使用的偏移 | |
// | |
uint size = 2048; | |
IntPtr GotHandle = Marshal.AllocHGlobal((int)size); | |
// Apply Relocation for all sections | |
// How to handle the relocations will change on each architecture | |
// and different file formats | |
byte[] GotTable = default; | |
foreach (var section in sections) | |
{ | |
for (int i = 0; i < section.RelocationsNumber; i++) | |
{ | |
IntPtr RelocationPtr = IntPtr.Zero; | |
RelocationPtr = IntPtrAdd(UnmanagedCoffBytes, (int)section.RelocationPtr + i * Marshal.SizeOf(typeof(CoffRelocation))); | |
CoffRelocation Relocation = (CoffRelocation)Marshal.PtrToStructure(RelocationPtr, typeof(CoffRelocation)); | |
IntPtr SymbolEntryPtr = IntPtrAdd(SymbolTablePtr, (int)Relocation.SymbolTableIndex * Marshal.SizeOf(typeof(CoffSymbolTable))); | |
CoffSymbolTable SymbolEntry = (CoffSymbolTable)Marshal.PtrToStructure(SymbolEntryPtr, typeof(CoffSymbolTable)); | |
// external symbol (imported function) | |
// IMAGE_SYM_CLASS_EXTERNAL 0x2 | |
// IMAGE_SYM_CLASS_STATIC 0x3 | |
// IMAGE_SYM_CLASS_LABEL 0x6 | |
// 这里判断是不是Long name,前四字节为0 后四字节是到字符串表的偏移 | |
if (SymbolEntry.StorageClass == 0x2 && new String(SymbolEntry.Name).StartsWith("\0")) | |
{ | |
// Compute symbol offset | |
// char 后四位字节转换为 int | |
IntPtr SymbolPtr = IntPtrAdd(SymbolValuePtr, SymbolEntry.Value); | |
// 总字符串表获取 Symbol | |
var Symbol = Marshal.PtrToStringAnsi(SymbolPtr); | |
Console.WriteLine(Symbol); | |
// ApplyRelocation(Relocation.VirtualAddress, section.); | |
} | |
// Direct relocation | |
else if (SymbolEntry.StorageClass == 0x3 || SymbolEntry.StorageClass == 0x6) | |
{ | |
// Apply-Relocation | |
// -VirtualAddress $Relocation.VirtualAddress | |
// -SourceAddress $CurrentSection.Handle | |
// -DestAddress $Sections[$SymbolEntry.SectionNumber - 1].Handle | |
// -Type $Relocation.Type -Win32Constants $Win32Constants | |
// Relocation.VirtualAddress | |
} | |
} | |
} | |
Marshal.Copy(GotTable, 0, GotHandle, GotTable.Length); | |
// Provisioning symbols | |
for (int i = 0; i < coffheader.NumberOfSymbols; i++) | |
{ | |
} | |
} | |
} | |
private const int IMAGE_REL_AMD64_ADDR64 = 0x1; | |
private const int IMAGE_REL_AMD64_ADDR32NB = 0x3; | |
private const int IMAGE_REL_AMD64_REL32 = 0x4; | |
private void ApplyRelocation(int VirtualAddress, IntPtr SourceAddress, IntPtr DestAddress, int type) | |
{ | |
IntPtr offsetPtr = IntPtrAdd(SourceAddress, VirtualAddress); | |
IntPtr EndOffsetPtr = offsetPtr + 4; // .net standard 2.0运算符重载 | |
// compute the relative address | |
if (type == IMAGE_REL_AMD64_REL32) | |
{ | |
// retrieve actual value of the offset | |
var OffsetValue = (Int32)Marshal.PtrToStructure(offsetPtr, typeof(Int32)); | |
OffsetValue += DestAddress.ToInt32() + EndOffsetPtr.ToInt32(); | |
Int32[] OffsetValueArray = { 0 }; | |
OffsetValueArray[0] = OffsetValue; | |
Marshal.Copy(OffsetValueArray, 0, offsetPtr, 1); | |
} | |
else if (type == IMAGE_REL_AMD64_ADDR32NB) | |
{ | |
var OffsetValue = (Int32)Marshal.PtrToStructure(offsetPtr, typeof(Int32)); | |
OffsetValue += DestAddress.ToInt32() + EndOffsetPtr.ToInt32(); | |
Int32[] OffsetValueArray = { 0 }; | |
OffsetValueArray[0] = OffsetValue; | |
Marshal.Copy(OffsetValueArray, 0, offsetPtr, 1); | |
} | |
else if (type == IMAGE_REL_AMD64_ADDR64) | |
{ | |
var OffsetValue = (Int32)Marshal.PtrToStructure(offsetPtr, typeof(Int64)); | |
OffsetValue += DestAddress.ToInt32() + EndOffsetPtr.ToInt32(); | |
Int32[] OffsetValueArray = { 0 }; | |
OffsetValueArray[0] = OffsetValue; | |
Marshal.Copy(OffsetValueArray, 0, offsetPtr, 1); | |
} | |
else | |
{ | |
Console.WriteLine("Unknown Relocation :" + type); | |
} | |
Console.WriteLine($"Apply relocation at: 0x{offsetPtr.ToString("x")}"); | |
} | |
/// <summary> | |
/// 内存加载bof文件 | |
/// 1. 加载读取bof | |
/// 2. 解析 FILE_HEADER | |
/// 3. 解析 SECTION_HEADER | |
/// 4. 解析SYMBOL符号表 | |
/// 5. 处理数据重定位和填充函数指针 | |
/// 6. 根据符号表寻找go函数的地址然后call过去 | |
/// | |
/// </summary> | |
/// <param name="coff"></param> | |
public void Loader(byte[] coff) | |
{ | |
} | |
private static byte[] ReadBytes(byte[] data, uint offset, uint size) | |
{ | |
if (size == 0) | |
{ | |
return default(byte[]); | |
} | |
if (size > Int32.MaxValue) | |
{ | |
return default(byte[]); | |
} | |
if (offset > data.Length) | |
{ | |
return default(byte[]); | |
} | |
byte[] tmp = new byte[size]; | |
using (MemoryStream ms = new MemoryStream(data)) | |
{ | |
ms.Position = offset; | |
ms.Read(tmp, 0, (int)size); | |
} | |
return tmp; | |
} | |
private static T FromBinaryReader<T>(BinaryReader reader) | |
{ | |
byte[] bytes = reader.ReadBytes(Marshal.SizeOf(typeof(T))); | |
GCHandle handle = GCHandle.Alloc(bytes, GCHandleType.Pinned); | |
T theStructure = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); | |
handle.Free(); | |
return theStructure; | |
} | |
private bool IsValidPeSignature(BinaryReader br) | |
{ | |
// read 4 bytes to get the PE signature | |
byte[] peSigBytes = br.ReadBytes(PeSignatureSize); | |
// convert it to a string and trim \0 at the end of the content | |
string peContent = Encoding.Default.GetString(peSigBytes).TrimEnd('\0'); | |
// check if PE is in the content | |
return peContent.Equals(PeSignatureContent); | |
} | |
private void SeekToPeSignature(BinaryReader br) | |
{ | |
// seek to the offset for the PE signature | |
br.BaseStream.Seek(PeSignatureOffsetLocation, SeekOrigin.Begin); | |
// read the offset | |
int offsetToPeSig = br.ReadInt32(); | |
// seek to the start of the PE signature | |
br.BaseStream.Seek(offsetToPeSig, SeekOrigin.Begin); | |
} | |
} | |
#region 结构体 | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] | |
public struct CoffHeader | |
{ | |
public MachineType Machine; | |
public ushort NumberOfSections; | |
public uint TimeDateStamp; | |
public uint PointerToSymbolTable; | |
public uint NumberOfSymbols; | |
public ushort SizeOfOptionalHeader; | |
public UInt16 Characteristics; | |
} | |
/// <summary> | |
/// COFF 可选头就是可选头了 要不要无所谓 | |
/// </summary> | |
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)] | |
public struct CoffOptionalHeader | |
{ | |
public MagicNumber Magic; | |
public short VersionStamp; | |
public uint ExeCodeSize; | |
public uint InitDataSize; | |
public uint UnInitDataSize; | |
public int EntryPoint; | |
public int ExeCodeAddress; | |
public int InitDataAddress; | |
} | |
/// <summary> | |
/// COFF文件 Section结构 | |
/// </summary> | |
[StructLayout(LayoutKind.Explicit)] | |
public struct CoffSectionHeader | |
{ | |
[FieldOffset(0)] | |
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] | |
public char[] Name; | |
[FieldOffset(8)] | |
public uint PhysicalAddr; | |
[FieldOffset(12)] | |
public uint VirtualAddr; | |
[FieldOffset(16)] | |
public uint SectionSize; | |
[FieldOffset(20)] | |
public uint RawdataPtr; | |
[FieldOffset(24)] | |
public uint RelocationPtr; | |
[FieldOffset(28)] | |
public uint LineNumberPtr; | |
[FieldOffset(32)] | |
public ushort RelocationsNumber; | |
[FieldOffset(34)] | |
public ushort LineNumbersNumber; | |
[FieldOffset(36)] | |
public uint Characteristics; | |
} | |
public enum MachineType : ushort | |
{ | |
Native = 0, | |
I386 = 0x014c, | |
Itanium = 0x0200, | |
x64 = 0x8664 | |
} | |
public enum MagicNumber : ushort | |
{ | |
TMS470 = 0x0097, | |
TMS320 = 0x0098, | |
C5400 = 0x0098, | |
C6000 = 0x0099, | |
C5500 = 0x009C, | |
C2800 = 0x009D, | |
MSP430 = 0x00A0, | |
C5500_High = 0x00A1 | |
} | |
/// <summary> | |
/// C2800 C6000 MSP430 TMS470 编译器使用10字节 | |
/// </summary> | |
[StructLayout(LayoutKind.Explicit, Pack = 2)] // Pack 结构的封装大小 | |
public struct CoffRelocation | |
{ | |
[FieldOffset(0)] | |
public uint VirtualAddress; // 引用的虚拟地址 | |
[FieldOffset(4)] | |
public uint SymbolTableIndex; // 符号表搜索 .rdata __imp_KERNEL32$HeapFree | |
[FieldOffset(8)] | |
public ushort RelocationType; | |
} | |
/// <summary> | |
/// 符号表 | |
/// </summary> | |
[StructLayout(LayoutKind.Explicit, Pack = 1)] // Pack 结构的封装大小 | |
public struct CoffSymbolTable | |
{ | |
[FieldOffset(0)] | |
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] | |
// Invoke-BOF 这里定义了三个int Value1 Value2 Value3 | |
// Long Name 超过8个字符 则前4字节为0 后四字节是到字符串表的偏移 | |
public char[] Name; | |
[FieldOffset(8)] | |
public int Value; | |
[FieldOffset(12)] | |
public ushort SectionNumber; | |
[FieldOffset(14)] | |
public ushort Type; // 0x20函数 0x0不是函数 | |
[FieldOffset(16)] | |
public char StorageClass; // 存储类的枚举值 | |
[FieldOffset(17)] | |
public char NumberOfAuxSymbols; // 跟随此记录的后背auxiliary符号表条目的数目 | |
} | |
#endregion | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment