AI智能
改变未来

反调试——2——深入NtQueryInformationProcess


反调试——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这个调试器是做了一些反反调试器的功能的。

赞(0) 打赏
未经允许不得转载:爱站程序员基地 » 反调试——2——深入NtQueryInformationProcess