类似于进程的创建过程:进程创建过程分析NtCreateProcess-NtCreateProcessEx-PspCreateProcess。
线程的创建是从NtCreateThread函数开始的。NtCreateThread所做的事很简单,首先,对于非内核模式传递过来的调用,检查参数是否可写。处理InitialTeb参数,将它放到局部变量CapturedInitialTeb中。这些操作都是在try块中完成的。然后调用真正创建线程的函数PspCreateThread。
NTSTATUS
NtCreateThread(
__out PHANDLE ThreadHandle,
__in ACCESS_MASK DesiredAccess,
__in_opt POBJECT_ATTRIBUTES ObjectAttributes,
__in HANDLE ProcessHandle,
__out Pcreateprocess-analyseCLIENT_ID ClientId,
__in PCONTEXT ThreadContext,
__in PINITIAL_TEB InitialTeb,
__in BOOLEAN CreateSuspended
)
{
NTSTATUS Status;
INITIAL_TEB CapturedInitialTeb;
PAGED_CODE();
try {
if (KeGetPreviousMode () != KernelMode) {
ProbeForWriteHandle (ThreadHandle);
if (ARGUMENT_PRESENT (ClientId)) {
ProbeForWriteSmallStructure (ClientId, sizeof (CLIENT_ID), sizeof (ULONG));
}
if (ARGUMENT_PRESENT (ThreadContext) ) {
ProbeForReadSmallStructure (ThreadContext, sizeof (CONTEXT), CONTEXT_ALIGN);
} else {
return STATUS_INVALID_PARAMETER;
}
ProbeForReadSmallStructure (InitialTeb, sizeof (InitialTeb->OldInitialTeb), sizeof (ULONG));
}
CapturedInitialTeb.OldInitialTeb = InitialTeb->OldInitialTeb;
if (CapturedInitialTeb.OldInitialTeb.OldStackBase == NULL &&
CapturedInitialTeb.OldInitialTeb.OldStackLimit == NULL) {
CapturedInitialTeb = *InitialTeb;
}
} except (ExSystemExceptionFilter ()) {
return GetExceptionCode ();
}
Status = PspCreateThread (ThreadHandle,
DesiredAccess,
ObjectAttributes,
ProcessHandle,
NULL,
ClientId,
ThreadContext,
&CapturedInitialTeb,
CreateSuspended,
NULL,
NULL);
return Status;
}
下面进入PspCreateThread的流程分析。
1.得到当前线程,判断模式,得到进程对象。
CurrentThread = PsGetCurrentThread ();
if (StartRoutine != NULL) {
PreviousMode = KernelMode;
} else {
PreviousMode = KeGetPreviousModeByThread (&CurrentThread->Tcb);
}
Teb = NULL;
Thread = NULL;
Process = NULL;
if (ProcessHandle != NULL) {
Status = ObReferenceObjectByHandle (ProcessHandle,
PROCESS_CREATE_THREAD,
PsProcessType,
PreviousMode,
&Process,
NULL);
} else {
if (StartRoutine != NULL) {
ObReferenceObject (ProcessPointer);
Process = ProcessPointer;
Status = STATUS_SUCCESS;
} else {
Status = STATUS_INVALID_HANDLE;
}
}
if (!NT_SUCCESS (Status)) {
return Status;
}
if ((PreviousMode != KernelMode) && (Process == PsInitialSystemProcess)) {
ObDereferenceObject (Process);
return STATUS_INVALID_HANDLE;
}
2.调用ObCreateObject创建一个线程对象ETHREAD,并清零。
Status = ObCreateObject (PreviousMode,
PsThreadType,
ObjectAttributes,
PreviousMode,
NULL,
sizeof(ETHREAD),
0,
0,
&Thread);
if (!NT_SUCCESS (Status)) {
ObDereferenceObject (Process);
return Status;
}
RtlZeroMemory (Thread, sizeof (ETHREAD));
3.初始化基本域。
//初始化rundown
ExInitializeRundownProtection (&Thread->RundownProtect);
Thread->ThreadsProcess = Process;
Thread->Cid.UniqueProcess = Process->UniqueProcessId;
CidEntry.Object = Thread;
CidEntry.GrantedAccess = 0;
//从CID句柄表中创建一个句柄表项
Thread->Cid.UniqueThread = ExCreateHandle (PspCidTable, &CidEntry);
if (Thread->Cid.UniqueThread == NULL) {
ObDereferenceObject (Thread);
return (STATUS_INSUFFICIENT_RESOURCES);
}
Thread->ReadClusterSize = MmReadClusterSize;
KeInitializeSemaphore (&Thread->LpcReplySemaphore, 0L, 1L);
InitializeListHead (&Thread->LpcReplyChain);
InitializeListHead (&Thread->IrpList);
InitializeListHead (&Thread->PostBlockList);
PspInitializeThreadLock (Thread);
KeInitializeSpinLock (&Thread->ActiveTimerListLock);
InitializeListHead (&Thread->ActiveTimerListHead);
4.获得RundownProtect锁,以避免在创建过程中该进程被停掉(rundown),直到该线程被插入到进程的线程链表中,锁才被释放。
if (!ExAcquireRundownProtection (&Process->RundownProtect)) {
ObDereferenceObject (Thread);
return STATUS_PROCESS_IS_TERMINATING;
}
5.判断是不是用户模式线程,并进行各种初始化。
if (ARGUMENT_PRESENT (ThreadContext)) {
//不为null,创建的是用户模式线程,创建TEB,并初始化
Status = MmCreateTeb (Process, InitialTeb, &Thread->Cid, &Teb);
if (!NT_SUCCESS (Status)) {
ExReleaseRundownProtection (&Process->RundownProtect);
ObDereferenceObject (Thread);
return Status;
}
try {
//利用ThreadContext中的程序指针(Eip寄存器)来设置线程的启动地址
Thread->StartAddress = (PVOID)CONTEXT_TO_PROGRAM_COUNTER(ThreadContext);
#if defined(_AMD64_)
Thread->Win32StartAddress = (PVOID)ThreadContext->Rdx;
#elif defined(_X86_)
//将ThreadContext中的Eax寄存器设置到线程的Win32StartAddress
Thread->Win32StartAddress = (PVOID)ThreadContext->Eax;
#else
#error “no target architecture”
#endif
} except (EXCEPTION_EXECUTE_HANDLER) {
Status = GetExceptionCode();
}
if (NT_SUCCESS (Status)) {
//初始化一些线程属性
Status = KeInitThread (&Thread->Tcb,
NULL,
PspUserThreadStartup,
(PKSTART_ROUTINE)NULL,
Thread->StartAddress,
ThreadContext,
Teb,
&Process->Pcb);
}
} else {
//系统线程
Teb = NULL;
//设置系统线程位
PS_SET_BITS (&Thread->CrossThreadFlags, PS_CROSS_THREAD_FLAGS_SYSTEM);
Thread->StartAddress = (PKSTART_ROUTINE) StartRoutine;
Status = KeInitThread (&Thread->Tcb,
NULL,
PspSystemThreadStartup,
StartRoutine,
StartContext,
NULL,
NULL,
&Process->Pcb);
}
if (!NT_SUCCESS (Status)) {
if (Teb != NULL) {
MmDeleteTeb(Process, Teb);
}
ExReleaseRundownProtection (&Process->RundownProtect);
ObDereferenceObject (Thread);
return Status;
}
6.锁住线程,确保此进程不是在退出或终止过程中。
PspLockProcessExclusive (Process, CurrentThread);
//进程正在结束
if ((Process->Flags&PS_PROCESS_FLAGS_PROCESS_DELETE) != 0 ||
(((CurrentThread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_TERMINATED) != 0) &&
(ThreadContext != NULL) &&
(THREAD_TO_PROCESS(CurrentThread) == Process))) {
PspUnlockProcessExclusive (Process, CurrentThread);
KeUninitThread (&Thread->Tcb);
if (Teb != NULL) {
MmDeleteTeb(Process, Teb);
}
ExReleaseRundownProtection (&Process->RundownProtect);
ObDereferenceObject(Thread);
return STATUS_PROCESS_IS_TERMINATING;
}
7.进程的活动线程+1,加入线程链表。
OldActiveThreads = Process->ActiveThreads++;
InsertTailList (&Process->ThreadListHead, &Thread->ThreadListEntry);
KeStartThread (&Thread->Tcb);
PspUnlockProcessExclusive (Process, CurrentThread);
ExReleaseRundownProtection (&Process->RundownProtect);
8.若是进程的第一个线程,则触发该进程的创建通知。
if (OldActiveThreads == 0) {
PERFINFO_PROCESS_CREATE (Process);
if (PspCreateProcessNotifyRoutineCount != 0) {
ULONG i;
PEX_CALLBACK_ROUTINE_BLOCK CallBack;
PCREATE_PROCESS_NOTIFY_ROUTINE Rtn;
for (i=0; i<PSP_MAX_CREATE_PROCESS_NOTIFY; i++) {
CallBack = ExReferenceCallBackBlock (&PspCreateProcessNotifyRoutine[i]);
if (CallBack != NULL) {
Rtn = (PCREATE_PROCESS_NOTIFY_ROUTINE) ExGetCallBackBlockRoutine (CallBack);
Rtn (Process->InheritedFromUniqueProcessId,
Process->UniqueProcessId,
TRUE);
ExDereferenceCallBackBlock (&PspCreateProcessNotifyRoutine[i],
CallBack);
}
}
}
}
9.如果新线程的进程在一个作业中,则需要做特定的处理。
Job = Process->Job;
if (Job != NULL && Job->CompletionPort &&
!(Process->JobStatus & (PS_JOB_STATUS_NOT_REALLY_ACTIVE|PS_JOB_STATUS_NEW_PROCESS_REPORTED))) {
PS_SET_BITS (&Process->JobStatus, PS_JOB_STATUS_NEW_PROCESS_REPORTED);
KeEnterCriticalRegionThread (&CurrentThread->Tcb);
ExAcquireResourceSharedLite (&Job->JobLock, TRUE);
if (Job->CompletionPort != NULL) {
IoSetIoCompletion (Job->CompletionPort,
Job->CompletionKey,
(PVOID)Process->UniqueProcessId,
STATUS_SUCCESS,
JOB_OBJECT_MSG_NEW_PROCESS,
FALSE);
}
ExReleaseResourceLite (&Job->JobLock);
KeLeaveCriticalRegionThread (&CurrentThread->Tcb);
}
PERFINFO_THREAD_CREATE(Thread, InitialTeb);
10.通知接受线程创建事件的出调例程。
if (PspCreateThreadNotifyRoutineCount != 0) {
ULONG i;
PEX_CALLBACK_ROUTINE_BLOCK CallBack;
PCREATE_THREAD_NOTIFY_ROUTINE Rtn;
for (i = 0; i < PSP_MAX_CREATE_THREAD_NOTIFY; i++) {
CallBack = ExReferenceCallBackBlock (&PspCreateThreadNotifyRoutine[i]);
if (CallBack != NULL) {
Rtn = (PCREATE_THREAD_NOTIFY_ROUTINE) ExGetCallBackBlockRoutine (CallBack);
Rtn (Thread->Cid.UniqueProcess,
Thread->Cid.UniqueThread,
TRUE);
ExDereferenceCallBackBlock (&PspCreateThreadNotifyRoutine[i],
CallBack);
}
}
}
11.线程对象的引用计数加2,一个针对当前的创建操作,另一个针对要返回的线程句柄。
ObReferenceObjectEx (Thread, 2);
12.如果CreateSuspended指示新线程立即被挂起,则调用KeSuspendThread挂起线程。
if (CreateSuspended) {
try {
KeSuspendThread (&Thread->Tcb);
} except ((GetExceptionCode () == STATUS_SUSPEND_COUNT_EXCEEDED)?
EXCEPTION_EXECUTE_HANDLER :
EXCEPTION_CONTINUE_SEARCH) {
}
if (Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_TERMINATED) {
KeForceResumeThread (&Thread->Tcb);
}
}
13.根据指定的期望访问权限,调用SeCreateAccessStateEx函数创建一个访问状态结构
AccessState = NULL;
if (!PsUseImpersonationToken) {
AccessState = &LocalAccessState;
Status = SeCreateAccessStateEx (NULL,
ARGUMENT_PRESENT (ThreadContext)?PsGetCurrentProcessByThread (CurrentThread) : Process,
AccessState,
&AuxData,
DesiredAccess,
&PsThreadType->TypeInfo.GenericMapping);
if (!NT_SUCCESS (Status)) {
PS_SET_BITS (&Thread->CrossThreadFlags,
PS_CROSS_THREAD_FLAGS_DEADTHREAD);
if (CreateSuspended) {
(VOID) KeResumeThread (&Thread->Tcb);
}
KeReadyThread (&Thread->Tcb);
ObDereferenceObjectEx (Thread, 2);
return Status;
}
}
14.调用ObInsertObject函数把线程对象插入到当前进程的句柄表中。
Status = ObInsertObject (Thread,
AccessState,
DesiredAccess,
0,
NULL,
&LocalThreadHandle);
if (AccessState != NULL) {
SeDeleteAccessState (AccessState);
}
if (!NT_SUCCESS (Status)) {
//调用失败,终止线程
PS_SET_BITS (&Thread->CrossThreadFlags,
PS_CROSS_THREAD_FLAGS_DEADTHREAD);
if (CreateSuspended) {
KeResumeThread (&Thread->Tcb);
}
} else {
try {
//设置ThreadHandle 、ClientId
*ThreadHandle = LocalThreadHandle;
if (ARGUMENT_PRESENT (ClientId)) {
*ClientId = Thread->Cid;
}
} except(EXCEPTION_EXECUTE_HANDLER) {
PS_SET_BITS (&Thread->CrossThreadFlags,
PS_CROSS_THREAD_FLAGS_DEADTHREAD);
if (CreateSuspended) {
(VOID) KeResumeThread (&Thread->Tcb);
}
KeReadyThread (&Thread->Tcb);
ObDereferenceObject (Thread);
ObCloseHandle (LocalThreadHandle, PreviousMode);
return GetExceptionCode();
}
}
15.设置线程的创建时间。
KeQuerySystemTime(&CreateTime);
ASSERT ((CreateTime.HighPart & 0xf0000000) == 0);
PS_SET_THREAD_CREATE_TIME(Thread, CreateTime);
16.设置线程的访问权限
if ((Thread->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_DEADTHREAD) == 0) {
Status = ObGetObjectSecurity (Thread,
&SecurityDescriptor,
&MemoryAllocated);
if (!NT_SUCCESS (Status)) {
PS_SET_BITS (&Thread->CrossThreadFlags,
PS_CROSS_THREAD_FLAGS_DEADTHREAD);
if (CreateSuspended) {
KeResumeThread(&Thread->Tcb);
}
KeReadyThread (&Thread->Tcb);
ObDereferenceObject (Thread);
ObCloseHandle (LocalThreadHandle, PreviousMode);
return Status;
}
SubjectContext.ProcessAuditId = Process;
SubjectContext.PrimaryToken = PsReferencePrimaryToken(Process);
SubjectContext.ClientToken = NULL;
AccessCheck = SeAccessCheck (SecurityDescriptor,
&SubjectContext,
FALSE,
MAXIMUM_ALLOWED,
0,
NULL,
&PsThreadType->TypeInfo.GenericMapping,
PreviousMode,
&Thread->GrantedAccess,
&accesst);
PsDereferencePrimaryTokenEx (Process, SubjectContext.PrimaryToken);
ObReleaseObjectSecurity (SecurityDescriptor,
MemoryAllocated);
if (!AccessCheck) {
Thread->GrantedAccess = 0;
}
Thread->GrantedAccess |= (THREAD_TERMINATE | THREAD_SET_INFORMATION | THREAD_QUERY_INFORMATION);
} else {
Thread->GrantedAccess = THREAD_ALL_ACCESS;
}
17.调用KeReadyThread,使线程进入“就绪”状态,准备马上执行。或者此时进程未在内存中,则新线程的状态为“转移”,以等待换入内存后再执行。引用计数减1.
KeReadyThread (&Thread->Tcb);
ObDereferenceObject (Thread);
return Status;
至此线程的创建过程就完成了。