我正在尝试编写一个apc dll注入驱动程序,我发现
this
举例说明并考虑根据我的需要修改它。
我用
PcreateProcessNotifyRoutineEx
要获取针对特定应用程序的processid,在本例中为“iexplore.exe”,然后使用
PloadImageNotifyRoutine
检查ntdll.dll是否已加载和初始化(从
this recommendation
,如果加载了ntdll.dll,则调用“my”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使用率,可能是因为它没有正确地“清理”。
我不知道我的分析是否正确,也许对这个问题甚至没有必要。