反调试 - NtQueryInformationProcess(ProcessDebugPort,ProcessDebugFlags,ProcessDebugObjectHandle)

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 结构体力有很多成员查不到意思,如果哪个老哥知道,希望告知,先谢过啦 !!

在这里插入图片描述

评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值