zoukankan      html  css  js  c++  java
  • 线程的创建过程

        由于这两天在研究调试机制,所以记录下被调试线程的创建过程,如果哪里有遗漏,以后会再补充

       线程创建过程分为两部分:

       第一部分: CreateThread->NtCreateThread->PspCreateThread->KeInitThread->KiInitializeContextThread->KiThreadStartUp

         第二部分:KiThreadStartUp->PspUserThreadStartup->DbgkCreateThread

     PspCreateThread: This routine creates and initializes a thread object. It implements the foundation for NtCreateThread and for PsCreateSystemThread.

      KeInitThread:    This function initializes a thread object. The priority, affinity, and initial quantum are taken from the parent process object.

      KiInitializeContextThread: This function initializes the machine dependent context of a thread object.

      KiThreadStartUp:

        ; This routine is called at thread startup. Its function is to call the
        ; initial thread procedure. If control returns from the initial thread
        ; procedure and a user mode context was established when the thread
        ; was initialized, then the user mode context is restored and control
        ; is transferred to user mode. Otherwise a bugcheck will occur.

    调试过程:DbgkCreateThread->DbgkpSendApiMessage(按需挂起线程)->DbgkpQueueMessage(内核事件唤醒,设置DEBUG_EVENT结构)

    //创建线程或者进程信息
    
    VOID
    DbgkCreateThread(
        PETHREAD Thread,
        PVOID StartAddress
        )
    
    /*++
    
    Routine Description:
    
        This function is called when a new thread begins to execute. If the
        thread has an associated DebugPort, then a message is sent thru the
        port.
    
        If this thread is the first thread in the process, then this event
        is translated into a CreateProcessInfo message.
    
        If a message is sent, then while the thread is awaiting a reply,
        all other threads in the process are suspended.
    
    Arguments:
    
        Thread - New thread just being started
    
        StartAddress - Supplies the start address for the thread that is
            starting.
    
    Return Value:
    
        None.
    
    --*/
    
    {
        PVOID Port;
        DBGKM_APIMSG m;
        PDBGKM_CREATE_THREAD CreateThreadArgs;
        PDBGKM_CREATE_PROCESS CreateProcessArgs;
        PEPROCESS Process;
        PDBGKM_LOAD_DLL LoadDllArgs;
        NTSTATUS Status;
        OBJECT_ATTRIBUTES Obja;
        IO_STATUS_BLOCK IoStatusBlock;
        PIMAGE_NT_HEADERS NtHeaders;
        PTEB Teb;
        ULONG OldFlags;
    #if defined(_WIN64)
        PVOID Wow64Process;
    #endif
    
        PAGED_CODE();
    
        Process = PsGetCurrentProcessByThread (Thread);
    
    #if defined(_WIN64)
        Wow64Process = Process->Wow64Process;
    #endif
    
        OldFlags = PS_TEST_SET_BITS (&Process->Flags, PS_PROCESS_FLAGS_CREATE_REPORTED|PS_PROCESS_FLAGS_IMAGE_NOTIFY_DONE);
    
        if ((OldFlags&PS_PROCESS_FLAGS_IMAGE_NOTIFY_DONE) == 0 && PsImageNotifyEnabled) {
            IMAGE_INFO ImageInfo;
            UNICODE_STRING UnicodeFileName;
            POBJECT_NAME_INFORMATION FileNameInfo;
    
            //
            // notification of main .exe
            //
            ImageInfo.Properties = 0;
            ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT;
            ImageInfo.ImageBase = Process->SectionBaseAddress;
            ImageInfo.ImageSize = 0;
    
            try {
                NtHeaders = RtlImageNtHeader (Process->SectionBaseAddress);
        
                if (NtHeaders) {
    #if defined(_WIN64)
                    if (Wow64Process != NULL) {
                        ImageInfo.ImageSize = DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER ((PIMAGE_NT_HEADERS32)NtHeaders, SizeOfImage);
                    } else {
    #endif
                        ImageInfo.ImageSize = DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER (NtHeaders, SizeOfImage);
    #if defined(_WIN64)
                    }
    #endif
                }
            } except (EXCEPTION_EXECUTE_HANDLER) {
                ImageInfo.ImageSize = 0;
            }
            ImageInfo.ImageSelector = 0;
            ImageInfo.ImageSectionNumber = 0;
    
            Status = MmGetFileNameForSection (Process->SectionObject, &FileNameInfo);
            if (FileNameInfo != NULL) {
                PsCallImageNotifyRoutines (&FileNameInfo->Name,
                                           Process->UniqueProcessId,
                                           &ImageInfo);
                ExFreePool (FileNameInfo);
            } else {
                PsCallImageNotifyRoutines (NULL,
                                           Process->UniqueProcessId,
                                           &ImageInfo);
            }
    
            //
            // and of ntdll.dll
            //
            ImageInfo.Properties = 0;
            ImageInfo.ImageAddressingMode = IMAGE_ADDRESSING_MODE_32BIT;
            ImageInfo.ImageBase = PsSystemDllBase;
            ImageInfo.ImageSize = 0;
    
            try {
                NtHeaders = RtlImageNtHeader (PsSystemDllBase);
                if ( NtHeaders ) {
    #if defined(_WIN64)
                    if (Wow64Process != NULL) {
                        ImageInfo.ImageSize = DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER ((PIMAGE_NT_HEADERS32)NtHeaders, SizeOfImage);
                    } else {
    #endif
                        ImageInfo.ImageSize = DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER (NtHeaders, SizeOfImage);
    #if defined(_WIN64)
                    }
    #endif
                }
            } except(EXCEPTION_EXECUTE_HANDLER) {
                ImageInfo.ImageSize = 0;
            }
    
            ImageInfo.ImageSelector = 0;
            ImageInfo.ImageSectionNumber = 0;
    
            RtlInitUnicodeString (&UnicodeFileName,
                                  L"\SystemRoot\System32\ntdll.dll");
            PsCallImageNotifyRoutines (&UnicodeFileName,
                                       Process->UniqueProcessId,
                                       &ImageInfo);
        }
    
    
        Port = Process->DebugPort;
    
        if (Port == NULL) {
            return;
        }
    
        //
        // Make sure we only get one create process message
        //
    
        if ((OldFlags&PS_PROCESS_FLAGS_CREATE_REPORTED) == 0) {
    
            //
            // This is a create process
            //
    
            CreateThreadArgs = &m.u.CreateProcessInfo.InitialThread;
            CreateThreadArgs->SubSystemKey = 0;
    
            CreateProcessArgs = &m.u.CreateProcessInfo;
            CreateProcessArgs->SubSystemKey = 0;
            CreateProcessArgs->FileHandle = DbgkpSectionToFileHandle(
                                                Process->SectionObject
                                                );
            CreateProcessArgs->BaseOfImage = Process->SectionBaseAddress;
            CreateThreadArgs->StartAddress = NULL;
            CreateProcessArgs->DebugInfoFileOffset = 0;
            CreateProcessArgs->DebugInfoSize = 0;
    
            try {
                            
                NtHeaders = RtlImageNtHeader(Process->SectionBaseAddress);
    
                if ( NtHeaders ) {
    
    #if defined(_WIN64)
                    if (Wow64Process != NULL) {
                        CreateThreadArgs->StartAddress = UlongToPtr (DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER ((PIMAGE_NT_HEADERS32)NtHeaders, ImageBase) +
                            DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER ((PIMAGE_NT_HEADERS32)NtHeaders, AddressOfEntryPoint));
                    } else {
    #endif
                        CreateThreadArgs->StartAddress = (PVOID) (DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER (NtHeaders, ImageBase) +
                            DBGKP_FIELD_FROM_IMAGE_OPTIONAL_HEADER (NtHeaders, AddressOfEntryPoint));
    #if defined(_WIN64)
                    }
    #endif
    
                    //
                    // The following fields are safe for Wow64 as the offsets
                    // are the same for a PE32+ as a PE32 header.
                    //
                    
                    CreateProcessArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable;
                    CreateProcessArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols;
                }
            } except (EXCEPTION_EXECUTE_HANDLER) {
                CreateThreadArgs->StartAddress = NULL;
                CreateProcessArgs->DebugInfoFileOffset = 0;
                CreateProcessArgs->DebugInfoSize = 0;
            }
    
            DBGKM_FORMAT_API_MSG(m,DbgKmCreateProcessApi,sizeof(*CreateProcessArgs));
    
            DbgkpSendApiMessage(&m,FALSE);
    
            if (CreateProcessArgs->FileHandle != NULL) {
                ObCloseHandle(CreateProcessArgs->FileHandle, KernelMode);
            }
    
            LoadDllArgs = &m.u.LoadDll;
            LoadDllArgs->BaseOfDll = PsSystemDllBase;
            LoadDllArgs->DebugInfoFileOffset = 0;
            LoadDllArgs->DebugInfoSize = 0;
            LoadDllArgs->NamePointer = NULL;
    
            Teb = NULL;
            try {
                NtHeaders = RtlImageNtHeader(PsSystemDllBase);
                if ( NtHeaders ) {
                    LoadDllArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable;
                    LoadDllArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols;
                }
    
                //
                // Normaly the ntdll loaded fills in this pointer for the debug API's. We fake it here
                // as ntdll isn't loaded yet and it can't load itself.
                //
    
                Teb = Thread->Tcb.Teb;
                if (Teb != NULL) {
                    wcsncpy (Teb->StaticUnicodeBuffer,
                             L"ntdll.dll",
                             sizeof (Teb->StaticUnicodeBuffer) / sizeof (Teb->StaticUnicodeBuffer[0]));
                    Teb->NtTib.ArbitraryUserPointer = Teb->StaticUnicodeBuffer;
                    LoadDllArgs->NamePointer = &Teb->NtTib.ArbitraryUserPointer;
                }
                
            } except (EXCEPTION_EXECUTE_HANDLER) {
                LoadDllArgs->DebugInfoFileOffset = 0;
                LoadDllArgs->DebugInfoSize = 0;
                LoadDllArgs->NamePointer = NULL;
            }
    
            //
            // Send load dll section for NT dll !
            //
    
            InitializeObjectAttributes(
                &Obja,
                (PUNICODE_STRING)&PsNtDllPathName,
                OBJ_CASE_INSENSITIVE | OBJ_FORCE_ACCESS_CHECK | OBJ_KERNEL_HANDLE,
                NULL,
                NULL
                );
    
            Status = ZwOpenFile(
                        &LoadDllArgs->FileHandle,
                        (ACCESS_MASK)(GENERIC_READ | SYNCHRONIZE),
                        &Obja,
                        &IoStatusBlock,
                        FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE,
                        FILE_SYNCHRONOUS_IO_NONALERT
                        );
    
            if (!NT_SUCCESS (Status)) {
                LoadDllArgs->FileHandle = NULL;
            }
    
            DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs));
            DbgkpSendApiMessage(&m,TRUE);
    
            if (LoadDllArgs->FileHandle != NULL) {
                ObCloseHandle(LoadDllArgs->FileHandle, KernelMode);
            }
    
            try {
                if (Teb != NULL) {
                    Teb->NtTib.ArbitraryUserPointer = NULL;
                }
            } except (EXCEPTION_EXECUTE_HANDLER) {
            }
    
        } else {
    
            CreateThreadArgs = &m.u.CreateThread;
            CreateThreadArgs->SubSystemKey = 0;
            CreateThreadArgs->StartAddress = StartAddress;
    
            DBGKM_FORMAT_API_MSG (m,DbgKmCreateThreadApi,sizeof(*CreateThreadArgs));
    
            DbgkpSendApiMessage (&m,TRUE);
        }
    }
    

    //退出线程信息 VOID DbgkExitThread( NTSTATUS ExitStatus ) /*++ Routine Description: This function is called when a new thread terminates. At this point, the thread will no longer execute in user-mode. No other exit processing has occured. If a message is sent, then while the thread is awaiting a reply, all other threads in the process are suspended. Arguments: ExitStatus - Supplies the ExitStatus of the exiting thread. Return Value: None. --*/ { PVOID Port; DBGKM_APIMSG m; PDBGKM_EXIT_THREAD args; PEPROCESS Process; BOOLEAN Frozen; PAGED_CODE(); Process = PsGetCurrentProcess(); if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG) { Port = NULL; } else { Port = Process->DebugPort; } if ( !Port ) { return; } if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_DEADTHREAD) { return; } args = &m.u.ExitThread; args->ExitStatus = ExitStatus; DBGKM_FORMAT_API_MSG(m,DbgKmExitThreadApi,sizeof(*args)); Frozen = DbgkpSuspendProcess(); DbgkpSendApiMessage(&m,FALSE); if (Frozen) { DbgkpResumeProcess(); } }
    //退出进程信息 VOID DbgkExitProcess( NTSTATUS ExitStatus ) /*++ Routine Description: This function is called when a process terminates. The address space of the process is still intact, but no threads exist in the process. Arguments: ExitStatus - Supplies the ExitStatus of the exiting process. Return Value: None. --*/ { PVOID Port; DBGKM_APIMSG m; PDBGKM_EXIT_PROCESS args; PEPROCESS Process; PAGED_CODE(); Process = PsGetCurrentProcess(); if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG) { Port = NULL; } else { Port = Process->DebugPort; } if ( !Port ) { return; } if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_DEADTHREAD) { return; } // // this ensures that other timed lockers of the process will bail // since this call is done while holding the process lock, and lock duration // is controlled by debugger // KeQuerySystemTime(&Process->ExitTime); args = &m.u.ExitProcess; args->ExitStatus = ExitStatus; DBGKM_FORMAT_API_MSG(m,DbgKmExitProcessApi,sizeof(*args)); DbgkpSendApiMessage(&m,FALSE); }
    //加载DLL信息 VOID DbgkMapViewOfSection( IN PVOID SectionObject, IN PVOID BaseAddress, IN ULONG SectionOffset, IN ULONG_PTR ViewSize ) /*++ Routine Description: This function is called when the current process successfully maps a view of an image section. If the process has an associated debug port, then a load dll message is sent. Arguments: SectionObject - Supplies a pointer to the section mapped by the process. BaseAddress - Supplies the base address of where the section is mapped in the current process address space. SectionOffset - Supplies the offset in the section where the process' mapped view begins. ViewSize - Supplies the size of the mapped view. Return Value: None. --*/ { PVOID Port; DBGKM_APIMSG m; PDBGKM_LOAD_DLL LoadDllArgs; PEPROCESS Process; PIMAGE_NT_HEADERS NtHeaders; PAGED_CODE(); UNREFERENCED_PARAMETER (SectionOffset); UNREFERENCED_PARAMETER (ViewSize); if ( KeGetPreviousMode() == KernelMode ) { return; } Process = PsGetCurrentProcess(); if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG) { Port = NULL; } else { Port = Process->DebugPort; } if ( !Port ) { return; } LoadDllArgs = &m.u.LoadDll; LoadDllArgs->FileHandle = DbgkpSectionToFileHandle(SectionObject); LoadDllArgs->BaseOfDll = BaseAddress; LoadDllArgs->DebugInfoFileOffset = 0; LoadDllArgs->DebugInfoSize = 0; // // The loader fills in the module name in this pointer before mapping // the section. It's a very poor linkage. // LoadDllArgs->NamePointer = &NtCurrentTeb()->NtTib.ArbitraryUserPointer; try { NtHeaders = RtlImageNtHeader (BaseAddress); if (NtHeaders != NULL) { LoadDllArgs->DebugInfoFileOffset = NtHeaders->FileHeader.PointerToSymbolTable; LoadDllArgs->DebugInfoSize = NtHeaders->FileHeader.NumberOfSymbols; } } except (EXCEPTION_EXECUTE_HANDLER) { LoadDllArgs->DebugInfoFileOffset = 0; LoadDllArgs->DebugInfoSize = 0; LoadDllArgs->NamePointer = NULL; } DBGKM_FORMAT_API_MSG(m,DbgKmLoadDllApi,sizeof(*LoadDllArgs)); DbgkpSendApiMessage(&m,TRUE); if (LoadDllArgs->FileHandle != NULL) { ObCloseHandle(LoadDllArgs->FileHandle, KernelMode); } }
    //卸载DLL信息 VOID DbgkUnMapViewOfSection( IN PVOID BaseAddress ) /*++ Routine Description: This function is called when the current process successfully un maps a view of an image section. If the process has an associated debug port, then an "unmap view of section" message is sent. Arguments: BaseAddress - Supplies the base address of the section being unmapped. Return Value: None. --*/ { PVOID Port; DBGKM_APIMSG m; PDBGKM_UNLOAD_DLL UnloadDllArgs; PAGED_CODE(); if ( KeGetPreviousMode() == KernelMode ) { return; } if (PsGetCurrentThread()->CrossThreadFlags&PS_CROSS_THREAD_FLAGS_HIDEFROMDBG) { Port = NULL; } else { Port = PsGetCurrentProcess()->DebugPort; } if ( !Port ) { return; } UnloadDllArgs = &m.u.UnloadDll; UnloadDllArgs->BaseAddress = BaseAddress; DBGKM_FORMAT_API_MSG(m,DbgKmUnloadDllApi,sizeof(*UnloadDllArgs)); DbgkpSendApiMessage(&m,TRUE); }

      

  • 相关阅读:
    React38路由守卫的实现和使用以及Route的不同渲染方式解析
    React37嵌套路由及路由重定向
    React36react-router的路由传参取参
    ElasticSearch总结3-聚合
    ElasticSearch总结2-高级搜索
    [转]Druid连接池泄露引发的血案!
    Swagger的Starter使用及增强
    MySQL问题排查
    ElasticSearch总结1-查询表达式
    使用Spring Validation优雅地进行参数校验
  • 原文地址:https://www.cnblogs.com/testvt/p/5677073.html
Copyright © 2011-2022 走看看