SHARE
TWEET

The "ZwContinue" Function Anti-Attaching Trick

waliedassar Sep 10th, 2012 635 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. //http://waleedassar.blogspot.com - (@waleedassar)
  2. //This code shows how to hook the "ZwContinue" function in order to detect debuggers trying to attach.
  3. //Tested with Windows XP SP2/SP3 and Windows 7 SP1.
  4. #include "stdafx.h"
  5. #include "windows.h"
  6. #include "stdio.h"
  7.  
  8. unsigned long relativeOffset(unsigned long from,unsigned long to)
  9. {
  10.         unsigned long diff=0;
  11.         if(from>to)
  12.         {
  13.                  //  5-byte jump instruction
  14.          diff=((unsigned long)from+5)-(unsigned long)to;
  15.                  diff=-diff;
  16.         }
  17.         else
  18.         {
  19.           diff=(unsigned long)to-((unsigned long)from+5);
  20.         }
  21.         return diff;
  22. }
  23.  
  24. struct OSVERSIONINFOEx
  25. {
  26.   DWORD dwOSVersionInfoSize;
  27.   DWORD dwMajorVersion;
  28.   DWORD dwMinorVersion;
  29.   DWORD dwBuildNumber;
  30.   DWORD dwPlatformId;
  31.   TCHAR szCSDVersion[128];
  32.   WORD  wServicePackMajor;
  33.   WORD  wServicePackMinor;
  34.   WORD  wSuiteMask;
  35.   BYTE  wProductType;
  36.   BYTE  wReserved;
  37. };
  38.  
  39. unsigned long ver;   //0 if XP, 1 if win7, -1 otherwise.
  40. unsigned char* p;  //holds address of ZwContinue
  41. unsigned long addr_Dbg;   //holds address of DbgUiRemoteBreakin
  42. unsigned long addr_DbgPnt;   //holds address of DbgBreakPoint
  43. unsigned long addr_RtlUserThreadStart; ////holds address of RtlUserThreadStart
  44.  
  45. char* backup;    //here we backup the first 5 bytes of ZwContinue.
  46.  
  47. void HookFunc(char* pCOntext)
  48. {
  49.            unsigned long eip_=*(unsigned long*)(pCOntext+0xB8);   //StartAddress
  50.            unsigned long eax_=*(unsigned long*)(pCOntext+0xB0);   //Win32StartAddress
  51.            if(ver==0)  //xp
  52.            {
  53.                    //Since the attaching thread is created via RtlCreateUserThread, then eip should be DbgUiRemoteBreakin and eax should be zero
  54.                    if(eip_==addr_Dbg) ExitProcess(0);
  55.                    //Heuristics (Smart guy may use DbgBreakPoint instead of DbgUiRemoteBreakin
  56.                    if(eip_==addr_DbgPnt) ExitProcess(0);
  57.                    //Smarter guy may manipulate DebugActiveProcess and replace RtlCreateUserThread with CreateRemoteThread
  58.                    if(eax_==addr_Dbg || eax_==addr_DbgPnt) ExitProcess(0);
  59.            }
  60.            else if(ver==1)  //Win7
  61.            {
  62.                    //No matter whether RtlCreateUserThread or CreateRemoteThread is used, the eip is ntdll.RtlUserThreadStart and eax is thread entrypoint
  63.                    if(eip_==addr_RtlUserThreadStart)
  64.                    {
  65.                            if(eax_==addr_Dbg || eax_==addr_DbgPnt) ExitProcess(0);
  66.                    }
  67.            }
  68.  
  69.            //For this to work, plz don't optimize
  70.            __asm
  71.            {
  72.                    leave
  73.                    jmp dword ptr[backup]
  74.            }
  75. }
  76. int main(int argc, char* argv[])
  77. {
  78.         //---------------version info---------------------------------------
  79.         OSVERSIONINFOEx OSI={sizeof(OSI)};
  80.         GetVersionEx((OSVERSIONINFO*)&OSI);
  81.         if(OSI.dwMajorVersion==5 && OSI.dwMinorVersion==1) ver=0;
  82.         else if(OSI.dwMajorVersion==6 && OSI.dwMinorVersion==1) ver=1;
  83.         else ver=-1;
  84.         //------------------------------------------------------------------
  85.               addr_RtlUserThreadStart=(unsigned long)GetProcAddress(GetModuleHandle("ntdll.dll"),"RtlUserThreadStart");
  86.               addr_Dbg=(unsigned long)GetProcAddress(GetModuleHandle("ntdll.dll"),"DbgUiRemoteBreakin");
  87.           addr_DbgPnt=(unsigned long)GetProcAddress(GetModuleHandle("ntdll.dll"),"DbgBreakPoint");
  88.                   p=(unsigned char*)GetProcAddress(GetModuleHandle("ntdll.dll"),"ZwContinue");
  89.           unsigned long old;
  90.  
  91.                   backup=(char*)VirtualAlloc(0,0x1000,MEM_COMMIT,PAGE_EXECUTE_READWRITE);
  92.                   memcpy(backup,p,0x5);
  93.                   backup[0x5]=0x68;  //push
  94.                   *(unsigned long*)(&backup[0x6])=(unsigned long)(p+0x5);
  95.                   backup[0xA]=0xC3;  //retn
  96.  
  97.           VirtualProtect(p,5,PAGE_EXECUTE_READWRITE,&old);
  98.           *p=0xE9;  //opcode for jmp
  99.           *(unsigned long*)(p+1)=relativeOffset((unsigned long)p,(unsigned long)&HookFunc);
  100.  
  101.           VirtualProtect(p,5,old,&old);
  102.           //----------------------Shitty stuff------------------------------------
  103.                   int x=0;
  104.           while(1)
  105.                   {
  106.                Sleep(1000);
  107.                printf("%s %d\r\n","walied",x);
  108.                            x++;
  109.                   }
  110.  return 0;
  111. }
RAW Paste Data
Top