乔丹二世 发表于 2011-1-16 00:53:15

内核所有模块导出函数inline hook检测

void HookCheckAllModuleExportRoutine (PVOID sysInfo)
{
int i,j,k,len,length;
PSYSMODULELIST List = NULL;
char image, Name,sysDir;
ANSI_STRING FullPath;
UNICODE_STRING uFullPath;
ANSI_STRING Temp1,Temp2,Temp3,Temp4,Temp5;

HANDLE hFile = NULL, hSection = NULL;
PVOID BaseAddress = NULL;
IO_STATUS_BLOCK IoStatusBlock;
CLIENT_ID ClientID;
PVOID SysInfo;


PIMAGE_DOS_HEADER DosHead = NULL;
PIMAGE_NT_HEADERS NtHeads = NULL;
PIMAGE_SECTION_HEADER Section = NULL;
PIMAGE_EXPORT_DIRECTORY ExportDir = NULL;
PIMAGE_BASE_RELOCATION RelocDir = NULL;
ULONG kBase = 0, mBase = 0, kNameBase = 0, kOrdinalBase = 0, kFunctionBase = 0;
ULONG ByteEqual, Address = 0, index, NameNumbers, FixAddr = 0, FixAddrBase = 0,RelocSize;
ULONG DataSecVA, DataSecSize, DataSec;


USHORT Temp = 0;
PUCHAR SystemFunName;
PKPROCESS Eprocess;
KAPC_STATE ApcState;
HANDLE ProcessHandle;
UNICODE_STRING ProcessName;
PSYSTEM_PROCESSES pSysinfo;

PKUSER_SHARED_DATA kShareData = USER_SHARED_DATA;

size_t size = 0;
NTSTATUS status;
OBJECT_ATTRIBUTES oa, ob = {sizeof (ob), NULL, NULL,NULL, NULL};


RtlInitAnsiString (&Temp2, "sys");
RtlInitAnsiString (&Temp3, "dll");
RtlInitAnsiString (&Temp4, "exe");
RtlInitAnsiString (&Temp5, "win32k.sys");
RtlInitUnicodeString (&ProcessName, L"winlogon.exe");

w2ascll (Name, kShareData->NtSystemRoot);

strcpy (sysDir, "\\??\\");
strcat (sysDir, Name);

List = (PSYSMODULELIST)sysInfo;

for (j = 0; j < List->ulCount; j++)
{
   

   
    if (StringCompare ("\\??\\", List->smi.ImageName, 4))
    {
       DbgPrint ("Skip %s\n", List->smi.ImageName);
       continue;
    }
   
    mBase = NULL;
    hFile = NULL;
    hSection = NULL;
    BaseAddress = NULL;
      
    memset (Name, 0, sizeof (Name));
    memset (image,0, sizeof (image));
   
    strcpy (Name, sysDir);
    strcpy(image, List->smi.ImageName + List->smi.ModuleNameOffset);
      
    len = strlen (image);
    RtlInitAnsiString (&Temp1, image + len - 3);
   

    if (!RtlCompareString (&Temp1, &Temp2, TRUE))
    {
      if (strstr (image, "watchdog"))
      {
          strcat (Name, "\\System32\\");
      }else
      {
          strcat (Name, "\\System32\\Drivers\\");
      }
      strcat (Name, image);
    }
    else if (!RtlCompareString (&Temp1, &Temp3, TRUE) || !RtlCompareString (&Temp1, &Temp4, TRUE))
    {
      strcat (Name, "\\System32\\");
      strcat (Name, image);
    }
    else
    {
      continue;
    }
   
    RtlInitAnsiString (&Temp1, image);
    if (!RtlCompareString (&Temp5, &Temp1, TRUE))
    {    //win32.sys模块的空间必须挂靠进程才能读取
   
      status = ZwQuerySystemInformation(5,NULL,0,&length);
      if (status == STATUS_INFO_LENGTH_MISMATCH)
      {
          SysInfo = ExAllocatePool(NonPagedPool,length);
          if (NULL == SysInfo)
          {
            goto Error;
          }
      }
      pSysinfo = (PSYSTEM_PROCESSES)SysInfo;
      status = ZwQuerySystemInformation(SystemProcessesAndThreadsInformation, pSysinfo, length, &length);
      if(!NT_SUCCESS(status))
      {
      goto Error;
      }

      //找到winlogon.exe进程,挂靠空间
      do
      {
      if (!RtlCompareString (&(pSysinfo->ProcessName), &ProcessName, TRUE))
      {
          ClientID = pSysinfo->Threads.ClientId;
          ZwOpenProcess (&ProcessHandle, PROCESS_ALL_ACCESS, &ob, &ClientID);
          ObReferenceObjectByHandle (ProcessHandle, PROCESS_ALL_ACCESS, *PsProcessType, KernelMode, &Eprocess, NULL);
          KeStackAttachProcess (Eprocess, &ApcState);
          break;
      }

      if (pSysinfo->NextEntryDelta == 0) break;

      pSysinfo = (ULONG)pSysinfo + pSysinfo->NextEntryDelta;
      }while (1);
      
      ExFreePool(SysInfo);
      memset (Name, 0, sizeof(Name));
      strcpy (Name, "\\Device\\HarddiskVolume1\\Windows\\System32\\");
      strcat (Name, image);
      
    }

    RtlInitAnsiString (&FullPath, Name);
    RtlAnsiStringToUnicodeString (&uFullPath, &FullPath, TRUE);

    //获得模块在内核中的相关参数
    kBase = List->smi.Base;
    if (!MmIsAddressValid (kBase))
    {
      DbgPrint ("%s 'base is not valid!\n", image);
      goto Error;
    }

    DosHead = (PIMAGE_DOS_HEADER)kBase;
    NtHeads = (PIMAGE_NT_HEADERS)((ULONG)DosHead + DosHead->e_lfanew);
    Section = (PIMAGE_SECTION_HEADER) ((ULONG)NtHeads + sizeof(IMAGE_NT_HEADERS));
   
    if (NULL == NtHeads->OptionalHeader.DataDirectory.VirtualAddress)
    {
      DbgPrint ("%sdoesnt has valid export table!\n", image);
      continue;
    }
   
    DataSec = 0;
    for (i = 0; i < NtHeads->FileHeader.NumberOfSections; i++)
    {
      if (strstr (Section->Name, "text") ||strstr (Section->Name, "PAGE")||strstr (Section->Name, "INIT"))
      {
      DataSecVA = Section->Misc.VirtualSize;
      DataSecSize = Section->VirtualAddress;
      DataSec++;
      }
      Section ++;
    }
    if (i ==NtHeads->FileHeader.NumberOfSections && DataSec == 0)
    {
      DbgPrint ("%wZdoesnt find the text section!\n", &FullPath);
    }

   
    ExportDir = (PIMAGE_EXPORT_DIRECTORY)((ULONG)kBase + NtHeads->OptionalHeader.DataDirectory.VirtualAddress);
    NameNumbers = ExportDir->NumberOfNames;

    kNameBase = kBase + ExportDir->AddressOfNames;
    kOrdinalBase = kBase + ExportDir->AddressOfNameOrdinals;
    kFunctionBase = kBase + ExportDir->AddressOfFunctions;



    //获得模块加载后的相关参数
    InitializeObjectAttributes (
      &oa,
      &uFullPath,
      OBJ_CASE_INSENSITIVE,
      NULL,
      NULL
      );
    status = ZwOpenFile(
      &hFile,
      FILE_READ_ACCESS,
      &oa,
      &IoStatusBlock,
      FILE_SHARE_READ,
      FILE_SYNCHRONOUS_IO_NONALERT
      );
    if (!NT_SUCCESS(status))
    {
      KdPrint (("OpenFile %wZ error\n", &uFullPath));
      goto Error;

    }
    oa.ObjectName = NULL;
    status =ZwCreateSection(
      &hSection,
      SECTION_MAP_EXECUTE,
      &oa,
      0,
      PAGE_EXECUTE,
      SEC_IMAGE,
      hFile
      );
    if (!NT_SUCCESS(status))
    {
      
      KdPrint (("CreateSection for%wZ error", &uFullPath));
      goto Error;

    }
    size = 0;
    status =ZwMapViewOfSection(
      hSection,
      NtCurrentProcess(),
      &BaseAddress,
      0,
      1000,
      0,
      &size,
      (SECTION_INHERIT)1,
      MEM_TOP_DOWN,
      PAGE_READWRITE
      );
    if (!NT_SUCCESS(status))
    {
      KdPrint (("MapViewSection for%wZ error", &uFullPath));
      goto Error;

    }
   
    mBase = ExAllocatePool (NonPagedPool, size);
    if (NULL == mBase)
    {
      goto Error;
    }

    if (BaseAddress != NULL)
    {
      RtlCopyMemory (mBase, BaseAddress, size);
    }
   
    DosHead = (PIMAGE_DOS_HEADER)mBase;
    NtHeads = (PIMAGE_NT_HEADERS)((ULONG)DosHead + DosHead->e_lfanew);
    RelocDir = (PIMAGE_BASE_RELOCATION)((ULONG)mBase + NtHeads->OptionalHeader.DataDirectory.VirtualAddress);
    if (RelocDir != NULL)
    {
      while (RelocDir->VirtualAddress != 0 || RelocDir->SizeOfBlock !=0)
      {
      FixAddrBase = RelocDir->VirtualAddress + (ULONG)mBase;
      RelocSize = (RelocDir->SizeOfBlock - 8)/2;
      for ( i = 0; i < RelocSize; i++)
      {
          Temp = *(PUSHORT)((ULONG)RelocDir + sizeof (IMAGE_BASE_RELOCATION) + i * 2);
          if ( (Temp & 0xF000) == 0x3000)
          {
            Temp &= 0x0FFF;
            FixAddr = FixAddrBase + (ULONG)Temp;
            *(PULONG)FixAddr = *(PULONG)FixAddr + (ULONG)kBase - (ULONG)NtHeads->OptionalHeader.ImageBase;
          }
      }
      RelocDir = (ULONG)RelocDir + RelocDir->SizeOfBlock;
      }
    }
                              /*
    if (j == 0)
    {
      KernelCheck (kBase, mBase, sysInfo);
    }
*/

    for (i = 0; i < NameNumbers; i++)
    {
      SystemFunName = (PUCHAR)(*(PULONG)(kNameBase + i * 4) + (ULONG)kBase);
      index = *((PUSHORT)(kOrdinalBase + i * 2));
      Address = *(PULONG)(kFunctionBase + index * 4);
      
      for (k = 0; k < DataSec; k++)
      {
         if ( (Address >= DataSecVA) && (Address <= DataSecVA + DataSecSize))
         {
            length = GetFunctionLength(kBase + Address);
            if (length)
            {
               ByteEqual = RtlCompareMemory (kBase + Address, mBase + Address, length);
               if (ByteEqual != length)
               {                                             
                  KdPrint (("%s:%s:%x has been inline-hooked!\n", image, SystemFunName, kBase + Address));
               }
            }
            break;
         }               
      }
      
    }



Error:
    RtlFreeUnicodeString (&uFullPath);
    if (!RtlCompareString (&Temp5, &Temp1, TRUE))
    {
      KeUnstackDetachProcess (&ApcState);
    }
    if (mBase != NULL)
    {
      ExFreePool (mBase);
      mBase = NULL;
    }
    if (hFile != NULL)
    {
      ZwClose(hFile);
      hFile = NULL;
    }
    if (hSection != NULL)
    {
      ZwClose(hSection);
      hSection = NULL;
    }
    if (BaseAddress != NULL)
    {
      ZwUnmapViewOfSection(NtCurrentProcess(),BaseAddress);
      BaseAddress = NULL;
    }

}
return;
}

ULONG GetFunctionLength(ULONG FAddress)
{
    ULONG i = 0, Flag = 0;
    PUCHAR Temp = NULL;
   
    Temp = FAddress;
    while (!Flag && MmIsAddressValid(Temp) && MmIsAddressValid (Temp + 1)
      && MmIsAddressValid(Temp + 2) && MmIsAddressValid (Temp + 3)&& MmIsAddressValid (Temp + 4))
    {
      
      switch (*Temp)
      {
      case 0xc3:
      case 0xcf:
      case 0xcb:
      if ( (*(Temp+1) == 0xcc) || (*(Temp+1) == 0x8b && *(Temp+1) == 0xFF))
      {
            Flag = 1;
      }
      break;
      
      case 0xc2:
      case 0xca:
      if ( (*(Temp+3) == 0xcc)|| (*(Temp+3) == 0x8b && *(Temp+4) == 0xFF))
      {
            Flag = 1;
      }
      break;
      
      default:
      break;
      }
      
      if (!Flag)
      {
          if (*((PULONG)Temp) == 0 && *(Temp + 4) == 0)
            return 0;
      }
      
      Temp ++;
      i++;
    }

    return i;
}

testid 发表于 2011-11-8 00:14:47

纯帮顶了!
页: [1]
查看完整版本: 内核所有模块导出函数inline hook检测