NtQueryInformationProcess 是微软 未公开 的一个 API,嗯,这个反调试的方法有一个特点就是 能过吾爱破解版OD! ,其他版本的OD没有尝试,但相信这种反调试手法可以检测大部分的第三方OD。
首先需要知道的几点:
// NtQueryInformationProcess 函数原型
__kernel_entry NTSTATUS NtQueryInformationProcess(
IN HANDLE ProcessHandle, // 进程句柄
IN PROCESSINFOCLASS ProcessInformationClass, // 检索的进程信息类型
OUT PVOID ProcessInformation, // 接收进程信息的缓冲区指针
IN ULONG ProcessInformationLength, // 缓冲区指针大小
OUT PULONG ReturnLength // 实际接收的进程信息大小
);
// PROCESSINFOCLASS 结构体原型(别问我这都啥意思,我也不知道 /手动滑稽)
typedef enum _PROCESSINFOCLASS
{
ProcessBasicInformation, // 0x0
ProcessQuotaLimits,
ProcessIoCounters,
ProcessVmCounters,
ProcessTimes,
ProcessBasePriority,
ProcessRaisePriority,
ProcessDebugPort, // 0x7
ProcessExceptionPort,
ProcessAccessToken,
ProcessLdtInformation,
ProcessLdtSize,
ProcessDefaultHardErrorMode,
ProcessIoPortHandlers,
ProcessPooledUsageAndLimits,
ProcessWorkingSetWatch,
ProcessUserModeIOPL,
ProcessEnableAlignmentFaultFixup,
ProcessPriorityClass,
ProcessWx86Information,
ProcessHandleCount,
ProcessAffinityMask,
ProcessPriorityBoost,
ProcessDeviceMap,
ProcessSessionInformation,
ProcessForegroundInformation,
ProcessWow64Information, // 0x1A
ProcessImageFileName, // 0x1B
ProcessLUIDDeviceMapsEnabled,
ProcessBreakOnTermination,
ProcessDebugObjectHandle, // 0x1E
ProcessDebugFlags, // 0x1F
ProcessHandleTracing,
ProcessIoPriority,
ProcessExecuteFlags,
ProcessResourceManagement,
ProcessCookie,
ProcessImageInformation,
ProcessCycleTime,
ProcessPagePriority,
ProcessInstrumentationCallback,
ProcessThreadStackAllocation,
ProcessWorkingSetWatchEx,
ProcessImageFileNameWin32,
ProcessImageFileMapping,
ProcessAffinityUpdateMode,
ProcessMemoryAllocationMode,
ProcessGroupInformation,
ProcessTokenVirtualizationEnabled,
ProcessConsoleHostProcess,
ProcessWindowInformation,
ProcessHandleInformation,
ProcessMitigationPolicy,
ProcessDynamicFunctionTableInformation,
ProcessHandleCheckingMode,
ProcessKeepAliveCount,
ProcessRevokeFileHandles,
ProcessWorkingSetControl,
ProcessHandleTable,
ProcessCheckStackExtentsMode,
ProcessCommandLineInformation,
ProcessProtectionInformation,
ProcessMemoryExhaustion,
ProcessFaultInformation,
ProcessTelemetryIdInformation,
ProcessCommitReleaseInformation,
ProcessDefaultCpuSetsInformation,
ProcessAllowedCpuSetsInformation,
ProcessSubsystemProcess,
ProcessJobMemoryInformation,
ProcessInPrivate,
ProcessRaiseUMExceptionOnInvalidHandleClose,
ProcessIumChallengeResponse,
ProcessChildProcessInformation,
ProcessHighGraphicsPriorityInformation,
ProcessSubsystemInformation,
ProcessEnergyValues,
ProcessActivityThrottleState,
ProcessActivityThrottlePolicy,
ProcessWin32kSyscallFilterInformation,
ProcessDisableSystemAllowedCpuSets,
ProcessWakeInformation,
ProcessEnergyTrackingState,
ProcessManageWritesToExecutableMemory,REDSTONE3
ProcessCaptureTrustletLiveDump,
ProcessTelemetryCoverage,
ProcessEnclaveInformation,
ProcessEnableReadWriteVmLogging,
ProcessUptimeInformation,
ProcessImageSection,
ProcessDebugAuthInformation,
ProcessSystemResourceManagement,
ProcessSequenceNumber,
ProcessLoaderDetour,
ProcessSecurityDomainInformation,
ProcessCombineSecurityDomainsInformation,
ProcessEnableLogging,
ProcessLeapSecondInformation,
ProcessFiberShadowStackAllocation,
ProcessFreeFiberShadowStackAllocation,
MaxProcessInfoClass
} PROCESSINFOCLASS;
_PROCESSINFOCLASS → ProcessDebugPort:
进程处于被调试状态时,ProcessDebugPort = 0xffffffff
有调试器时:
没有调试器时:
参考代码:
#include "stdafx.h"
#include <iostream>
#include <windows.h>
#include <winternl.h>
#pragma region 依赖
typedef NTSTATUS(NTAPI *pfnNtQueryInformationProcess)(
_In_ HANDLE ProcessHandle,
_In_ UINT ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
#pragma endregion
int _tmain(int argc, _TCHAR* argv[])
{
pfnNtQueryInformationProcess NtQueryInformationProcess = NULL; // 存放 ntdll 中 NtQueryInformationProcess 函数地址
NTSTATUS status; // NTSTATUS 错误代码,0:执行成功
DWORD isDebuggerPresent = -1; // 如果当前被调试,则 = ffffffff
HMODULE hNtDll = LoadLibrary(TEXT("ntdll.dll")); // ntdll 模块句柄
// ntdll 加载成功
if(hNtDll){
// 取 NtQueryInformationProcess 函数地址
NtQueryInformationProcess = (pfnNtQueryInformationProcess)GetProcAddress(hNtDll, "NtQueryInformationProcess");
// 取地址成功
if (NtQueryInformationProcess){
// NtQueryInformationProcess 检测调试器
status = NtQueryInformationProcess(
GetCurrentProcess(), // 进程句柄
0x7, // 要检索的进程信息类型,ProcessDebugPort:调试器端口号
&isDebuggerPresent, // 接收进程信息的缓冲区指针
sizeof(DWORD), // 缓冲区大小
NULL // 实际返回进程信息的大小
);
// NtQueryInformationProcess 执行成功
if(status == 0 && isDebuggerPresent != 0){
// 输出
std::cout << "status = " << status << std::endl;
std::cout << "isDebuggerPresent = " << std::hex << isDebuggerPresent << std::endl;
std::cout << "检测到调试器" << std::endl;
getchar();
return 0;
}
}
}
// 输出
std::cout << "status = " << status << std::endl;
std::cout << "isDebuggerPresent = " << std::hex << isDebuggerPresent << std::endl;
std::cout << "没有发现调试器" << std::endl;
getchar();
return 0;
}
_PROCESSINFOCLASS → ProcessDebugObjectHandle:
ProcessDebugObjectHandle = 调试对象句柄
有调试器时:
没有调试器时:
代码:
// 只需要把 NtQueryInformationProcess() 中的 0x7 改成 0x1E
_PROCESSINFOCLASS → ProcessDebugFlags:
调试状态:ProcessDebugFlags = 0,非调试状态 ProcessDebugFlags = 1
有调试器时:
没有调试器时:
代码:
// 1.把 NtQueryInformationProcess() 中的 0x7 改成 0x1F
// 2.把 if(status == 0 && isDebuggerPresent != 0) 判断改为 if(status == 0 && isDebuggerPresent == 0)
就这些了,_PROCESSINFOCLASS 结构体力有很多成员查不到意思,如果哪个老哥知道,希望告知,先谢过啦 !!