如题,在使用KeStackAttachProcess
挂靠到目标进程后,又调用了一系列子函数,此时并没有把EPROCESS
传进去。
PEPROCESS pProcess = NULL;
KAPC_STATE apc;
NTSTATUS status = PsLookupProcessByProcessId((HANDLE)pid, &pProcess);
if (NT_SUCCESS(status))
{
KeStackAttachProcess(pProcess, &apc);
SubRoutine(); // didn't pass target eprocess into sub routine.
KeUnstackDetachProcess(&apc);
ObDereferenceObject(pProcess);
}
但是在SubRoutine
函数中又调用了PsGetCurrentProcessId
() 来获取目标进程的PID
,得到的结果是4
明显这是错误的,通过该查看当前环境信息确认已经附加到IE进程了!
通过查看反汇编PsGetCurrentProcessId
得知,它获取PID是从ethread
结构中读取偏移0x3B0
的数据
1: kd> uf PsGetCurrentProcessId
nt!PsGetCurrentProcessId:
fffff800`03eaccb0 65488b042588010000 mov rax,qword ptr gs:[188h]
fffff800`03eaccb9 488b80b0030000 mov rax,qword ptr [rax+3B0h]
fffff800`03eaccc0 c3 ret
1: kd> dt _ETHREAD
nt!_ETHREAD
+0x000 Tcb : _KTHREAD
+0x360 CreateTime : _LARGE_INTEGER
+0x368 ExitTime : _LARGE_INTEGER
+0x368 KeyedWaitChain : _LIST_ENTRY
+0x378 ExitStatus : Int4B
+0x380 PostBlockList : _LIST_ENTRY
+0x380 ForwardLinkShadow : Ptr64 Void
+0x388 StartAddress : Ptr64 Void
+0x390 TerminationPort : Ptr64 _TERMINATION_PORT
+0x390 ReaperLink : Ptr64 _ETHREAD
+0x390 KeyedWaitValue : Ptr64 Void
+0x398 ActiveTimerListLock : Uint8B
+0x3a0 ActiveTimerListHead : _LIST_ENTRY
+0x3b0 Cid : _CLIENT_ID 《============= 这里读取的PID,进程挂靠后保存的还是原进程的PID
通过查看KeStackAttachProcess
函数的源码,得知被附加进程的EPROCESS结构,保存在ethread->ApcState->Process
中
1: kd> dx -id 0,0,fffffa801b803b30 -r1 (*((ntkrnlmp!_KTHREAD *)0xfffffa801ca40040))
(*((ntkrnlmp!_KTHREAD *)0xfffffa801ca40040)) [Type: _KTHREAD]
[+0x000] Header [Type: _DISPATCHER_HEADER]
[+0x018] CycleTime : 0x6d92c1272 [Type: unsigned __int64]
[+0x020] QuantumTarget : 0x6dd003af2 [Type: unsigned __int64]
[+0x028] InitialStack : 0xfffff8800386cc70 [Type: void *]
[+0x030] StackLimit : 0xfffff88003867000 [Type: void *]
[+0x038] KernelStack : 0xfffff8800386b480 [Type: void *]
[+0x040] ThreadLock : 0x0 [Type: unsigned __int64]
[+0x048] WaitRegister [Type: _KWAIT_STATUS_REGISTER]
[+0x049] Running : 0x1 [Type: unsigned char]
[+0x04a] Alerted [Type: unsigned char [2]]
[+0x04c ( 0: 0)] KernelStackResident : 0x1 [Type: unsigned long]
[+0x04c ( 1: 1)] ReadyTransition : 0x0 [Type: unsigned long]
[+0x04c ( 2: 2)] ProcessReadyQueue : 0x0 [Type: unsigned long]
[+0x04c ( 3: 3)] WaitNext : 0x0 [Type: unsigned long]
[+0x04c ( 4: 4)] SystemAffinityActive : 0x0 [Type: unsigned long]
[+0x04c ( 5: 5)] Alertable : 0x0 [Type: unsigned long]
[+0x04c ( 6: 6)] GdiFlushActive : 0x0 [Type: unsigned long]
[+0x04c ( 7: 7)] UserStackWalkActive : 0x0 [Type: unsigned long]
[+0x04c ( 8: 8)] ApcInterruptRequest : 0x0 [Type: unsigned long]
[+0x04c ( 9: 9)] ForceDeferSchedule : 0x0 [Type: unsigned long]
[+0x04c (10:10)] QuantumEndMigrate : 0x0 [Type: unsigned long]
[+0x04c (11:11)] UmsDirectedSwitchEnable : 0x0 [Type: unsigned long]
[+0x04c (12:12)] TimerActive : 0x0 [Type: unsigned long]
[+0x04c (13:13)] SystemThread : 0x1 [Type: unsigned long]
[+0x04c (31:14)] Reserved : 0x0 [Type: unsigned long]
[+0x04c] MiscFlags : 8193 [Type: long]
[+0x050] ApcState [Type: _KAPC_STATE] <========= 0x50
1: kd> dx -r1 (*((ntkrnlmp!_KAPC_STATE *)0xfffffa801ca40090))
(*((ntkrnlmp!_KAPC_STATE *)0xfffffa801ca40090)) [Type: _KAPC_STATE]
[+0x000] ApcListHead [Type: _LIST_ENTRY [2]]
[+0x020] Process : 0xfffffa801b803b30 [Type: _KPROCESS *] <<======= 0x20
通过分析PsGetCurrentProcess
反汇编,正式利用了上面的偏移来获取的被附加进程的eprocess
1: kd> uf PsGetCurrentProcess
nt!PsGetCurrentProcess:
fffff800`03e9bbb0 65488b042588010000 mov rax,qword ptr gs:[188h] =======》ETHREAD
fffff800`03e9bbb9 488b4070 mov rax,qword ptr [rax+70h] =======》ETHREAD->ApcState->Process
fffff800`03e9bbbd c3 ret
因此,在附加进程后,想要通过某个函数获取被附加进程pid,不能直接使用PsGetCurrentProcessId
,
应该先通过PsGetCurrentProcess
获取目标进程的EPROCESS结构,再使用PsGetProcessId
来获取指定Eprocess的PID。
PsGetProcessId
的反汇编,可以看出是直接从传入参数Eprocess中读取的PID,因此不会错。
// 例如 A 附加到B进程
PEPROCESS pProcess = PsGetCurrentProcess();
HANDLE AttachedPID = PsGetProcessId(pProcess); // 得到的是B进程的PID
HANDLE pid = PsGetCurrentProcessId(); // 得到的是A进程的PID