[英]Windows Kernel Driver: ZwAllocateVirtualMemory causing thread to terminate
I'm trying to write an APC dll injection driver, I've found this example and thought to modify it to my needs. 我正在尝试编写一个APC dll注入驱动程序,我找到了这个示例,并想根据自己的需要对其进行修改。
I use PcreateProcessNotifyRoutineEx to obtain the ProcessId for specific applications I targeting, in this case, "iexplore.exe" and then use PloadImageNotifyRoutine to check if ntdll.dll is already loaded and initialized (from this recommendation ), and if ntdll.dll is loaded, I call "my" InjectDLL function. 我使用PcreateProcessNotifyRoutineEx来获取我定位的特定应用程序的ProcessId,在这种情况下为“ iexplore.exe”,然后使用PloadImageNotifyRoutine检查是否已加载和初始化ntdll.dll(根据此建议 ),以及是否已加载ntdll.dll。 ,我称之为“我的” InjectDLL函数。
This is the PloadImageNotifyRoutine function that is calling InjectDll: 这是调用InjectDll的PloadImageNotifyRoutine函数:
VOID PloadImageNotifyRoutine(
_In_ PUNICODE_STRING FullImageName,
_In_ HANDLE ProcessId,
_In_ PIMAGE_INFO ImageInfo
)
{
PEPROCESS Process = NULL;
PETHREAD Thread = NULL;
PCHAR pTeb = nullptr;
DWORD ArbitraryUserPointer = 0;
PCHAR pszProcessNameA = nullptr;
pTeb = (PCHAR)__readfsdword(0x18);
ArbitraryUserPointer = *(DWORD*)(pTeb + 0x014);
// If ArbitraryUserPointer points to kernel32.dll it means ntdll.dll is done loading.
if (FALSE == IsStringEndWith((wchar_t*)ArbitraryUserPointer, L"\\kernel32.dll"))
{
return;
}
if (!NT_SUCCESS(PsLookupProcessByProcessId(ProcessId, &Process)))
{
return;
}
pszProcessNameA = (PCHAR)PsGetProcessImageFileName(Process);
if (FALSE == StringNCompare(pszProcessNameA, "iexplore.exe", GetStringLength("iexplore.exe")))
{
return;
}
Thread = KeGetCurrentThread();
InjectDll(MODULE_PATH, Process, Thread);
ObDereferenceObject(Process);
}
And this is the InjectDll function: 这是InjectDll函数:
BOOLEAN InjectDll(PWCHAR pModulePath, PEPROCESS Process, PETHREAD Thread)
{
PKINJECT mem;
ULONG size;
mem = NULL;
size = 4096;
if (!NT_SUCCESS(ZwAllocateVirtualMemory(NtCurrentProcess(), (PVOID*)&mem, 0, &size, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE)))
{
return FALSE;
}
//more code ...
}
I removed here some checks so it would be more clear. 我在这里删除了一些检查,这样会更清楚。
I tried to debug it a little, but it seems like ZwAllocateVirtualMemory is trying to allocate memory, failing at some point and terminate the thread. 我尝试对其进行一些调试,但是ZwAllocateVirtualMemory似乎正在尝试分配内存,有时会失败并终止线程。
After it calls ExAllocatePoolWithTag it starting to free memory, unmapping sections and terminate the thread (<= calls I saw at the stack while debugging - didn't really trace each call, but looked at it in general view). 在调用ExAllocatePoolWithTag之后,它开始释放内存,取消映射节并终止线程(<=我在调试时在堆栈中看到的调用-并未真正跟踪每个调用,而是在一般视图中进行了查看)。
The stack before the thread get terminated: 线程终止之前的堆栈:
nt!ExAllocatePoolWithTag+0x195
nt!NtAllocateVirtualMemory+0x1066
nt!KiSystemServicePostCall
nt!ZwAllocateVirtualMemory+0x11
kernel_apc_dll_injector!InjectDll+0x54
kernel_apc_dll_injector!PloadImageNotifyRoutine+0x2b0
nt!PsCallImageNotifyRoutines+0x62
The process is still visible from task manager, but its Memory is 92k and has no CPU usage, probably because it didn't "cleaned up" properly. 从任务管理器中仍然可以看到该进程,但是该进程的内存为92k,没有CPU使用率,可能是因为未正确“清理”该进程。
I don't know if my analysis is right, and maybe it even unnecessary for this problem. 我不知道我的分析是否正确,也许对于这个问题甚至是不必要的。
at first side note - not call PsLookupProcessByProcessId
from image notify routine. 首先注意-不要从图像通知例程调用PsLookupProcessByProcessId
。 this is simply not need. 根本不需要。 check that ProcessId == PsGetCurrentProcessId()
. 检查ProcessId == PsGetCurrentProcessId()
。 and if yes - use current process pointer (as you and use in call ZwAllocateVirtualMemory
- NtCurrentProcess()
) otherwise just exist. 如果是,请使用当前进程指针(如您所用,并在调用ZwAllocateVirtualMemory
- NtCurrentProcess()
),否则将仅存在。
now about main - "ZwAllocateVirtualMemory causing thread to terminate" - of course no. 现在有关主-“ ZwAllocateVirtualMemory导致线程终止”-当然没有。 thread not terminate . 线程未终止 。 it hung . 它挂了 。 at first if thread is terminate - because this is single thread in process at this stage - all process is terminate. 首先,如果线程终止,则-由于此线程在此阶段处于进程中-所有进程均终止。 but you yourself say that The process is still visible from task manager . 但是您自己说, 该过程仍然可以从任务管理器中看到 。 also how you view call stack of terminated thread ? 还如何查看终止线程的调用堆栈? this also say that thread not terminated but wait inside ExAllocatePoolWithTag
这也表示线程没有终止,而是在ExAllocatePoolWithTag
内部ExAllocatePoolWithTag
problem that callback is execute in some critical region and The actions that you can perform in this routine are restricted (The operating system calls the driver's process-notify routine at PASSIVE_LEVEL inside a critical region with normal kernel APCs disabled). 问题是在某些关键区域执行回调,并且您在此例程中可以执行的操作受到限制 (操作系统在禁用了常规内核APC的关键区域内的PASSIVE_LEVEL内调用驱动程序的进程通知例程)。 one of the restrictions - is call ZwAllocateVirtualMemory
- it hung in callback, which you and can see. 限制之一-称为ZwAllocateVirtualMemory
它挂在回调中,您可以看到。
so you can not call ZwAllocateVirtualMemory
and do injection direct from callback. 因此您不能调用ZwAllocateVirtualMemory
并直接从回调中进行注入。 but solution exist. 但存在解决方案。 insert normal kernel apc to current thread. 将普通内核apc插入当前线程。 it will be not executed in-place because - normal kernel APCs disabled in callback. 它不会就地执行,因为-回调中禁用了常规内核APC。 but just after you exit from callback and apc will be enabled - your apc executed. 但在您退出回调并启用apc之后,您的apc已执行。 and here (in normal routine) you already can call ZwAllocateVirtualMemory
and do dll injection 在这里(按常规),您已经可以调用ZwAllocateVirtualMemory
并进行dll注入
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.