刺激战场
六合彩
贵宾厅
  • 1816阅读
  • 1回复

调试器检测技术 - 2、PEB.NtGlobalFlag , Heap.HeapFlags, Heap.ForceFlags [复制链接]

上一主题 下一主题
离线天道酬勤
 

只看楼主 倒序阅读 使用道具 楼主  发表于: 2016-02-05
— 本帖被 天道酬勤 从 驱动保护 移动到本区(2016-05-19) —


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”标志位处跳,执行退出代码。
}
}

离线v2680267313

只看该作者 沙发  发表于: 2016-04-30
用户被禁言,该主题自动屏蔽!
快速回复
限100 字节
如果您在写长篇帖子又不马上发表,建议存为草稿
 
上一个 下一个