Я опаздываю на вечеринку, но мне просто нужно было сделать это для личного "проекта любопытства" - подписи в итоге выглядят так:
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct LIST_ENTRY
{
public IntPtr Flink;
public IntPtr Blink;
public ListEntryWrapper Fwd
{
get
{
var fwdAddr = Flink.ToInt32();
return new ListEntryWrapper()
{
Header = Flink.ReadMemory<LIST_ENTRY>(),
Body = new IntPtr(fwdAddr + Marshal.SizeOf(typeof(LIST_ENTRY))).ReadMemory<LDR_MODULE>()
};
}
}
public ListEntryWrapper Back
{
get
{
var fwdAddr = Blink.ToInt32();
return new ListEntryWrapper()
{
Header = Flink.ReadMemory<LIST_ENTRY>(),
Body = new IntPtr(fwdAddr + Marshal.SizeOf(typeof(LIST_ENTRY))).ReadMemory<LDR_MODULE>()
};
}
}
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct ListEntryWrapper
{
public LIST_ENTRY Header;
public LDR_MODULE Body;
}
[StructLayout(LayoutKind.Sequential)]
public struct UNICODE_STRING : IDisposable
{
public ushort Length;
public ushort MaximumLength;
private IntPtr buffer;
public UNICODE_STRING(string s)
{
Length = (ushort)(s.Length * 2);
MaximumLength = (ushort)(Length + 2);
buffer = Marshal.StringToHGlobalUni(s);
}
public void Dispose()
{
Marshal.FreeHGlobal(buffer);
buffer = IntPtr.Zero;
}
public override string ToString()
{
return Marshal.PtrToStringUni(buffer);
}
}
[StructLayout(LayoutKind.Sequential, Pack = 0)]
public struct PEB_LDR_DATA
{
public int Length;
public int Initialized;
public int SsHandle;
public IntPtr InLoadOrderModuleListPtr;
public IntPtr InMemoryOrderModuleListPtr;
public IntPtr InInitOrderModuleListPtr;
public int EntryInProgress;
public ListEntryWrapper InLoadOrderModuleList { get { return InLoadOrderModuleListPtr.ReadMemory<ListEntryWrapper>(); } }
public ListEntryWrapper InMemoryOrderModuleList { get { return InLoadOrderModuleListPtr.ReadMemory<ListEntryWrapper>(); } }
public ListEntryWrapper InInitOrderModuleList { get { return InLoadOrderModuleListPtr.ReadMemory<ListEntryWrapper>(); } }
}
Где IntPtr.ReadMemory простометод расширения:
public static T ReadMemory<T>(this IntPtr atAddress)
{
var ret = (T)Marshal.PtrToStructure(atAddress, typeof (T));
return ret;
}