-
Notifications
You must be signed in to change notification settings - Fork 197
/
WinternlTests.cs
119 lines (107 loc) · 4.93 KB
/
WinternlTests.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
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
using NUnit.Framework;
using static Vanara.PInvoke.NtDll;
namespace Vanara.PInvoke.Tests;
[TestFixture]
public partial class WinternlTests
{
[Test]
public void NtQueryInformationProcessTest()
{
HPROCESS hProc = Kernel32.GetCurrentProcess();
var procIsWow64 = hProc.IsWow64();
var procIs64 = Environment.Is64BitProcess;
var osIs64 = Environment.Is64BitOperatingSystem;
using var pbi = NtQueryInformationProcess<PROCESS_BASIC_INFORMATION>(hProc, PROCESSINFOCLASS.ProcessBasicInformation);
Assert.That(pbi, ResultIs.ValidHandle);
// Can get pointer here since PROCESS_BASIC_INFORMATION has no managed types
unsafe
{
var rpbi = (PROCESS_BASIC_INFORMATION*)pbi;
Assert.That(rpbi->UniqueProcessId.ToInt32(), Is.EqualTo(Kernel32.GetCurrentProcessId()));
Assert.That(rpbi->PebBaseAddress, Is.Not.EqualTo(IntPtr.Zero));
// Have to use ToStructure here since PEB has managed types
var peb = rpbi->PebBaseAddress.ToStructure<PEB>();
// Have to use ToStructure here since RTL_USER_PROCESS_PARAMETERS has managed types
var upp = peb.ProcessParameters.ToStructure<RTL_USER_PROCESS_PARAMETERS>();
Assert.That(upp.CommandLine.ToString(hProc), Is.Not.Empty);
TestContext.WriteLine($"Img: {upp.ImagePathName.ToString(hProc)}; CmdLine: {upp.CommandLine.ToString(hProc)}");
}
NtQueryResult<IntPtr>? pdp = null;
Assert.That(() => pdp = NtQueryInformationProcess<IntPtr>(hProc, PROCESSINFOCLASS.ProcessDebugPort), Throws.Nothing);
Assert.That(pdp, ResultIs.ValidHandle);
TestContext.WriteLine($"DbgPort: {pdp?.Value.ToInt64()}");
NtQueryResult<BOOL>? pwi = null;
Assert.That(() => pwi = NtQueryInformationProcess<BOOL>(hProc, PROCESSINFOCLASS.ProcessWow64Information), Throws.Nothing);
Assert.That(pwi, ResultIs.ValidHandle);
Assert.That(pwi?.Value.Value, Is.True);
NtQueryResult<UNICODE_STRING>? pfn = null;
Assert.That(() => pfn = NtQueryInformationProcess<UNICODE_STRING>(hProc, PROCESSINFOCLASS.ProcessImageFileName), Throws.Nothing);
Assert.That(pfn, ResultIs.ValidHandle);
TestContext.WriteLine($"Fn: {pfn?.Value.ToString(hProc)}");
NtQueryResult<BOOL>? pbt = null;
Assert.That(() => pbt = NtQueryInformationProcess<BOOL>(hProc, PROCESSINFOCLASS.ProcessBreakOnTermination), Throws.Nothing);
Assert.That(pbt, ResultIs.ValidHandle);
Assert.That(pbt?.Value.Value, Is.False);
NtQueryResult<SUBSYSTEM_INFORMATION_TYPE>? psi = null;
// This is documented, but fails on Win10
Assert.That(() => psi = NtQueryInformationProcess<SUBSYSTEM_INFORMATION_TYPE>(hProc, PROCESSINFOCLASS.ProcessSubsystemInformation), Throws.ArgumentException);
//Assert.That(psi, ResultIs.ValidHandle);
//Assert.That(Enum.IsDefined(typeof(SUBSYSTEM_INFORMATION_TYPE), psi.Value), Is.True);
//TestContext.WriteLine($"SubSys: {psi.Value}");
// Try undocumented fetch
NtQueryResult<uint>? ppb = null;
Assert.That(() => ppb = NtQueryInformationProcess<uint>(hProc, PROCESSINFOCLASS.ProcessPriorityBoost), Throws.Nothing);
TestContext.WriteLine($"Priority boost: {ppb?.Value}");
}
[Test]
public void DbgUiSetThreadDebugObjectAndNtRemoveProcessDebugTest()
{
Kernel32.STARTUPINFO StartInfo = new()
{
dwFlags = Kernel32.STARTF.STARTF_USESHOWWINDOW,
wShowWindow = (ushort)ShowWindowCommand.SW_HIDE
};
Assert.That(Kernel32.CreateProcess(@"C:\Program Files\Notepad++\notepad++.exe", dwCreationFlags: Kernel32.CREATE_PROCESS.DEBUG_PROCESS | Kernel32.CREATE_PROCESS.CREATE_UNICODE_ENVIRONMENT, lpStartupInfo: StartInfo, lpProcessInformation: out Kernel32.SafePROCESS_INFORMATION Information), ResultIs.Successful);
using (Information)
using (NtQueryResult<IntPtr> DebugObjectHandleQueryResult = NtQueryInformationProcess<IntPtr>(Information.hProcess, PROCESSINFOCLASS.ProcessDebugObjectHandle))
{
Assert.That(DebugObjectHandleQueryResult, ResultIs.ValidHandle);
Assert.That(DebugObjectHandleQueryResult.Value, ResultIs.ValidHandle);
try
{
DbgUiSetThreadDebugObject(DebugObjectHandleQueryResult.Value);
try
{
Kernel32.SafeHPROCESS DebugProcessHandle = Kernel32.SafeHPROCESS.Null;
try
{
while (true)
{
Assert.That(Kernel32.WaitForDebugEvent(out Kernel32.DEBUG_EVENT Event, Kernel32.INFINITE), ResultIs.Successful);
if (Event.dwDebugEventCode == Kernel32.DEBUG_EVENT_CODE.CREATE_PROCESS_DEBUG_EVENT)
{
DebugProcessHandle = new Kernel32.SafeHPROCESS(Event.u.CreateProcessInfo.hProcess);
break;
}
Assert.That(Kernel32.ContinueDebugEvent(Event.dwProcessId, Event.dwThreadId, Kernel32.DEBUG_CONTINUE.DBG_CONTINUE), ResultIs.Successful);
}
Assert.False(DebugProcessHandle.IsNull);
}
finally
{
DebugProcessHandle.Dispose();
}
}
finally
{
DbgUiSetThreadDebugObject(IntPtr.Zero);
}
}
finally
{
Assert.That(Kernel32.TerminateProcess(Information.hProcess, 0), ResultIs.Successful);
Assert.That(NtRemoveProcessDebug(Information.hProcess, DebugObjectHandleQueryResult.Value), ResultIs.Successful);
}
}
}
}