现如今Windows x64已经很普遍了。基于内核驱动,监视进程创建,在进程主线程启动之前修改其入口点以便执行一段自己的代码是十分有用的。本文以Windows 7 x64为基础,对这个问题进行了尝试。
0x1 修改的时机
Windows x64提供了注册回调的方法,PsSetCreateProcessNotifyRoutine/ PsSetCreateProcessNotifyRoutineEx,以使得安全产品开发者可以在进程创建时得到通知。在回调函数中得到新建进程的主线程对象是修改入口点的第一步。
PsSetCreateProcessNotifyRoutineEx回调函数的原型是:
VOID
CreateProcessNotifyEx(
__inout PEPROCESS Process,
__in HANDLE ProcessId,
__in_opt PPS_CREATE_NOTIFY_INFO CreateInfo
);
第一个参数是一个指向新创建的进程对象。通过 _EPROCESS 可以得到该进程目前唯一的一个线程:
0:kd> dt _EPROCESS ThreadListHead
ntdll!_EPROCESS
+0x300 ThreadListHead : _LIST_ENTRY
ThreadListHead的Flink指向主线程 _ETHREAD 结构中的 ThreadListEntry的地址:
0:kd> dt _ETHREAD ThreadListEntry
ntdll!_ETHREAD
+0x420 ThreadListEntry: _LIST_ENTRY
得到ThreadListEntry地址后即可反推出线程对象的地址,本例中即为
ethread = poi(eprocess+0x300) - 0x420
PsSetCreateProcessNotifyRoutine回调函数的原型是:
VOID
(*PCREATE_PROCESS_NOTIFY_ROUTINE)(
IN HANDLE ParentId,
IN HANDLE ProcessId,
IN BOOLEAN Create
);
第二个参数是新创建进程ID。可以采用PsLookupProcessByProcessId可以得到进程对象,从而再进一步采用上面的方面获得新进程的主线程对象:
NTSTATUS PsLookupProcessByProcessId(
_In_ HANDLE ProcessId,
_Out_ PEPROCESS *Process
);
Windows还提供了通过PsSe