Skip to content

Instantly share code, notes, and snippets.

@MSDN-WhiteKnight
Last active September 7, 2021 04:15
Show Gist options
  • Save MSDN-WhiteKnight/62ef8d733fabbf1dbd01dedf3b43132e to your computer and use it in GitHub Desktop.
Save MSDN-WhiteKnight/62ef8d733fabbf1dbd01dedf3b43132e to your computer and use it in GitHub Desktop.
LoadLibraryEx
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace ConsoleApp1
{
class Program
{
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
static extern IntPtr LoadLibrary([MarshalAs(UnmanagedType.LPStr)] string lpFileName);
[Flags]
enum LoadLibraryFlags : uint
{
None = 0,
DONT_RESOLVE_DLL_REFERENCES = 0x00000001,
LOAD_IGNORE_CODE_AUTHZ_LEVEL = 0x00000010,
LOAD_LIBRARY_AS_DATAFILE = 0x00000002,
LOAD_LIBRARY_AS_DATAFILE_EXCLUSIVE = 0x00000040,
LOAD_LIBRARY_AS_IMAGE_RESOURCE = 0x00000020,
LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200,
LOAD_LIBRARY_SEARCH_DEFAULT_DIRS = 0x00001000,
LOAD_LIBRARY_SEARCH_DLL_LOAD_DIR = 0x00000100,
LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800,
LOAD_LIBRARY_SEARCH_USER_DIRS = 0x00000400,
LOAD_WITH_ALTERED_SEARCH_PATH = 0x00000008
}
[DllImport("kernel32.dll", SetLastError = true)]
static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hReservedNull, LoadLibraryFlags dwFlags);
[StructLayout(LayoutKind.Sequential)]
public struct MODULEINFO
{
public IntPtr lpBaseOfDll;
public uint SizeOfImage;
public IntPtr EntryPoint;
}
[DllImport("psapi.dll", SetLastError = true)]
static extern bool GetModuleInformation(IntPtr hProcess, IntPtr hModule, out MODULEINFO lpmodinfo, uint cb);
[DllImport("kernel32.dll", SetLastError = true)]
static extern bool ReadProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
[Out] byte[] lpBuffer,
int dwSize,
out IntPtr lpNumberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true, EntryPoint = "ReadProcessMemory")]
static extern bool ReadProcessMemory_Byte(
IntPtr hProcess, IntPtr lpBaseAddress, out byte lpBuffer, int dwSize, out IntPtr lpNumberOfBytesRead
);
[StructLayout(LayoutKind.Sequential)]
public struct MEMORY_BASIC_INFORMATION
{
public IntPtr BaseAddress;
public IntPtr AllocationBase;
public uint AllocationProtect;
public IntPtr RegionSize;
public uint State;
public uint Protect;
public uint Type;
}
public enum AllocationProtect : uint
{
PAGE_EXECUTE = 0x00000010,
PAGE_EXECUTE_READ = 0x00000020,
PAGE_EXECUTE_READWRITE = 0x00000040,
PAGE_EXECUTE_WRITECOPY = 0x00000080,
PAGE_NOACCESS = 0x00000001,
PAGE_READONLY = 0x00000002,
PAGE_READWRITE = 0x00000004,
PAGE_WRITECOPY = 0x00000008,
PAGE_GUARD = 0x00000100,
PAGE_NOCACHE = 0x00000200,
PAGE_WRITECOMBINE = 0x00000400
}
const uint MEM_COMMIT = 0x1000;
const uint MEM_FREE = 0x10000;
const uint MEM_RESERVE = 0x2000;
[DllImport("kernel32.dll")]
static extern int VirtualQueryEx(IntPtr hProcess, IntPtr lpAddress, out MEMORY_BASIC_INFORMATION lpBuffer, uint dwLength);
public struct MemoryRegion
{
public long Address { get; set; }
public long Size { get; set; }
public bool IsReadable { get; set; }
}
static bool IsReadAccess(uint protectionFlags)
{
AllocationProtect ap = (AllocationProtect)protectionFlags;
return ap == AllocationProtect.PAGE_EXECUTE_READ ||
ap == AllocationProtect.PAGE_EXECUTE_READWRITE ||
ap == AllocationProtect.PAGE_EXECUTE_WRITECOPY ||
ap == AllocationProtect.PAGE_READONLY ||
ap == AllocationProtect.PAGE_READWRITE ||
ap == AllocationProtect.PAGE_WRITECOPY;
}
public static MemoryRegion[] GetMemoryRegions(IntPtr hProcess, IntPtr address, int size)
{
List<MemoryRegion> ret = new List<MemoryRegion>(50);
long MaxAddress = (long)address + size;
while(true)
{
MEMORY_BASIC_INFORMATION m=new MEMORY_BASIC_INFORMATION();
int result = VirtualQueryEx(
hProcess, address, out m, (uint)Marshal.SizeOf(m)
);
if (result==0||m.RegionSize == IntPtr.Zero) break;
MemoryRegion reg = new MemoryRegion();
reg.Address = (long)m.BaseAddress;
reg.Size = (long)m.RegionSize;
if (m.State == MEM_COMMIT && IsReadAccess(m.AllocationProtect))
{
reg.IsReadable = true;
}
ret.Add(reg);
address = (IntPtr)((long)m.BaseAddress + (long)m.RegionSize);
if ((long)address > MaxAddress) break;
}
return ret.ToArray();
}
static void EnumMemoryRegions(IntPtr hProcess,IntPtr address, int size)
{
MemoryRegion[] regions = GetMemoryRegions(hProcess, address, size);
for (int i = 0; i < regions.Length; i++)
{
Console.WriteLine("0x{0} : {1} bytes, Readable: {2}",
regions[i].Address.ToString("X"), regions[i].Size, regions[i].IsReadable
);
}
}
[STAThread]
static void Main(string[] args)
{
string path = "C:\\Test\\Lib.dll";
//string path = typeof(object).Assembly.Location;
IntPtr hModule = LoadLibraryEx(path, IntPtr.Zero, LoadLibraryFlags.None);
if (hModule == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error());
IntPtr hProcess = Process.GetCurrentProcess().Handle;
MODULEINFO mi = new MODULEINFO();
bool res = GetModuleInformation(hProcess, hModule, out mi, (uint)Marshal.SizeOf(mi));
if (res == false) throw new Win32Exception(Marshal.GetLastWin32Error());
EnumMemoryRegions(hProcess, mi.lpBaseOfDll, (int)mi.SizeOfImage);
byte[] data = new byte[mi.SizeOfImage];
IntPtr c;
int count_errors = 0;
for (int i = 0; i < data.Length; i++)
{
byte b = 0;
res = ReadProcessMemory_Byte(hProcess, mi.lpBaseOfDll + i, out b, 1, out c);
if (res == false || c == IntPtr.Zero) count_errors++;
else data[i] = b;
}
Console.WriteLine(count_errors);
;
Console.ReadKey();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment