静态反调试技术总结

静态反调试技术

静态反调试技术只需要在程序运行之前进行一次破解即可解除全部限制,且不需要二次操作。而且静态反调试技术对于操作系统的依赖性非常大,相同的反调试技术在不同的操作系统表现可能不同。这里举例表述几个较为常用的反调试技术。

利用PEB结构体进行反调试

mov eax,dword ptr fs:[0x30]   // 直接获取PEB结构体的地址

mov eax,dword ptr fs:[0x18]   //先获取TEB结构体的地址
mov eax,dword ptr fs:[eax+30]  //通过TEB结构体获取指向PEB结构体的指针

PEB结构体的0x2偏移处所含立即数是PEB.BeingDebugger成员,若进程未处于被调试状态,则该成员值为0,否则为1。

mov eax,fs:[0x30]
inc eax
inc eax           //两步eax+1到达了PEB结构体的0x2偏移处
mov eax,[eax]
and eax,0x000000ff
test eax,eax
jne rt_label
jmp rt_label

破解方法就是追踪PEB.BeingDebugged 的值然后进行修改。

利用进程堆(HEAP)进行反调试

PEB.ProcessHeap成员是指向HEAD结构体的指针,其中比较重要的是FLAGS成员和Force FLAG成员。

mov   eax,  dword ptr  fs:[0x18]            //TEB的起始地址
mov   eax , dword  ptr  ds:[eax+30]      //PEB的地址
mov   eax , dword  ptr  ds:[eax+18]     /PEB.Processheap的地址

进程正常运行时,heap.flags的值为0x2,heap.Forceflags的值为0x0,当被调试时这些值都会被改变。

利用PEB_NtGlobalFlags进行反调试

PEB_NtGlobalFlags 位于PEB环境中偏移为0x68的位置,当进程被调试的时候,该成员的值为0x70

mov eax, fs:[30h]
mov eax, [eax+68h]
and eax, 0x70
test eax, eax
jne rt_label
jmp rf_label

利用NtqueryInformationProcess() API进行反调试

该API当中含有几个重要成员,其中一个为ProcessDebugPort(0x7),进程被调试的时候,系统会为其分配一个调试端口,以便于调试器相连接。

当程序处于调试状态的时候,Port值会变成0xFFFFFFFF ,处于非调试状态的时候会变成0。

使用CheckRemoteDebuggerPresent() 可以查看是否调用了NtquerylnformationProcess() API

利用ProcessDebugFlags进行反调试

检测debug flag调试标志的值也可以判断是否处于被调试状态,调用函数后通过该函数的第三个参数即可获得调试标志的值,若为0 则处于被调试状态,若为1则处于非调试状态。

利用Find_Debugger_Window()进行反调试

该API所起的作用是寻找目标调试器窗口,如果发现,则进行反调试操作。

//ollyice
    hWnd=CWnd::FindWindow(_T("1212121"),NULL);
    if (hWnd!=NULL)
    return true;
  //ollydbg v1.1
    hWnd=CWnd::FindWindow(_T("icu_dbg"),NULL);
    if (hWnd!=NULL)
    return true;
  //ollyice pe--diy
    hWnd=CWnd::FindWindow(_T("pe--diy"),NULL);
    if (hWnd!=NULL)
    return true;
  //ollydbg ?-°?
    hWnd=CWnd::FindWindow(_T("ollydbg"),NULL);
    if (hWnd!=NULL)
    return true;
  //ollydbg ?-°?
    hWnd=CWnd::FindWindow(_T("odbydyk"),NULL);
    if (hWnd!=NULL)
    return true;
  //windbg
    hWnd=CWnd::FindWindow(_T("WinDbgFrameClass"),NULL);
    if (hWnd!=NULL)
    return true;
  //dede3.50
    hWnd=CWnd::FindWindow(_T("TDeDeMainForm"),NULL);
    if (hWnd!=NULL)
    return true;
  //IDA5.20
    hWnd=CWnd::FindWindow(_T("TIdaWindow"),NULL);
    if (hWnd!=NULL)
    return true;
  //others
    hWnd=CWnd::FindWindow(_T("TESTDBG"),NULL);
    if (hWnd!=NULL)
    return true;
    hWnd=CWnd::FindWindow(_T("kk1"),NULL);
    if (hWnd!=NULL)
    return true;
    hWnd=CWnd::FindWindow(_T("Eew75"),NULL);
    if (hWnd!=NULL)
    return true;
    hWnd=CWnd::FindWindow(_T("Shadow"),NULL);
    if (hWnd!=NULL)    return true;  //PEiD v0.94    hWnd=CWnd::FindWindow(NULL,"PEiD v0.94");    if (hWnd!=NULL)    return true;  //RegMON    hWnd=CWnd::FindWindow(NULL,"Registry Monitor - Sysinternals: www.sysinternals.com");    if (hWnd!=NULL)    return true;  //File Monitor    hWnd=CWnd::FindWindow(NULL,"File Monitor - Sysinternals: www.sysinternals.com");    if (hWnd!=NULL)    return true;  //Import Rec v1.6    hWnd=CWnd::FindWindow(NULL,"Import REConstructor v1.6 FINAL (C) 2001-2003 MackT/uCF");    if (hWnd!=NULL)    return true;  return false;

利用Find_Device_Driver()进行反调试

调试工具通常会使用内核驱动,因此如果尝试是否可以打开一些调试器所用到的设备,就可以判断是否存在调试器。

\\.\SICE  (SoftICE)
\\.\SIWVID(SoftICE)    
\\.\NTICE  (SoftICE)    
\\.\REGVXG(RegMON)
\\.\REGVXD(RegMON)
\\.\REGSYS(RegMON)
\\.\REGSYS(RegMON)
\\.\FILEVXG(FileMON)
\\.\FILEM(FileMON)
\\.\TRW(TRW2000)

利用Exception_Int3()进行反调试

INT3会产生异常中断,当INT3被执行到的时候,如果程序未被调试,将会异常处理器程序继续执行,如果处于被调试状态,则会被调试器误认为是自己的一个断点,从而不进入异常处理程序。

__asm 
  {
    push   offset exception_handler; set exception handler
    push  dword ptr fs:[0h]
    mov    dword ptr fs:[0h],esp  
    xor   eax,eax;reset EAX invoke int3
    int    3h
    pop    dword ptr fs:[0h];restore exception handler
    add   esp,4

    test   eax,eax; check the flag 
    je    rt_label
    jmp    rf_label

exception_handler:
    mov   eax,dword ptr [esp+0xc];EAX = ContextRecord
    mov    dword ptr [eax+0xb0],0xffffffff;set flag (ContextRecord.EAX)
    inc   dword ptr [eax+0xb8];set ContextRecord.EIP
    xor   eax,eax
    retn

rt_label:
    xor eax,eax
    inc eax
    mov esp,ebp
    pop ebp
    retn
rf_label:
    xor eax,eax
    mov esp,ebp
    pop ebp
    retn
  }

利用OutpuDebugString()进行反调试技术

在调试器不存在和存在两种情况下,该API 的结果是不同的,如果有调试器存在,GetLastError()的返回值为零。

OutputDebugString("");
  tmpD=GetLastError();
  if(tmpD==0)
    return true;
  return false;

 利用VMWare_VMX进行反调试技术

VMware提供一种主机与客户机之间进行通信的方式,这里可以被用作一种VMWARE的反调试,Vmware将会处理IN(端口为0x5658/'VX')指令,它会返回一个magic数值“VMXh”到ebx寄存器当中。

当在保护模式操作系统下的ring3运行时,in指令的执行将会产生异常,除非我们修改了I/O的优先级等级,然而,如果在Vmware下运行,则不会产生任何异常,正常运行,且EBX寄存器但当中会含有'VMXh' magic数值,ECX寄存器当中含有VMWARE的产品ID.

这种技巧在病毒中比较常见,称为"in指令反调试"。

bool IsInsideVMWare_()
{
  bool r;
  _asm
  {
    push   edx
    push   ecx
    push   ebx

    mov    eax, 'VMXh'
    mov    ebx, 0 // any value but MAGIC VALUE
    mov    ecx, 10 // get VMWare version
    mov    edx, 'VX' // port number
    in     eax, dx // read port
                   // on return EAX returns the VERSION
    cmp    ebx, 'VMXh' // is it a reply from VMWare?
    setz   [r] // set return value

    pop    ebx
    pop    ecx
    pop    edx
  }
  return r;
}

bool FV_VMWare_VMX()
{
  __try
  {
    return IsInsideVMWare_();
  }
  __except(1) // 1 = EXCEPTION_EXECUTE_HANDLER
  {
    return false;
  }
}

 

posted @ 2019-09-15 19:14  ReVe1Se  阅读(560)  评论(0编辑  收藏  举报