-
Notifications
You must be signed in to change notification settings - Fork 1
/
Pinvoke.cs
102 lines (89 loc) · 3.96 KB
/
Pinvoke.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace HitmanPatcher
{
// from https://docs.microsoft.com/en-us/windows/win32/memory/memory-protection-constants
[Flags]
public enum MemProtection : 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
}
// from https://docs.microsoft.com/en-us/windows/win32/procthread/process-security-and-access-rights
// I've only listed the ones that I use
[Flags]
public enum ProcessAccess : uint
{
PROCESS_QUERY_INFORMATION = 0x0400, // Required to retrieve certain information about a process
PROCESS_VM_READ = 0x0010, // Required to read memory in a process using ReadProcessMemory.
PROCESS_VM_WRITE = 0x0020, // Required to write to memory in a process using WriteProcessMemory.
PROCESS_VM_OPERATION = 0x0008 // Required to perform an operation on the address space of a process using VirtualProtectEx
}
// from https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess
public enum PROCESSINFOCLASS
{
ProcessBasicInformation = 0,
ProcessDebugPort = 7,
ProcessWow64Information = 26,
ProcessImageFileName = 27,
ProcessBreakOnTermination = 29,
ProcessSubsystemInformation = 75
}
// from https://docs.microsoft.com/en-us/windows/win32/api/winternl/nf-winternl-ntqueryinformationprocess
[StructLayout(LayoutKind.Sequential)]
public struct PROCESS_BASIC_INFORMATION
{
public IntPtr Reserved1;
public IntPtr PebBaseAddress;
public IntPtr Reserved2_0;
public IntPtr Reserved2_1;
public IntPtr UniqueProcessId;
public IntPtr Reserved3;
}
public static class Pinvoke
{
[DllImport("kernel32", SetLastError = true)]
public static extern IntPtr OpenProcess(ProcessAccess dwDesiredAccess, bool bInheritHandle, int dwProcessId);
[DllImport("kernel32", SetLastError = true)]
public static extern bool CloseHandle(IntPtr hObject);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool WriteProcessMemory([In] IntPtr hProcess, [In] IntPtr address, [In, MarshalAs(UnmanagedType.LPArray)] byte[] buffer, [In] UIntPtr size, [Out] out UIntPtr byteswritten);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool ReadProcessMemory([In] IntPtr hProcess, [In] IntPtr address, [Out, MarshalAs(UnmanagedType.LPArray, SizeParamIndex = 3)] byte[] buffer, [In] UIntPtr size, [Out] out UIntPtr numberOfBytesRead);
[DllImport("kernel32.dll", SetLastError = true)]
public static extern bool VirtualProtectEx([In] IntPtr hProcess, [In] IntPtr lpAddress, [In] UIntPtr dwSize, [In] MemProtection flNewProtect, [Out] out MemProtection lpflOldProtect);
[DllImport("ntdll.dll")]
public static extern int NtQueryInformationProcess(IntPtr hProcess, PROCESSINFOCLASS processInformationClass, out PROCESS_BASIC_INFORMATION processInformation, uint processInformationLength, out uint returnLength);
public static int GetProcessParentPid(Process process)
{
IntPtr hProcess = OpenProcess(
ProcessAccess.PROCESS_VM_READ
| ProcessAccess.PROCESS_QUERY_INFORMATION,
false, process.Id);
if (hProcess == IntPtr.Zero)
{
throw new Win32Exception(Marshal.GetLastWin32Error(), "Failed to get a process handle.");
}
PROCESS_BASIC_INFORMATION PEB = new PROCESS_BASIC_INFORMATION();
uint returnlength;
int result = NtQueryInformationProcess(hProcess, PROCESSINFOCLASS.ProcessBasicInformation, out PEB, (uint)Marshal.SizeOf(PEB), out returnlength);
CloseHandle(hProcess);
if (result != 0)
{
throw new Win32Exception(result, "(NTSTATUS)"); // not a w32 status code, but an NTSTATUS
}
return PEB.Reserved3.ToInt32(); // undocumented, but should hold the parent PID
}
}
}