模块回调

模块回调

1. 模块加载的监控

[!NOTE] Note
模块加载的监控

// 模块加载回调
VOID ImageMonitorRoutine(
  PUNICODE_STRING FullImageName,
  HANDLE ProcessId,
  PIMAGE_INFO ImageInfo
)
{
  PEPROCESS dwProcess;

  if (ProcessId == 0) // 则是驱动加载
  {
    PsLookupProcessByProcessId(ProcessId, &dwProcess);
    DbgPrint("驱动进程ID: %d, 驱动进程名称: %s, 驱动路径: %wZ\n", 
      ProcessId, PsGetProcessImageFileName(dwProcess), FullImageName);
  }
  else
  {
    PsLookupProcessByProcessId(ProcessId, &dwProcess);
    DbgPrint("模块进程ID: %d, 驱动进程名称: %s, 驱动路径: %wZ\n",
      ProcessId, PsGetProcessImageFileName(dwProcess), FullImageName);
  }
}

// 模块加载的监控
NTSTATUS LgHeaderClass::CreateMoudleMonitor()
{
  // 注册加载模块,卸载模块通知函数
  NTSTATUS dwStatus = PsSetLoadImageNotifyRoutine(ImageMonitorRoutine);

  return dwStatus;
}

// 取消模块加载监控
VOID LgHeaderClass::DeleteMoudleMonitor()
{
  // 取消加载模块,卸载模块通知函数
  PsRemoveLoadImageNotifyRoutine(ImageMonitorRoutine);
}

然后我们在主函数中调用

LgHeaderClass * dwLg;

EXTERN_C VOID DriverUnload(PDRIVER_OBJECT DriverObject)
{
  KdPrint(("驱动卸载\r\n"));
  //dwLg->DeleteProcessMonitor();
  dwLg->DeleteMoudleMonitor();

  delete dwLg;
}

EXTERN_C NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING pReg)
{
  KdPrint(("驱动加载\r\n"));
  NTSTATUS dwStatus = STATUS_SUCCESS;
  DriverObject->DriverUnload = DriverUnload;

  dwLg = new LgHeaderClass();
  //dwStatus = dwLg->CreateProcessMonitor();
  dwStatus = dwLg->CreateMoudleMonitor();
  
  return dwStatus;
}

调用成功

image

2. 模块加载衍生的拦截操作

[!NOTE] Note
模块加载衍生的驱动拦截操作

// 获取进程名称, 因为这个函数导出却未在头文件中声明,所以需要自己定义
PCHAR PsGetProcessImageFileName(IN PEPROCESS Process);
NTSTATUS MmUnmapViewOfSection(IN PEPROCESS Process, PVOID pLoadImageBase);
// 阻止指定驱动加载
BOOLEAN DenyLoadDriver(PVOID pLoadImageBase)
{
  PIMAGE_DOS_HEADER pDosHeader = (PIMAGE_DOS_HEADER)pLoadImageBase;
  PIMAGE_NT_HEADERS pNtHeader = (PIMAGE_NT_HEADERS)((PCHAR)pDosHeader + pDosHeader->e_lfanew);

  // 获取 OEP
  PVOID pAddressOfEntryPoint = (PVOID)((PCHAR)pDosHeader + pNtHeader->OptionalHeader.AddressOfEntryPoint);

  // 使用 MDL 方式写入
  ULONG dwShellCodeSize = 6;
  UCHAR pShellCode[6] = { 
    0xB8, 0x22, 0x00, 0x00, 0xC0, // mov eax, 0xC0000022
    0xC3              // ret
  };

  // 建立与目标地址物理内存的映射
  PMDL pMdl = MmCreateMdl(NULL, pAddressOfEntryPoint, dwShellCodeSize);
  if (pMdl == NULL)
  {
    KdPrint(("MmCreateMdl Error!!!"));
    return FALSE;
  }

  // 更新 MDL 对物理内存的描述
  MmBuildMdlForNonPagedPool(pMdl);
  // 将 MDL 中描述的物理页面映射到虚拟内存中,并返回映射的虚拟内存地址
  PVOID pNewAddress = MmMapLockedPages(pMdl, KernelMode);
  if (pNewAddress == NULL)
  {
    IoFreeMdl(pMdl);
    return FALSE;
  }
  // 写入数据
  RtlCopyMemory(pNewAddress, pShellCode, dwShellCodeSize);

  // 释放 MDL 映射的虚拟内存地址
  MmUnmapLockedPages(pNewAddress, pMdl);
  IoFreeMdl(pMdl);
  return TRUE;
}

// 阻止指定DLL加载
BOOLEAN DenyLoadDll(HANDLE ProcessId, PVOID pLoadImageBase)
{
  NTSTATUS dwStatus = STATUS_SUCCESS;
  PEPROCESS dwpErocess = NULL;

  dwStatus = PsLookupProcessByProcessId(ProcessId, &dwpErocess);
  if (!NT_SUCCESS(dwStatus))
  {
    KdPrint(("PsLookupProcessByProcessId Error:%X\n", dwStatus));
    return FALSE;
  }

  // 卸载模块
  dwStatus = MmUnmapViewOfSection(dwpErocess, pLoadImageBase);
  if (!NT_SUCCESS(dwStatus))
  {
    KdPrint(("MmUnmapViewOfSection Error:%X\n", dwStatus));
    return FALSE;
  }
  return TRUE;
}

‍

posted @ 2026-09-10 23:01  旅行者-林小小  阅读(10)  评论(0)    收藏  举报