I am writing a simple C++ project on Microsoft's Visual Studio 2022, that uses NtQueryInformationProcess to check if a process is being debugged but it is not working.
Here is my code:
#include "Header.h"
#include <iostream>
#include <winternl.h>
#include<Windows.h>
// Method use Debug flags in the PEB. This worked and return a = 1
int PEB_Flag() {
int a;
__asm {
mov eax, dword ptr fs : [18h]
mov eax, dword ptr ds : [eax + 30h]
movzx eax, byte ptr ds : [eax + 2h]
mov[a], eax
}
return a;
}
typedef enum _PROCESSINFOCLASS {
ProcessBasicInformation = 0,
ProcessDebugPort = 7,
ProcessWow64Information = 26,
ProcessImageFileName = 27,
ProcessBreakOnTermination = 29
} PROCESSINFOCLASS;
typedef NTSTATUS(NTAPI* TNtQueryInformationProcess)(
IN HANDLE ProcessHandle,
IN PROCESSINFOCLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength
);
int main() {
HANDLE ProcessHandler = OpenProcess(PROCESS_ALL_ACCESS, TRUE, GetCurrentProcessId());
HMODULE hNtdll = LoadLibraryA("ntdll.dll");
//HINSTANCE hNtDll = GetModuleHandleW(L"ntdll.dll");
std::cout << "hNtdll: " << std::hex << hNtdll << std::endl;
auto pfnNtQueryInformationProcess = (TNtQueryInformationProcess)GetProcAddress(
hNtdll, "NtQueryInformationProcess");
DWORD dwProcessDebugPort, dwReturned;
NTSTATUS status = pfnNtQueryInformationProcess(
//GetCurrentProcess(),
ProcessHandler,
ProcessDebugPort,
&dwProcessDebugPort,
sizeof(DWORD),
&dwReturned);
a = int(status);
std::cout << "Is debugged: " << a << std::endl;
std::cout << "OK ?";
std::cin >> a; // I set a breakpoint here
}
I build it, run it in both debug mode and realease mode, and it print "Is debugged: 0", which is wrong because this process is being debugged. I know that my code has something wrong, because I had tried with method check for debugger flag and it prints "1".
The return value of a call to the
NtQueryInformationProcessfunction indicates only whether or not the call succeeded (and, if it failed, and indication of the nature of the error). Thus, yourstatusvariable – assuming the call succeeds – will have the valueSTATUS_SUCCESS, which is defined as zero (whether or not you cast it to anint).The actual data that you want to inspect is the
dwProcessDebugPortDWORD, whose address you (seemingly correctly) pass to the system call. That will have a non-zero value if the process is being run under a debugger.So, after your call to
NtQueryInformationProcess, your 'diagnostic' code should look something like this: