调试器检测技术 - 2、PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags

2、PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags

PEB.NtGlobalFlag PEB另一个成员被称作NtGlobalFlag(偏移0x68),壳也通过它来检测程序是否用调试器加载。通常程序没有被调试时,NtGlobalFlag成员值为0,如果进程被调试这个成员通常值为0x70(代表下述标志被设置):

FLG_HEAP_ENABLE_TAIL_CHECK(0X10)

FLG_HEAP_ENABLE_FREE_CHECK(0X20)

FLG_HEAP_VALIDATE_PARAMETERS(0X40)

这些标志是在ntdll!LdrpInitializeExecutionOptions()里设置的。请注意PEB.NtGlobalFlag的默认值可以通过gflags.exe工具或者在注册表以下位置创建条目来修改:

HKLM\Software\Microsoft\Windows Nt\CurrentVersion\Image File Execution Options

Heap Flags 由于NtGlobalFlag标志的设置,堆也会打开几个标志,这个变化可以在ntdll!RtlCreateHeap()里观测到。通常情况下为进程创建的第一个堆会将其Flags和ForceFlags4分别设为0x02(HEAP_GROWABLE)和0 。然而当进程被调试时,这两个标志通常被设为0x50000062(取决于NtGlobalFlag)和0x40000060(等于Flags AND 0x6001007D)。默认情况下当一个被调试的进程创建堆时下列附加的堆标志将被设置:

HEAP_TAIL_CHECKING_ENABLED(0X20)

HEAP_FREE_CHECKING_ENABLED(0X40)

示例

下面的示例代码检查PEB.NtGlobalFlag是否等于0,为进程创建的第一个堆是否设置了附加标志(PEB.ProcessHeap):

;ebx = PEB

Mov                 ebx,[fs:0x30]

;Check if PEB.NtGlobalFlag != 0

Cmp               dword [ebx+0x68],0

jne                   .debugger_found

;eax = PEB.ProcessHeap

Mov                 eax,[ebx+0x18]

;Check PEB.ProcessHeap.Flags

Cmp               dword [eax+0x0c],2

jne                   .debugger_found

;Check PEB.ProcessHeap.ForceFlags

Cmp               dword [eax+0x10],0

jne                   .debugger_found

对策

可以将 PEB.NtGlobalFlag和PEB.HeapProcess标志补丁为进程未被调试时的相应值。下面是一个补丁上述标志的ollyscript示例:

Var                   peb

var                   patch_addr

var                   process_heap

//retrieve PEB via a hardcoded TEB address( first thread: 0x7ffde000)

Mov                 peb,[7ffde000+30]

//patch PEB.NtGlobalFlag

Lea                  patch_addr,[peb+68]

mov                 [patch_addr],0

//patch PEB.ProcessHeap.Flags/ForceFlags

Mov                 process_heap,[peb+18]

lea                   patch_addr,[process_heap+0c]

mov                 [patch_addr],2

lea                   patch_addr,[process_heap+10]

mov                 [patch_addr],0

同样地Olly Advanced插件有设置PEB.NtGlobalFlag和PEB.ProcessHeap的选项。

-------------------------------------------------------------------------
以下由Coderui修改整理,在VC 6.0下调试通过。
编写日期:2008年05月31日(更新)
联系邮箱:
作者博客:http://hi.baidu.com/coderui

void PEB_NtGlobalFlag()
{
_asm
{
   jmp   Coderui;      //先跳转到“Coderui”处去执行后边的判断代码。
Coderui_exit:         //标志位。跳到这里后,然后执行退出代码。
   retn;         //用这招当退出,还会异常,够狠(其它地方也可以这么做)。
Coderui:          //标志位。跳到这里后,可以继续执行后边的代码。
   ;//ebx = PEB
   mov   ebx,fs:[0x30];
  
   ;//Check if PEB.NtGlobalFlag != 0
   cmp   dword ptr [ebx+0x68],0;
   jnz   coderui_exit;     //发现被调试,向“Coderui_exit”标志位处跳,执行退出代码。

   ;//eax = PEB.ProcessHeap
   mov   eax,[ebx+0x18];

   ;//Check PEB.ProcessHeap.Flags
   cmp   dword ptr [eax+0x0c],2;
   jnz   coderui_exit;     //发现被调试,向“Coderui_exit”标志位处跳,执行退出代码。

   ;//Check PEB.ProcessHeap.ForceFlags
   cmp   dword ptr [eax+0x10],0;
   jnz   coderui_exit;     //发现被调试,向“Coderui_exit”标志位处跳,执行退出代码。
}
}

你可能感兴趣的:(windows,调试)