原理
正常情况下,我们自己的进程的父进程是 explorer.exe ,当然也有很多进程的父进程不是 explorer.exe(比如服务进程)但这不是我们考虑的范畴。如果程序在调试则父进程是就是调试器进程。
代码示例
// Test_Console_1.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <Windows.h>
#include <intrin.h>
using namespace std;
typedef NTSTATUS(WINAPI* pNtQueryInformationProcess)(IN HANDLE, IN UINT, OUT PVOID, IN ULONG, OUT PULONG);
typedef struct _ALK_PROCESS_BASIC_INFORMATION {
PVOID Reserved1; // 进程终止状态
void* PebBaseAddress; // peb 地址
PVOID Reserved2[2]; // 进程关联掩码,优先级
ULONG_PTR UniqueProcessId; // 进程 ID
ULONG_PTR ParentProcessId; // 父进程 ID
} ALK_PROCESS_BASIC_INFORMATION;
int main()
{
// 获取 explorer.exe 进程 ID
DWORD d_expID = 0;
GetWindowThreadProcessId(
GetShellWindow(), // program manager 窗口句柄
&d_expID // 窗口对应的进程 ID
);
// 获取自身父进程 ID
pNtQueryInformationProcess NtQueryInformationProcess = (pNtQueryInformationProcess)GetProcAddress(LoadLibrary(L"ntdll.dll"), "ZwQueryInformationProcess");
if (NtQueryInformationProcess == NULL) {
goto main_end;
}
ALK_PROCESS_BASIC_INFORMATION pbi;
SecureZeroMemory(&pbi, sizeof(ALK_PROCESS_BASIC_INFORMATION));
if (NtQueryInformationProcess(GetCurrentProcess(), 0, (PVOID)&pbi, sizeof(ALK_PROCESS_BASIC_INFORMATION), 0) != 0) {
goto main_end;
}
// 判断调试器
if (pbi.ParentProcessId != d_expID) {
cout << "发现调试器!" << endl;
}
else {
cout << "没有调试器" << endl;
}
main_end:
getchar();
return 0;
}
效果图
vs调试:
正常运行: