首页
社区
课程
招聘
[原创][翻译]反调试:调试标志寄存器
发表于: 2021-6-8 17:17 10420

[原创][翻译]反调试:调试标志寄存器

2021-6-8 17:17
10420

备注
原文地址:https://anti-debug.checkpoint.com/techniques/debug-flags.html
原文标题:Anti-Debug: Debug Flags
更新日期:2021年6月8日
此文后期:根据自身所学进行内容扩充
因自身技术有限,只能尽自身所能翻译国外技术文章,供大家学习,若有不当或可完善的地方,希望可以指出,用于共同完善这篇文章。

目录

调试标志寄存器

1. 使用Win32 API

1.1. IsDebuggerPresent()

1.2. CheckRemoteDebuggerPresent()

1.3. NtQueryInformationProcess()

1.3.1. ProcessDebugPort进程调试端口

1.3.2. ProcessDebugFlags进程调试标志寄存器

1.3.3. ProcessDebugObjectHandle进程调试对象句柄

1.4. RtlQueryProcessHeapInformation()

1.5. RtlQueryProcessDebugInformation()

1.6. NtQuerySystemInformation()

反制措施

2. 手工检查

2.1. PEB!BeingDebugged标志寄存器

2.2. NtGlobalFlag

2.3. 堆标志寄存器

2.4. 堆保护

反制措施

调试标志寄存器
系统表中的特殊标志寄存器,即停留在进程内存中的、由操作系统设置的标志寄存器,可以用来指示进程正在被调试。这些标志寄存器的状态可以通过使用特定的API函数或检查内存中的系统表来验证。
这些技术是恶意软件最常使用的。
1. 使用Win32 API
以下技术使用现有的API函数(WinAPI或NativeAPI),这些函数检查进程内存中的系统结构,以寻找表明进程现在正在被调试的特定标志寄存器。

1.1. IsDebuggerPresent()
函数kernel32!IsDebuggerPresent()确定当前进程是否被用户模式的调试器如OllyDbg或x64dbg调试。一般来说,该函数只检查进程环境块(PEB)的 BeingDebugged 标志寄存器。
如果正在调试进程,可以使用以下代码终止进程:
汇编代码:


C/C++ 代码:


1.2. CheckRemoteDebuggerPresent()
函数kernel32!CheckRemoteDebuggerPresent()检查一个调试器(在同一台机器的不同进程中)是否连接到当前进程。
C/C++ 代码:


x86 汇编:


x86-64 汇编:


1.3. NtQueryInformationProcess()
函数ntdll!NtQueryInformationProcess()可以从一个进程中检索不同种类的信息。它接受一个ProcessInformationClass参数,该参数指定了你想得到的信息,并定义了ProcessInformation参数的输出类型。

1.3.1. ProcessDebugPort进程调试端口
可以使用ntdll!NtQueryInformationProcess()来检索进程的调试器端口号。有一个记录在案的类ProcessDebugPort,如果进程正在被调试,它会检索到一个等于0xFFFFFFFF(十进制-1)的DWORD值。
C/C++ 代码:



x86 汇编:



x86-64 汇编:




1.3.2. ProcessDebugFlags进程调试标志寄存器
一个叫做EPROCESS的内核结构代表一个进程对象,它包含NoDebugInherit字段。这个字段的反值可以通过一个无文件记录的类ProcessDebugFlags(0x1f)来检索。因此,如果返回值为0,则说明有调试器存在。
C/C++ 代码:



x86 汇编:



x86-64 汇编:



1.3.3. ProcessDebugObjectHandle进程调试对象句柄
当调试开始时,一个叫做 "debug object "的内核对象被创建。可以通过使用无文献记载的ProcessDebugObjectHandle(0x1e)类来查询这个句柄的值。
C/C++ 代码:



x86 汇编:



x86-64 汇编:




1.4. RtlQueryProcessHeapInformation()
ntdll!RtlQueryProcessHeapInformation()函数可以用来从当前进程的进程内存中读取堆标志寄存器。
C/C++ 代码:




1.5. RtlQueryProcessDebugInformation()
ntdll!RtlQueryProcessDebugInformation()函数可用于从被请求进程的进程内存中读取某些字段,包括堆标志寄存器。
C/C++ 代码:


1.6. NtQuerySystemInformation()
ntdll!NtQuerySystemInformation()函数接受一个参数,即要查询的信息类别。大多数类都没有被记录下来。这包括SystemKernelDebuggerInformation(0x23)类,它从Windows NT开始就存在了。SystemKernelDebuggerInformation类返回两个标志寄存器的值。al中的KdDebuggerEnabled,和ah中的KdDebuggerNotPresent。因此,如果内核调试器存在,ah中的返回值为零。
C/C++ 代码:



反制措施

对于IsDebuggerPresent()。将进程环境块(PEB)的BeingDebugged标志设置为0。 更多信息请参见BeingDebugged 标志寄存器反制措施。

对于CheckRemoteDebuggerPresent()和NtQueryInformationProcess():
由于CheckRemoteDebuggerPresent()调用NtQueryInformationProcess(),唯一的方法是拦截NtQueryInformationProcess()并在返回缓冲区设置以下值。

如果是ProcessDebugPort查询,则为0(或除-1外的任何值)。

如果是ProcessDebugFlags查询,则为非零值。

在ProcessDebugObjectHandle查询的情况下为0。

用RtlQueryProcessHeapInformation()、RtlQueryProcessDebugInformation()和NtQuerySystemInformation()函数反制这些检查的唯一方法是拦截它们并修改返回值:

RTL_PROCESS_HEAPS::HeapInformation::Heaps[0]:标志寄存器改为HEAP_GROWABLE,用于RtlQueryProcessHeapInformation()和RtlQueryProcessDebugInformation()。

SYSTEM_KERNEL_DEBUGGER_INFORMATION::DebuggerEnabled为0和系统_KERNEL_DEBUGGER_INFORMATION::DebuggerNotPresent为1。NtQuerySystemInformation()函数在查询SystemKernelDebuggerInformation的情况下。


2. 手工检查
以下方法用于验证系统结构中的调试标志。他们手工检查进程的内存,而不使用特殊的调试API函数。
2.1. PEB!正在调试标志寄存器
这个方法只是检查PEB的BeingDebugged标志寄存器[的另一种方法,而不需要调用IsDebuggerPresent()。
32位进程:



64位进程:


WOW64 进程:



C/C++ 代码:



2.2. NtGlobalFlag
进程环境块的NtGlobalFlag字段(32位Windows的0x68偏移,64位Windows的0xBC)默认为0。附加一个调试器并不改变NtGlobalFlag的值。但是,如果进程是由调试器创建的,则将设置以下标志寄存器:

FLG_HEAP_ENABLE_TAIL_CHECK (0x10)

FLG_HEAP_ENABLE_FREE_CHECK (0x20)

FLG_HEAP_VALIDATE_PARAMETERS (0x40)


调试器的存在可以通过检查这些标志寄存器的组合来检测。
32位进程:



64位进程:



WOW64 进程:


C/C++ 代码:




2.3. 堆标志寄存器
堆包含两个字段,它们会受到调试器存在的影响。具体如何影响,取决于Windows的版本。这些字段是标志寄存器(Flags)和强标志寄存器(ForceFlags)。

标志寄存器和强标志寄存器的值通常分别设置为HEAP_GROWABLE和0。
当调试器出现时,在Windows NT、Windows 2000和32位Windows XP上,标志寄存器字段被设置为这些标志寄存器的组合。

HEAP_GROWABLE (2)

HEAP_TAIL_CHECKING_ENABLED (0x20)

HEAP_FREE_CHECKING_ENABLED (0x40)

HEAP_SKIP_VALIDATION_CHECKS (0x10000000)

HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)


在64位的Windows XP和Windows Vista及更高版本中,如果有调试器存在,Flags字段会被设置为这些标志寄存器组合:

HEAP_GROWABLE (2)

HEAP_TAIL_CHECKING_ENABLED (0x20)

HEAP_FREE_CHECKING_ENABLED (0x40)

HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)


当调试器出现时,ForceFlags字段被设置为这些标志寄存器的组合:

HEAP_TAIL_CHECKING_ENABLED (0x20)

HEAP_FREE_CHECKING_ENABLED (0x40)

HEAP_VALIDATE_PARAMETERS_ENABLED (0x40000000)


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

最后于 2021-6-8 17:47 被梦幻的彼岸编辑 ,原因:
收藏
免费 10
支持
分享
最新回复 (2)
雪    币: 6076
活跃值: (5480)
能力值: ( LV5,RANK:65 )
在线值:
发帖
回帖
粉丝
2
感谢分享
2021-6-8 17:42
0
雪    币: 1795
活跃值: (3995)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
感谢分享
2021-6-17 11:05
0
游客
登录 | 注册 方可回帖
返回
//