NTDLL:反调试中需要包含NtDll头文件
以上是包含的格式!
PEB(进程环境块):
概述:在你进行打开这个程序或以调试方式打开这个程序、那么操作系统会对你这个进程的进程环境块的一些标志设置一系列的属性
调试器:如果你使用系统的调试方法、那么系统就会把相对应的标志位给设置上
PEB有四个标志位
在fs : [0x30]这处地方就是PEB的指针 需要用*PEB指针进行接收
PEB中有四个标志位(检测是否被调试):
PEB
{
BeingDebugger:1
NtGlobalFlag:0x70
HeapFlags:=2 offset (x32) 0x40!=2 则被调试状态 0x70!=0则被调试状态
ForceFlags:=0 offset (x32)0x44!=2 则被调试状态 0x74
}
**如果PEB的BeingDebugger为True的话则说明被调试!
(NtGlobalFlag & 0x70) == True 则说明被调试状态**
这个API的原理就是获取TEB (fs:0x18)然后再获取PEB然后再获取PEB的BeingDebugger成员、如果为1则有调试
WinApi:IsDebuggerPresent() 检测是被调试、如果为返回值为True则为调试状态、如果为False则为没有被调试
概述:检查远程调试器
原理:原理用NtQueryInformationProcess检查ProcessDebugPort这个属性
参数一:HANDLE hProcess 句柄
参数二:PBOOL pbDebuggerPresent 指向是否被调试的指针、如果返回值为true则为调试状态、如果为false则为未调试状态
这个原理就是查询SystemKernelDebuggerInformation的信息
这个API函数检测当前系统是否正在调试状态
这个函数可以判断当前这个系统是否被内核调试器给附加或者是给调试状态、比如双机调试
参数一:SystemKernelDebuggerInformation
参数二:指向SYSTEM_KERNEL_DEBUGGER_INFORMATION结构体的指针
参数三:SYSTEM_KERNEL_DEBUGGER_INFORMATION结构体的长度
参数四:返回一个长度
返回值:应用层所有Nt函数成功都是返回0、和驱动层是反过来的、内核层成功返回1、所有可以用NT_SUCCESS这个宏来判断Nt函数是否被调用成功
typedef struct _SYSTEM_KERNEL_DEBUGGER_INFORMATION
{
BOOLEAN KernelDebuggerEnabled;
BOOLEAN KernelDebuggerNotPresent;
} SYSTEM_KERNEL_DEBUGGER_INFORMATION, *PSYSTEM_KERNEL_DEBUGGER_INFORMATION;
其实就是一个CloseHandle、如果有调试器的情况下关闭一个无效的句柄则会触发一个异常、可以用VEH进行接收并处理
如果有调试器存在的话NtClose就会触发一个异常、则可以捕获这个异常
来判断是否被调试器调试状态
NtClose
参数一:In HANDLE Handle 句柄、这里需要用到ULongToHandle()进行转换
这个函数是像系统查询环境块的属性、仅仅是查询的作用、一些调试信息保存在操作系统内核、所有用这个函数对它进行查询就行
这个是加密壳里用到最多的反调试函数、这个函数非常重要
函数的定义:
参数一:当前窗口句柄
参数二:可以指定ProcessDebugPort、ProcessDebugObjectHandle、ProcessDebugFlags
参数三:接收进程信息的指针
参数四:指针的长度 比如sizeof(PVOID)
参数五:返回长度
返回值:成功返回0 失败返回1
注意一:
如果参数二等于ProcessDebugPort、ProcessDebugObjectHandle 则ProcessInformation != NULL (不为0)、的情况下的情况下表示当前正在被调试
注意二:
如果是参数二等于ProcessDebugObjectHandle则Nt函数返回值是0xC0000353则当前没有被调试、否则即为调试状态
注意三:
如果参数二等于ProcessDebugFlags标志、则ProcessInformation != 1则为被调试状态
如果成功调用这个API则会分离调试器、无论怎么下断点都断不下!
清除了DebuggerPort、调试器接收不了所有调试事件等
函数定义:
参数一:当前线程的句柄可以设置为NtCurrentThread
参数二:可以设置为ThreadHideFromDebugger标志
参数三:NULL
参数四:NULL
相当于NtClose函数
这个反调试是SE壳商业版用的一个反调试SE壳商业版和普通班相比就多了一个
函数定义
参数一:原进程的句柄
参数二:目标进程的句柄
参数三:复制到的进程句柄
参数四:用来返回真实的句柄
参数五:NULL
参数六:复制完成句柄操作、可关闭、可不关闭
Inherit=false //不能继承
ProtectFromClose//开启句柄保护
这个函数其实的意思就是当前的进程的句柄复制到当前的进程、然后最后一个属性对它进程关闭
原理:就是查询系统的所有对象
方法:以类型的方式查找调试结构体标识残留
获取所有的长度、可以用它进行反调试操作
函数定义
参数一:可以指定当前的句柄 可以指定NtCurrentProcess
参数二:对象信息类结构体表示可以指定 ObjectTypesInformation
参数三:变量接收指针
参数四:变量长度
变量五:变量接收指针
因为这个结构体的TypeInformation成员是一个软成员、所以需要用内存搜索的方法搜出这个DebugObejct字符串、然后用因为这个字符串在BJECT_TYPE_INFORMATION 的最先所以需要减4 然后得到BJECT_TYPE_INFORMATION 最后一个成员 然后即可反推出这个结构指针
可以使用CONTAINING_RECORD(缓存区、结构体、结构体成员名字) 推出这个结构体的首指针
如果当前有调试器调试这个程序、则
OBJECT_TYPE_INFORMATION 成员
ULONG TotalNumberOfObjects;
ULONG TotalNumberOfHandles;
不为0、否则等于0、可以判断这两个结构体判断当前的进程是否被调试、
注意:如果别的调试器的句柄打开没有关掉、或者是开了调试器有残留信息残留在操作系统、即时调试器没有附加和调试、这两个成员也会出现调试状态、解决办法是重启计算机!(不推荐使用这个反调试)
以下是代码
检测父进程:
ProcessBasicInformation是用来检测当前的父进程、如果当前的父进程句柄不等于桌面的句柄即为当前为调试状态
NtQueryInformationProcess函数的第二个参数主要用来指定一个类型、
这里用ProcessBasicInformation指定父进程类型
父进程结构体:
其中InheritedFromUniqueProcessId这个就是父进程的ID、如果父进程不等于桌面上打开、则说明你被其他进程所打开!即为调试状态、否则不为调试状态
这个太简单了、我这里就不多说了、就是获取全部的进程信息挨个遍历、寻找相关的进程信息或者是进程标题
取启动时间 返回是从系统启动到现在所有毫秒数
//从破解者角度观察、因为破解者跟进一个循环肯定得需要时间进行理解、
//当他跳出这个循环再取一个时间、那么这个时间减去上一次的时间如果大于特定的毫秒数则为调试
如果在中间进行单步调试、则时间差一定大于1000毫秒、即为调试
在函数头部加上这个禁止键盘输入的函数、然后在函数尾部恢复这个键盘输入、函数执行非常快、所以感受不到键盘有时候被禁止输入!所以这个方法有利于反单步调试(单步单步跟着键盘就失灵了笑死我
)、这个可以与时间差反调试进行联合使用!
可以获取当前线程的上下文、当前判断当前的调试寄存器DR0\DIR1\DR2\DIR3是否有值、如果这几个调试寄存器有值说明当前这个进程正在被调试
异常方式检测硬件断点
反抗硬件断点调试
HOOK之后首先把DR寄存器全部清0然后再调用VEH、所以别人用的是你的VEH
HOOK这个函数然后还原之前的硬件断点
对抗CRC:下内存硬件断点、然后一步一步跟踪、Nop掉CRC即可
自内存CRC需要很早时期先计算一遍内存CRC校验和!然后后续在根据这个CRC校验值再来判断
反附加之前要先获取一次代码段的页面CRC校验和算出CRC、比如某些壳在链接的时候就已经算好了、这是最早的计算方式、越早越好
以下是代码、获取页面CRC
循环校验CRC
反附加:
因为调试器在附加的时候会走DbgBreakPoint函数、所以HOOK这个函数就可以改变调试器运转流程、从而达到反附加!
对抗反调试方法:几乎是HOOK
mov eax,dword ptr fs:[
0x30
]
mov eax,dword ptr fs:[
0x30
]
typedef struct _PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN ImageUsesLargePages :
1
;
BOOLEAN IsProtectedProcess :
1
;
BOOLEAN IsImageDynamicallyRelocated :
1
;
BOOLEAN SkipPatchingUser32Forwarders :
1
;
BOOLEAN IsPackagedProcess :
1
;
BOOLEAN IsAppContainer :
1
;
BOOLEAN IsProtectedProcessLight :
1
;
BOOLEAN IsLongPathAwareProcess :
1
;
} s1;
} u1;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
PVOID AtlThunkSListPtr;
PVOID IFEOKey;
union
{
ULONG CrossProcessFlags;
struct
{
ULONG ProcessInJob :
1
;
ULONG ProcessInitializing :
1
;
ULONG ProcessUsingVEH :
1
;
ULONG ProcessUsingVCH :
1
;
ULONG ProcessUsingFTH :
1
;
ULONG ProcessPreviouslyThrottled :
1
;
ULONG ProcessCurrentlyThrottled :
1
;
ULONG ReservedBits0 :
25
;
} s2;
} u2;
union
{
PVOID KernelCallbackTable;
PVOID UserSharedInfoPtr;
} u3;
ULONG SystemReserved[
1
];
ULONG AtlThunkSListPtr32;
PVOID ApiSetMap;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[
2
];
PVOID ReadOnlySharedMemoryBase;
PVOID HotpatchInformation;
PVOID
*
ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
LARGE_INTEGER CriticalSectionTimeout;
SIZE_T HeapSegmentReserve;
SIZE_T HeapSegmentCommit;
SIZE_T HeapDeCommitTotalFreeThreshold;
SIZE_T HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID
*
ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
ULONG GdiDCAttributeList;
PRTL_CRITICAL_SECTION LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
USHORT OSBuildNumber;
USHORT OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
ULONG_PTR ActiveProcessAffinityMask;
GDI_HANDLE_BUFFER GdiHandleBuffer;
PVOID PostProcessInitRoutine;
PVOID TlsExpansionBitmap;
ULONG TlsExpansionBitmapBits[
32
];
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
PVOID pShimData;
PVOID AppCompatInfo;
UNICODE_STRING CSDVersion;
PVOID ActivationContextData;
PVOID ProcessAssemblyStorageMap;
PVOID SystemDefaultActivationContextData;
PVOID SystemAssemblyStorageMap;
SIZE_T MinimumStackCommit;
PVOID
*
FlsCallback;
LIST_ENTRY FlsListHead;
PVOID FlsBitmap;
ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE
/
(sizeof(ULONG)
*
8
)];
ULONG FlsHighIndex;
PVOID WerRegistrationData;
PVOID WerShipAssertPtr;
PVOID pContextData;
PVOID pImageHeaderHash;
union
{
ULONG TracingFlags;
struct
{
ULONG HeapTracingEnabled :
1
;
ULONG CritSecTracingEnabled :
1
;
ULONG LibLoaderTracingEnabled :
1
;
ULONG SpareTracingBits :
29
;
} s3;
} u4;
ULONGLONG CsrServerReadOnlySharedMemoryBase;
PVOID TppWorkerpListLock;
LIST_ENTRY TppWorkerpList;
PVOID WaitOnAddressHashTable[
128
];
} PEB,
*
PPEB;
typedef struct _PEB
{
BOOLEAN InheritedAddressSpace;
BOOLEAN ReadImageFileExecOptions;
BOOLEAN BeingDebugged;
union
{
BOOLEAN BitField;
struct
{
BOOLEAN ImageUsesLargePages :
1
;
BOOLEAN IsProtectedProcess :
1
;
BOOLEAN IsImageDynamicallyRelocated :
1
;
BOOLEAN SkipPatchingUser32Forwarders :
1
;
BOOLEAN IsPackagedProcess :
1
;
BOOLEAN IsAppContainer :
1
;
BOOLEAN IsProtectedProcessLight :
1
;
BOOLEAN IsLongPathAwareProcess :
1
;
} s1;
} u1;
HANDLE Mutant;
PVOID ImageBaseAddress;
PPEB_LDR_DATA Ldr;
PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
PVOID SubSystemData;
PVOID ProcessHeap;
PRTL_CRITICAL_SECTION FastPebLock;
PVOID AtlThunkSListPtr;
PVOID IFEOKey;
union
{
ULONG CrossProcessFlags;
struct
{
ULONG ProcessInJob :
1
;
ULONG ProcessInitializing :
1
;
ULONG ProcessUsingVEH :
1
;
ULONG ProcessUsingVCH :
1
;
ULONG ProcessUsingFTH :
1
;
ULONG ProcessPreviouslyThrottled :
1
;
ULONG ProcessCurrentlyThrottled :
1
;
ULONG ReservedBits0 :
25
;
} s2;
} u2;
union
{
PVOID KernelCallbackTable;
PVOID UserSharedInfoPtr;
} u3;
ULONG SystemReserved[
1
];
ULONG AtlThunkSListPtr32;
PVOID ApiSetMap;
ULONG TlsExpansionCounter;
PVOID TlsBitmap;
ULONG TlsBitmapBits[
2
];
PVOID ReadOnlySharedMemoryBase;
PVOID HotpatchInformation;
PVOID
*
ReadOnlyStaticServerData;
PVOID AnsiCodePageData;
PVOID OemCodePageData;
PVOID UnicodeCaseTableData;
ULONG NumberOfProcessors;
ULONG NtGlobalFlag;
LARGE_INTEGER CriticalSectionTimeout;
SIZE_T HeapSegmentReserve;
SIZE_T HeapSegmentCommit;
SIZE_T HeapDeCommitTotalFreeThreshold;
SIZE_T HeapDeCommitFreeBlockThreshold;
ULONG NumberOfHeaps;
ULONG MaximumNumberOfHeaps;
PVOID
*
ProcessHeaps;
PVOID GdiSharedHandleTable;
PVOID ProcessStarterHelper;
ULONG GdiDCAttributeList;
PRTL_CRITICAL_SECTION LoaderLock;
ULONG OSMajorVersion;
ULONG OSMinorVersion;
USHORT OSBuildNumber;
USHORT OSCSDVersion;
ULONG OSPlatformId;
ULONG ImageSubsystem;
ULONG ImageSubsystemMajorVersion;
ULONG ImageSubsystemMinorVersion;
ULONG_PTR ActiveProcessAffinityMask;
GDI_HANDLE_BUFFER GdiHandleBuffer;
PVOID PostProcessInitRoutine;
PVOID TlsExpansionBitmap;
ULONG TlsExpansionBitmapBits[
32
];
ULONG SessionId;
ULARGE_INTEGER AppCompatFlags;
ULARGE_INTEGER AppCompatFlagsUser;
PVOID pShimData;
PVOID AppCompatInfo;
UNICODE_STRING CSDVersion;
PVOID ActivationContextData;
PVOID ProcessAssemblyStorageMap;
PVOID SystemDefaultActivationContextData;
PVOID SystemAssemblyStorageMap;
SIZE_T MinimumStackCommit;
PVOID
*
FlsCallback;
LIST_ENTRY FlsListHead;
PVOID FlsBitmap;
ULONG FlsBitmapBits[FLS_MAXIMUM_AVAILABLE
/
(sizeof(ULONG)
*
8
)];
ULONG FlsHighIndex;
PVOID WerRegistrationData;
PVOID WerShipAssertPtr;
PVOID pContextData;
PVOID pImageHeaderHash;
union
{
ULONG TracingFlags;
struct
{
ULONG HeapTracingEnabled :
1
;
ULONG CritSecTracingEnabled :
1
;
ULONG LibLoaderTracingEnabled :
1
;
ULONG SpareTracingBits :
29
;
} s3;
} u4;
ULONGLONG CsrServerReadOnlySharedMemoryBase;
PVOID TppWorkerpListLock;
LIST_ENTRY TppWorkerpList;
PVOID WaitOnAddressHashTable[
128
];
} PEB,
*
PPEB;
/
/
WinApi IsDebuggerPresent 如果返回值为
True
则为调试状态 如果为
False
则为未调试状态
bool
bRet
=
false;
bRet
=
IsDebuggerPresent();
/
/
WinApi IsDebuggerPresent 如果返回值为
True
则为调试状态 如果为
False
则为未调试状态
bool
bRet
=
false;
bRet
=
IsDebuggerPresent();
WINBASEAPI
BOOL
WINAPI
CheckRemoteDebuggerPresent(
_In_ HANDLE hProcess,
_Out_ PBOOL pbDebuggerPresent
);
WINBASEAPI
BOOL
WINAPI
CheckRemoteDebuggerPresent(
_In_ HANDLE hProcess,
_Out_ PBOOL pbDebuggerPresent
);
BOOL
bRet
=
FALSE;
/
/
参数一:HANDLE hProcess 句柄
/
/
参数二:PBOOL pbDebuggerPresent 指向是否被调试的指针、如果返回值为true则为调试状态、如果为false则为未调试状态
CheckRemoteDebuggerPresent(NtCurrentProcess,
&bRet
);
OUTPRINTF(
"CheckRemoteDebuggerPresent(检查远程调试器)"
, bRet);
BOOL
bRet
=
FALSE;
/
/
参数一:HANDLE hProcess 句柄
/
/
参数二:PBOOL pbDebuggerPresent 指向是否被调试的指针、如果返回值为true则为调试状态、如果为false则为未调试状态
CheckRemoteDebuggerPresent(NtCurrentProcess,
&bRet
);
OUTPRINTF(
"CheckRemoteDebuggerPresent(检查远程调试器)"
, bRet);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQuerySystemInformation(
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
_Out_opt_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQuerySystemInformation(
_In_ SYSTEM_INFORMATION_CLASS SystemInformationClass,
_Out_opt_ PVOID SystemInformation,
_In_ ULONG SystemInformationLength,
_Out_opt_ PULONG ReturnLength
);
NTSTATUS ntStatus
=
0
;
SYSTEM_KERNEL_DEBUGGER_INFORMATION pSystemKernelDebuggerInformation;
ULONG uRetLength
=
0
;
ntStatus
=
NtQuerySystemInformation(SystemKernelDebuggerInformation,&pSystemKernelDebuggerInformation,sizeof(pSystemKernelDebuggerInformation),&uRetLength);
/
/
参数一:SystemKernelDebuggerInformation
/
/
参数二:指向SYSTEM_KERNEL_DEBUGGER_INFORMATION结构体的指针
/
/
参数三:SYSTEM_KERNEL_DEBUGGER_INFORMATION结构体的长度
/
/
参数四:返回一个长度
/
/
返回值:应用层、如果Nt函数成功一般都是返回
0
、和驱动层是反过来的、内核层成功返回
1
、所有可以用NT_SUCCESS这个宏来判断Nt函数是否被调用成功
if
(NT_SUCCESS(ntStatus))
{
OUTPRINTF(
"NtQuerySystemInformation(检测内核调试器)"
, !pSystemKernelDebuggerInformation.KernelDebuggerNotPresent);
/
/
KernelDebuggerEnabled:是否激活、一般为
0
/
/
KernelDebuggerNotPresent : 没有内核调试器附加则为
1
、所以这里需要取反操作
}
NTSTATUS ntStatus
=
0
;
SYSTEM_KERNEL_DEBUGGER_INFORMATION pSystemKernelDebuggerInformation;
ULONG uRetLength
=
0
;
ntStatus
=
NtQuerySystemInformation(SystemKernelDebuggerInformation,&pSystemKernelDebuggerInformation,sizeof(pSystemKernelDebuggerInformation),&uRetLength);
/
/
参数一:SystemKernelDebuggerInformation
/
/
参数二:指向SYSTEM_KERNEL_DEBUGGER_INFORMATION结构体的指针
/
/
参数三:SYSTEM_KERNEL_DEBUGGER_INFORMATION结构体的长度
/
/
参数四:返回一个长度
/
/
返回值:应用层、如果Nt函数成功一般都是返回
0
、和驱动层是反过来的、内核层成功返回
1
、所有可以用NT_SUCCESS这个宏来判断Nt函数是否被调用成功
if
(NT_SUCCESS(ntStatus))
{
OUTPRINTF(
"NtQuerySystemInformation(检测内核调试器)"
, !pSystemKernelDebuggerInformation.KernelDebuggerNotPresent);
/
/
KernelDebuggerEnabled:是否激活、一般为
0
/
/
KernelDebuggerNotPresent : 没有内核调试器附加则为
1
、所以这里需要取反操作
}
BOOL
bRet
=
FALSE;
__try
{
NtClose(ULongToHandle(
0x1234
));
}
__except (EXCEPTION_EXECUTE_HANDLER)
/
/
接受句柄异常
{
bRet
=
TRUE;
}
OUTPRINTF(
"NtClose(句柄异常方式)"
, bRet);
BOOL
bRet
=
FALSE;
__try
{
NtClose(ULongToHandle(
0x1234
));
}
__except (EXCEPTION_EXECUTE_HANDLER)
/
/
接受句柄异常
{
bRet
=
TRUE;
}
OUTPRINTF(
"NtClose(句柄异常方式)"
, bRet);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
NTSYSCALLAPI
NTSTATUS
NTAPI
NtQueryInformationProcess(
_In_ HANDLE ProcessHandle,
_In_ PROCESSINFOCLASS ProcessInformationClass,
_Out_ PVOID ProcessInformation,
_In_ ULONG ProcessInformationLength,
_Out_opt_ PULONG ReturnLength
);
PVOID pInfo;
ULONG uRetLength
=
0
;
NTSTATUS ntStatus
=
0
;
ntStatus
=
NtQueryInformationProcess(NtCurrentProcess, ProcessDebugPort, &pInfo, sizeof(pInfo), &uRetLength);
if
(NT_SUCCESS(ntStatus))
{
/
/
如果ProcessInformation !
=
NULL 、说明ProcessInformation不为
0
的情况下的情况下表示当前正在被调试
OUTPRINTF(
"NtQueryInformationProcess::ProcessDebugPort(常见壳反调试)"
, pInfo !
=
NULL);
}
PVOID pInfo;
ULONG uRetLength
=
0
;
NTSTATUS ntStatus
=
0
;
ntStatus
=
NtQueryInformationProcess(NtCurrentProcess, ProcessDebugPort, &pInfo, sizeof(pInfo), &uRetLength);
if
(NT_SUCCESS(ntStatus))
{
/
/
如果ProcessInformation !
=
NULL 、说明ProcessInformation不为
0
的情况下的情况下表示当前正在被调试
OUTPRINTF(
"NtQueryInformationProcess::ProcessDebugPort(常见壳反调试)"
, pInfo !
=
NULL);
}
ntStatus
=
NtQueryInformationProcess(NtCurrentProcess, ProcessDebugObjectHandle, &pInfo, sizeof(pInfo), &uRetLength);
if
(ntStatus!
=
0xC0000353
)
{
/
/
如果是参数二等于ProcessDebugObjectHandle则Nt函数返回值是
0xC0000353
则当前没有被调试、否则即为调试状态
OUTPRINTF(
"NtQueryInformationProcess::ProcessDebugObjectHandle(常见壳反调试)"
,true);
}
ntStatus
=
NtQueryInformationProcess(NtCurrentProcess, ProcessDebugObjectHandle, &pInfo, sizeof(pInfo), &uRetLength);
if
(ntStatus!
=
0xC0000353
)
{
[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)