您的位置:首页 > 产品设计 > UI/UE

反调试——2——深入NtQueryInformationProcess

2021-08-30 16:53 1056 查看

反调试——2——深入NtQueryInformationProcess

ProcessDebugPort这个标志位里面涉及到的东西比较复杂,所以要展开来讲。

CheckRemoteDebuggerPresent():

CheckRemoteDebuggerPresent function (debugapi.h) - Win32 apps | Microsoft Docs 该API的微软官方文档。

主要就是调用这个函数如果程序在被调试就会返回非零值,如果没有被调试就会返回0。

 

但是前面我们也解析了,其实CheckRemoteDebuggerPresent内部调用的是NtQueryInformationProcess函数来处理的。

 

两个函数的共同本质:如果程序处于调试状态,这Nt函数会查询调试端口并返回,Check函数会返回一个bool值。

 

BOOL CheckRemoteDebuggerPresent(
HANDLE hProcess,
PBOOL pbDebuggerPresent
);
__kernel_entry NTSTATUS NtQueryInformationProcess(
HANDLE           ProcessHandle,//进程句柄
PROCESSINFOCLASS ProcessInformationClass,//进程信息类型,传不同的值表示查进程不同的信息
PVOID           ProcessInformation,//输出参数 存储进行信息的缓冲区
ULONG           ProcessInformationLength,//缓冲区大小
PULONG           ReturnLength//实际大小
);

 

进程信息类型:(这里面有相当多的消息)pinvoke.net: PROCESSINFOCLASS (ntdll)

//其中比较常用有文档记录的
typedef enum _PROCESSINFOCLASS {
  ProcessDebugPort = 7,//调试端口
  ProcessDebugObjectHandle = 30,//获取调试对象句柄,句柄为空表示未调试
ProcessDebugFlags = 31 //检测调试标志位为0表示处于调试状态
} PROCESSINFOCLASS;

 

代码实现简单的NtQueryInformationProcess函数调用

首先这里需要从DLL里面获得函数,这里由于PROCESSINFOCLASS是一个枚举值,而且值都是0x00这样类型的,所以这里我们可以直接使用DWORD来取代,更加方便:

typedef NTSTATUS(NTAPI *_NtQueryInformationProcess)(
HANDLE           ProcessHandle,
DWORD ProcessInformationClass,
PVOID           ProcessInformation,
ULONG           ProcessInformationLength,
PULONG           ReturnLength
);

 

 

//头文件
#pragma once
#include<Windows.h>
#include<iostream>
typedef NTSTATUS(NTAPI *_NtQueryInformationProcess)(
HANDLE           ProcessHandle,
DWORD ProcessInformationClass,
PVOID           ProcessInformation,
ULONG           ProcessInformationLength,
PULONG           ReturnLength
);
using namespace std;

void testBeginDebugged();
void testNtGlobalFlag();
void testProcessDebugPort();
void testNtQueryInformationProcess();
void testNtPort(_NtQueryInformationProcess NtQueryInformationProcess);
void testNtObjectHandle(_NtQueryInformationProcess NtQueryInformationProcess);
void testFlag(_NtQueryInformationProcess NtQueryInformationProcess);
//源文件
#include"TestC++.h"

void testBeginDebugged()
{
if (IsDebuggerPresent())
{
cout << "BeginDebugged验证失败,程序被调试" << endl;
}
else
{
cout << "BeginDebugged验证正常" << endl;
}
}
void testNtGlobalFlag()
{
DWORD IsDebug = 1;
__asm
{
push eax
mov eax, fs: [0x30]
mov eax, [eax + 0x68]
mov IsDebug, eax
pop eax
}
if (IsDebug == 0x70)
{
cout << "NtGlobalFlag验证失败,程序被调试" << endl;
}
else
{
cout << "NtGlobalFlag验证正常" << endl;
}
}
void testProcessDebugPort()
{
BOOL IsDebug = FALSE;
CheckRemoteDebuggerPresent(GetCurrentProcess(), &IsDebug);
if(IsDebug == TRUE)
{
cout << "ProcessDebugPort验证失败,程序被调试" << endl;
}
else
{
cout << "ProcessDebugPort验证正常,程序未被调试" << endl;
}
}
void testNtQueryInformationProcess()
{
HMODULE hDll = LoadLibraryW(L"Ntdll.dll");
_NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress(hDll, "NtQueryInformationProcess");
testNtPort(NtQueryInformationProcess);
testNtObjectHandle(NtQueryInformationProcess);
testFlag(NtQueryInformationProcess);
}
void testNtPort(_NtQueryInformationProcess NtQueryInformationProcess)
{
HANDLE hProcess = GetCurrentProcess();
DWORD DebugPort;
NtQueryInformationProcess(hProcess,7,&DebugPort,sizeof(DWORD),NULL);
if (DebugPort != 0)
{
cout << "DebugPort验证失败,程序正在被调试" << endl;
}
else
{
cout << "DebugPort验证成功" << endl;
}
}
void testNtObjectHandle(_NtQueryInformationProcess NtQueryInformationProcess)
{
HANDLE hProcess = GetCurrentProcess();
HANDLE ObjectHandle;
NtQueryInformationProcess(hProcess, 30, &ObjectHandle, sizeof(ObjectHandle), NULL);
if (ObjectHandle != NULL)
{
cout << "调试端口验证失败,程序正在被调试" << endl;
}
else
{
cout << "调试端口验证成功" << endl;
}
}
void testFlag(_NtQueryInformationProcess NtQueryInformationProcess)
{
HANDLE hProcess = GetCurrentProcess();
BOOL Flags;
NtQueryInformationProcess(hProcess, 31, &Flags, sizeof(Flags), NULL);
if (Flags != 1)
{
cout << "调试端口验证失败,程序正在被调试" << endl;
}
else
{
cout << "调试端口验证成功" << endl;
}
}

int main()
{
printf("%s\n", "Welcome");
cout << "Welcome" << endl;
testBeginDebugged();
testNtGlobalFlag();
testProcessDebugPort();
testNtQueryInformationProcess();

return 0;
}

采用OD查看:

 

 

 

 

采用VS调试器查看:

 

 

采用直接运行:

 

 

这个我一直想不通,按理来说应该是都正常啊,然后我想了一下有没有可能是Debug模式的问题,所以我打开了release版本的:

运行Release版本的exe:

 

 

证明了刚刚的猜测,也可以看到od这个调试器是做了一些反反调试器的功能的。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: