从 LoadImageNotifyRoutine 注入 DLL 会在 ZwMapViewOfSection 上挂起



所以我正在制作一个破解,其中一个部分是钩住某个函数并等待某个参数的某个组合发生,然后挑战就完成了。

为此,我正在创建一个驱动程序,用于将 DLL 注入具有特定 DLL 并挂钩某个函数的进程。

我正在做

  1. 获取要注入的 DLL 的句柄
ZwCreateFile(
&DeviceExtension->HookDllHandle, 
GENERIC_ALL, 
&Attributes, 
&StatusBlock, 
NULL, 
0, 
0, 
FILE_OPEN, 
FILE_SYNCHRONOUS_IO_NONALERT, 
NULL, 
0
)
  1. 然后,在驱动程序 main 中注册一个 LoadImageNotifyRoutine。PsSetLoadImageNotifyRoutine(ImageCBK);

应该发生什么:

  1. 我检查是否加载了所需的 DLL(将导出我的函数(。
  2. 通过在调用回调的进程的上下文中,我创建了一个带有ZwCreateSection的部分,然后将 dll 映射到该部分,并通过创建新线程来调用 DLL 的入口点。
  3. 之后,挂钩应该没有问题。

尽管用于ZwCreateSectionZwMapViewOfSection的 IRQL 允许在通知例程中使用它们,但每次我尝试使用它时,ZwMapViewOfSection仍然挂起。

我一直在使用旁观者的一些代码

status = ObOpenObjectByPointer(PsGetCurrentProcess(), OBJ_KERNEL_HANDLE, NULL, STANDARD_RIGHTS_ALL, NULL, KernelMode, &ProcessHandle);
if (!NT_SUCCESS(status))
{
DbgPrint("Unable to get process handlen");
return STATUS_SEVERITY_ERROR;
}
// Create a new section for DLL mapping
InitializeObjectAttributes(&Attributes, NULL, OBJ_KERNEL_HANDLE, NULL, NULL);
status = ZwCreateSection(&DllSectionHandle, SECTION_MAP_WRITE | SECTION_MAP_READ | SECTION_MAP_EXECUTE | SECTION_QUERY, &Attributes, NULL, PAGE_EXECUTE_READ, SEC_IMAGE, DeviceExtension->HookDllHandle);
if (!NT_SUCCESS(status))
{
ZwClose(ProcessHandle);
DbgPrint("Section creation failed %08Xn", status);
return status;
}
DbgPrint("Section created %08Xn", DllSectionHandle);
// Map DLL on the section
status = ZwMapViewOfSection(DllSectionHandle, ProcessHandle, &DllBaseAddress, 0, 0, NULL, &DllViewSize, ViewUnmap, 0, PAGE_EXECUTE_READ);
if (!NT_SUCCESS(status))
{
ZwClose(ProcessHandle);
ZwClose(DllSectionHandle);
DbgPrint("Unable to map section %08Xn", status);
return status;
}
DbgPrint("Mapped DLL: %08Xn", DllBaseAddress);

可悲的是,它从未显示带有DllBaseAddress的最后一个 DbgPrint

只需阅读文档

操作系统调用驱动程序的加载映像通知例程 始终在具有正常内核 APC 的关键区域内PASSIVE_LEVEL禁用

为避免死锁,加载映像通知例程不得调用系统映射、分配、查询、释放或执行其他操作的例程 在用户空间虚拟内存上。

您忽略了这一点并调用该映射ZwMapViewOfSection例程。 并陷入僵局

解决方案简单而优雅 - 将普通内核模式 APC 插入ImageCBK中的当前线程。 因为此APC在此处被禁用 - 它已经在您从ImageCBK返回后执行 - 只是系统从关键区域退出并启用APC。 此时,将调用您的APC KernelRoutine/NormalRoutine。 正是在NormalRoutine里面你必须映射

相关内容

  • 没有找到相关文章

最新更新