Ps回調函數.攔截驅動模組原理+實現.

  • 2019 年 10 月 8 日
  • 筆記

目錄

一丶簡介

主要是講解.內核中如何攔截模組載入的. 需要熟悉.內核回調的設置 PE知識. ShellCode

二丶原理

1.原理

原理是通過回調函數. 回調函數中有 ImageBase. 使用PE解析ImageBase 得到OEP. OEP位置寫入 ret等ShellCode

如何判斷 是載入DLL 還是載入Sys. 可以看回調的第二個參數.(ProcessId) 如果ProcessId == 0. 則是載入Sys

PS: 在內核中解析PE需要用到 ntImage.h頭文件來進行解析.

2.程式碼實現

#include <ntimage.h>  #include <ntddk.h>    #include <wdm.h>    ULONG_PTR g_LoadPtr = 0;      void WPONx64(KIRQL irql)  {      UINT64 cr0 = __readcr0();      cr0 |= 0x10000;      _enable();      __writecr0(cr0);      KeLowerIrql(irql);  }        KIRQL WPOFFx64()  {      KIRQL irql = KeRaiseIrqlToDpcLevel();      UINT64 cr0 = __readcr0();      cr0 &= 0xfffffffffffeffff;      __writecr0(cr0);      _disable();      return irql;    }      BOOLEAN Fuck(PVOID pOep)  {      KIRQL kirql;        if (NULL == pOep)          return FALSE;        //寫入位元組.        UCHAR FuckCode[] = { "xB8x22x00x00xC0xC3" };      kirql = WPOFFx64();      KdBreakPoint();      memcpy(pOep, FuckCode, sizeof(FuckCode) / sizeof(FuckCode[0])); //開頭寫入拒絕訪問錯誤碼讓其無法載入即可.      WPONx64(kirql);      return TRUE;  }  //根據ImageBase來獲取載入模組的入口點  PVOID GetImageOep(PVOID ImageBase)  {        PVOID pAddressOfEntryPoint = NULL;      PIMAGE_DOS_HEADER pDosHead = NULL;      PIMAGE_NT_HEADERS pNtHead = NULL;      PIMAGE_FILE_HEADER pFileHead = NULL;      PIMAGE_OPTIONAL_HEADER pOptHead = NULL;        //開始解析      if (ImageBase == NULL)          return NULL;        pDosHead = (PIMAGE_DOS_HEADER)ImageBase;      pNtHead = (PIMAGE_NT_HEADERS)(pDosHead->e_lfanew + (char *)ImageBase);      pFileHead = (PIMAGE_FILE_HEADER)&pNtHead->FileHeader;      pOptHead = (PIMAGE_OPTIONAL_HEADER)&pNtHead->OptionalHeader;        //判斷是否是PE頭      if (pDosHead->e_magic != 0x5A4D && pNtHead->Signature != 0x5045)          return NULL;      pAddressOfEntryPoint = pOptHead->AddressOfEntryPoint + (char *)ImageBase;        return pAddressOfEntryPoint;  }    char * MyWideUnicodeStringToMutilString(PUNICODE_STRING uString)  {      ANSI_STRING asStr;      char *Buffer = NULL; ;      RtlUnicodeStringToAnsiString(&asStr, uString, TRUE);      Buffer = ExAllocatePoolWithTag(NonPagedPool, uString->MaximumLength * sizeof(wchar_t), 0);      if (Buffer == NULL)          return NULL;      RtlCopyMemory(Buffer, asStr.Buffer, asStr.Length);      return Buffer;  }  VOID pSfFilterModule(      _In_opt_ PUNICODE_STRING FullImageName,      _In_ HANDLE ProcessId,                // pid into which image is being mapped      _In_ PIMAGE_INFO ImageInfo  )  {      /*      模組攔截思路:      1.通過 PIMAGE_INFO->ImageBase 得到模組的ImageBase      2.解析PE頭.      3.可選頭的OEP + ImageBase = 程式運行位置      4.在程式開頭寫入 ret.      5.通過參數一,判斷是不是我們想要攔截的模組.然後進行1 2 3 4步      6.如何判斷載入驅動模組還是DLL 根據參數2.ProcessId高低位判斷即可. == 0載入驅動模組.否則載入DLL      */            PVOID pDriverOep = NULL;      char *ComPareString = NULL;      if (MmIsAddressValid(FullImageName))      {            if (ProcessId == 0)          {              //代表攔截驅動模組                    //判斷名字是否是你想要攔截的.              KdBreakPoint();                ComPareString = MyWideUnicodeStringToMutilString(FullImageName);              if (ComPareString == NULL)                  return;                if (strstr(ComPareString,"1.sys"))              {                  KdBreakPoint();                  KdPrint(("你要攔截的驅動模組名字為: %wZ rn", FullImageName));                  pDriverOep = GetImageOep(ImageInfo->ImageBase);                    //判斷攔截的名字是否是你想要攔截的                  if (pDriverOep != NULL)                  {                      Fuck(pDriverOep);                  }              }            }          //輸出調試        }    }    NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)  {      ULONG iCount = 0;      NTSTATUS ntStatus;      pDriverObj->DriverUnload = DriverUnLoad;      ntStatus = InitDeviceAnSybolicLinkName(pDriverObj);      if (!NT_SUCCESS(ntStatus))      {          return ntStatus;      }        ntStatus = InitDisPatchFunction(pDriverObj);      if (!NT_SUCCESS(ntStatus))      {          return ntStatus;      }          PsSetLoadImageNotifyRoutine(pSfFilterModule);      return STATUS_SUCCESS;  }

3.效果

win7 64 sp1 下測試.