PInvoke
- Platform Invoke aka P/Invoke allows you to access functions in unmanaged libraries from your managed C# code
- functions are declared with
externandDllImportkeywords
OpenProcess Api:
[DllImport("kernel32.dll", SetLastError = true)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern IntPtr OpenProcess(
PROCESS_ACCESS_RIGHTS dwDesiredAccess,
bool bInheritHandle,
int dwProcessId);
- settings
SetLastErrorto true allows you to get the error code of the last API that was called DefaultDllImportprotects against DLL Hijacking by forcing the application to look in System32
One of the downsides of P/Invoke is that we dont have access to Windows headers like Windows.h so we need to add the headers to our code:
[Flags]
internal enum PROCESS_ACCESS_RIGHTS : uint
{
PROCESS_TERMINATE = 0x00000001,
PROCESS_CREATE_THREAD = 0x00000002,
PROCESS_SET_SESSIONID = 0x00000004,
PROCESS_VM_OPERATION = 0x00000008,
PROCESS_VM_READ = 0x00000010,
PROCESS_VM_WRITE = 0x00000020,
PROCESS_DUP_HANDLE = 0x00000040,
PROCESS_CREATE_PROCESS = 0x00000080,
PROCESS_SET_QUOTA = 0x00000100,
PROCESS_SET_INFORMATION = 0x00000200,
PROCESS_QUERY_INFORMATION = 0x00000400,
PROCESS_SUSPEND_RESUME = 0x00000800,
PROCESS_QUERY_LIMITED_INFORMATION = 0x00001000,
PROCESS_SET_LIMITED_INFORMATION = 0x00002000,
PROCESS_ALL_ACCESS = 0x001FFFFF,
PROCESS_DELETE = 0x00010000,
PROCESS_READ_CONTROL = 0x00020000,
PROCESS_WRITE_DAC = 0x00040000,
PROCESS_WRITE_OWNER = 0x00080000,
PROCESS_SYNCHRONIZE = 0x00100000,
PROCESS_STANDARD_RIGHTS_REQUIRED = 0x000F0000
}
Marshalling
- Windows APIs have two variants: A(ANSI) and W(Unicode, aka 'wide')
LoadLibraryA,LoadLibraryW,CreateProcessA,CreateProcessW- The main difference between A and W are the types of encoding used for strings
- PInvoke needs a way to marashal managed C# strings as C# only has a single string type
- This is done by adding the
CharSetattribute
// ANSI
[DllImport("KERNEL32.dll", SetLastError = true, CharSet = CharSet.Ansi)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern IntPtr LoadLibraryA(string libFileName);
// Unicode
[DllImport("KERNEL32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)]
internal static extern IntPtr LoadLibraryW(string libFileName);