[英]Windows Kernel Driver: ZwAllocateVirtualMemory causing thread to terminate
我正在嘗試編寫一個APC dll注入驅動程序,我找到了這個示例,並想根據自己的需要對其進行修改。
我使用PcreateProcessNotifyRoutineEx來獲取我定位的特定應用程序的ProcessId,在這種情況下為“ iexplore.exe”,然后使用PloadImageNotifyRoutine檢查是否已加載和初始化ntdll.dll(根據此建議 ),以及是否已加載ntdll.dll。 ,我稱之為“我的” 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);
}
這是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 ...
}
我在這里刪除了一些檢查,這樣會更清楚。
我嘗試對其進行一些調試,但是ZwAllocateVirtualMemory似乎正在嘗試分配內存,有時會失敗並終止線程。
在調用ExAllocatePoolWithTag之后,它開始釋放內存,取消映射節並終止線程(<=我在調試時在堆棧中看到的調用-並未真正跟蹤每個調用,而是在一般視圖中進行了查看)。
線程終止之前的堆棧:
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
從任務管理器中仍然可以看到該進程,但是該進程的內存為92k,沒有CPU使用率,可能是因為未正確“清理”該進程。
我不知道我的分析是否正確,也許對於這個問題甚至是不必要的。
首先注意-不要從圖像通知例程調用PsLookupProcessByProcessId
。 根本不需要。 檢查ProcessId == PsGetCurrentProcessId()
。 如果是,請使用當前進程指針(如您所用,並在調用ZwAllocateVirtualMemory
- NtCurrentProcess()
),否則將僅存在。
現在有關主-“ ZwAllocateVirtualMemory導致線程終止”-當然沒有。 線程未終止 。 它掛了 。 首先,如果線程終止,則-由於此線程在此階段處於進程中-所有進程均終止。 但是您自己說, 該過程仍然可以從任務管理器中看到 。 還如何查看終止線程的調用堆棧? 這也表示線程沒有終止,而是在ExAllocatePoolWithTag
內部ExAllocatePoolWithTag
問題是在某些關鍵區域執行回調,並且您在此例程中可以執行的操作受到限制 (操作系統在禁用了常規內核APC的關鍵區域內的PASSIVE_LEVEL內調用驅動程序的進程通知例程)。 限制之一-稱為ZwAllocateVirtualMemory
它掛在回調中,您可以看到。
因此您不能調用ZwAllocateVirtualMemory
並直接從回調中進行注入。 但存在解決方案。 將普通內核apc插入當前線程。 它不會就地執行,因為-回調中禁用了常規內核APC。 但在您退出回調並啟用apc之后,您的apc已執行。 在這里(按常規),您已經可以調用ZwAllocateVirtualMemory
並進行dll注入
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.