Search code examples
c++windowswinapintdll

Use NtQueryInformationProcess to check for debugger attached


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".


Solution

  • The return value of a call to the NtQueryInformationProcess function indicates only whether or not the call succeeded (and, if it failed, and indication of the nature of the error). Thus, your status variable – assuming the call succeeds – will have the value STATUS_SUCCESS, which is defined as zero (whether or not you cast it to an int).

    The actual data that you want to inspect is the dwProcessDebugPort DWORD, 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:

    if (NT_SUCCESS(status)) {
        std::cout << (dwProcessDebugPort == 0 ? "Not debugging.\n" : "Debugging.\n");
    }
    else {
        std::cout << "Call failed!\n";
    }