Skip to content

Instantly share code, notes, and snippets.

@bopin2020
Created January 1, 2023 13:38
Show Gist options
  • Save bopin2020/d2d7b8a411c36bdd713975e95f95e294 to your computer and use it in GitHub Desktop.
Save bopin2020/d2d7b8a411c36bdd713975e95f95e294 to your computer and use it in GitHub Desktop.
#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