Add two undocumented API in ntdll (#386)

API1: DbgUiSetThreadDebugObject
API2: NtRemoveProcessDebug
pull/387/head
Ruofan 2023-04-04 21:45:07 +08:00 committed by GitHub
parent 38e611f1e3
commit a9ff5e3c8f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 276 additions and 193 deletions

View File

@ -300,6 +300,33 @@ namespace Vanara.PInvoke
[In] HPROCESS ParentProcess, [In] PROCESS_CREATE_FLAGS Flags, [In, Optional] IntPtr SectionHandle,
[In, Optional] IntPtr DebugPort, [In, Optional] IntPtr ExceptionPort, uint JobMemberLevel);
/// <summary>Set the debug object handle in the TEB. This function is UNDOCUMENTED.</summary>
/// <param name="DebugObjectHandle">Debug object handle. Retrieve from NtQueryInformationProcess</param>
/// <returns>
/// <para>The function returns an NTSTATUS success or error code.</para>
/// <para>
/// The forms and significance of NTSTATUS error codes are listed in the Ntstatus.h header file available in the DDK, and are
/// described in the DDK documentation under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques /
/// Logging Errors.
/// </para>
/// </returns>
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
public static extern NTStatus DbgUiSetThreadDebugObject(IntPtr DebugObjectHandle);
/// <summary>Call the kernel to remove the debug object. This function is UNDOCUMENTED.</summary>
/// <param name="ProcessHandle">The process handle.</param>
/// <param name="DebugObjectHandle">Debug object handle. Retrieve from NtQueryInformationProcess</param>
/// <returns>
/// <para>The function returns an NTSTATUS success or error code.</para>
/// <para>
/// The forms and significance of NTSTATUS error codes are listed in the Ntstatus.h header file available in the DDK, and are
/// described in the DDK documentation under Kernel-Mode Driver Architecture / Design Guide / Driver Programming Techniques /
/// Logging Errors.
/// </para>
/// </returns>
[DllImport(Lib.NtDll, SetLastError = false, ExactSpelling = true)]
public static extern NTStatus NtRemoveProcessDebug(HPROCESS ProcessHandle, IntPtr DebugObjectHandle);
/// <summary>
/// <para>
/// [ <c>NtQueryInformationProcess</c> may be altered or unavailable in future versions of Windows. Applications should use the

View File

@ -1,10 +1,6 @@
using NUnit.Framework;
using NUnit.Framework.Constraints;
using System;
using System.Diagnostics;
using System.Linq;
using Vanara.Extensions;
using Vanara.InteropServices;
using static Vanara.PInvoke.NtDll;
namespace Vanara.PInvoke.Tests
@ -68,5 +64,65 @@ namespace Vanara.PInvoke.Tests
Assert.That(() => ppb = NtQueryInformationProcess<uint>(hProc, PROCESSINFOCLASS.ProcessPriorityBoost), Throws.Nothing);
TestContext.WriteLine($"Priority boost: {ppb.Value}");
}
[Test]
public void DbgUiSetThreadDebugObjectAndNtRemoveProcessDebugTest()
{
Kernel32.STARTUPINFO StartInfo = new Kernel32.STARTUPINFO
{
dwFlags = Kernel32.STARTF.STARTF_USESHOWWINDOW,
wShowWindow = (ushort)ShowWindowCommand.SW_HIDE
};
Assert.IsTrue(Kernel32.CreateProcess("notepad.exe", dwCreationFlags: Kernel32.CREATE_PROCESS.DEBUG_PROCESS | Kernel32.CREATE_PROCESS.CREATE_UNICODE_ENVIRONMENT, lpStartupInfo: StartInfo, lpProcessInformation: out Kernel32.SafePROCESS_INFORMATION Information));
using (Information)
using (NtQueryResult<IntPtr> DebugObjectHandleQueryResult = NtQueryInformationProcess<IntPtr>(Information.hProcess, PROCESSINFOCLASS.ProcessDebugObjectHandle))
{
Assert.That(DebugObjectHandleQueryResult, ResultIs.ValidHandle);
Assert.That(DebugObjectHandleQueryResult.Value, ResultIs.ValidHandle);
try
{
Assert.DoesNotThrow(() => DbgUiSetThreadDebugObject(DebugObjectHandleQueryResult.Value).ThrowIfFailed());
try
{
Kernel32.SafeHPROCESS DebugProcessHandle = Kernel32.SafeHPROCESS.Null;
try
{
while (true)
{
Assert.IsTrue(Kernel32.WaitForDebugEvent(out Kernel32.DEBUG_EVENT Event, Kernel32.INFINITE));
if (Event.dwDebugEventCode == Kernel32.DEBUG_EVENT_CODE.CREATE_PROCESS_DEBUG_EVENT)
{
DebugProcessHandle = new Kernel32.SafeHPROCESS(Event.u.CreateProcessInfo.hProcess);
break;
}
Assert.IsTrue(Kernel32.ContinueDebugEvent(Event.dwProcessId, Event.dwThreadId, Kernel32.DEBUG_CONTINUE.DBG_CONTINUE));
}
Assert.AreNotEqual(Kernel32.SafeHPROCESS.Null, DebugProcessHandle);
}
finally
{
DebugProcessHandle.Dispose();
}
}
finally
{
Assert.DoesNotThrow(() => DbgUiSetThreadDebugObject(IntPtr.Zero).ThrowIfFailed());
}
}
finally
{
Assert.IsTrue(Kernel32.TerminateProcess(Information.hProcess, 0));
Assert.DoesNotThrow(() => NtRemoveProcessDebug(Information.hProcess, DebugObjectHandleQueryResult.Value).ThrowIfFailed());
}
}
}
}
}