|
|
[bgcolor=#ffffff]这是Windows Internals第6章的内容。发现描述的还算详细。读了总比不读强。于是纪录之,老鸟飘过----[/bgcolor]
[bgcolor=#ffffff]<一> 进程相关[/bgcolor]
[bgcolor=#ffffff]EPROCESS算是进程的代表,它还保留着与之相关的其他信息。进程是死的,其中的线程才是活的。进程就好比一个容器,装着很多活跃的线程而已[没有线程的进程注定要死亡,因为它没有活力]。对了,还有PEB、TEB[这2个结构存在于用户进程空间中,其他的都在系统的高2GB地址范围里] 。见图:[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffff00]① 明确KPCR、KPRCB、ETHREAD、KTHREAD、EPROCESS、KPROCESS、TEB、PEB ----[/bgcolor]
[bgcolor=#ffffff]KPCR[/bgcolor][bgcolor=#ffffff](Kernel's Processor Control Region,[/bgcolor][bgcolor=#ffffff]内核进程控制区域[/bgcolor][bgcolor=#ffffff])是一个不会随WINDOWS版本变动而改变的固定结构体,在它的末尾[偏移[/bgcolor][bgcolor=#ffffff]0x120[/bgcolor][bgcolor=#ffffff]]指向[/bgcolor][bgcolor=#ffffff]KPRCB[/bgcolor][bgcolor=#ffffff]结构。[/bgcolor]
[bgcolor=#ffffff]nt!_KPCR[/bgcolor]
[bgcolor=#ffffff] +0x000 NtTib : _NT_TIB[/bgcolor]
[bgcolor=#ffffff] +0x01c SelfPcr : Ptr32 _KPCR[/bgcolor]
[bgcolor=#ffffff] +0x020 Prcb : Ptr32 _KPRCB[/bgcolor]
[bgcolor=#ffffff] +0x024 Irql : UChar[/bgcolor]
[bgcolor=#ffffff] +0x028 IRR : Uint4B[/bgcolor]
[bgcolor=#ffffff] +0x02c IrrActive : Uint4B[/bgcolor]
[bgcolor=#ffffff] +0x030 IDR : Uint4B[/bgcolor]
[bgcolor=#ffffff] +0x034 KdVersionBlock : Ptr32 Void[/bgcolor]
[bgcolor=#ffffff] +0x038 IDT : Ptr32 _KIDTENTRY[/bgcolor]
[bgcolor=#ffffff] +0x03c GDT : Ptr32 _KGDTENTRY[/bgcolor]
[bgcolor=#ffffff] +0x040 TSS : Ptr32 _KTSS[/bgcolor]
[bgcolor=#ffffff] ...// 省略[/bgcolor]
[bgcolor=#ffffff] +0x120 PrcbData : _KPRCB[/bgcolor]
[bgcolor=#ffffff]KPRCB[/bgcolor][bgcolor=#ffffff]同样是一个不会随WINDOWS版本变动而改变的固定结构体。它包含有指向当前[/bgcolor][bgcolor=#ffffff]KTHREAD[/bgcolor][bgcolor=#ffffff]的指针,偏移值[/bgcolor][bgcolor=#ffffff]0x004[/bgcolor][bgcolor=#ffffff]。其实也就是知道了当前的[/bgcolor][bgcolor=#ffffff]ETHREAD[/bgcolor][bgcolor=#ffffff]基地址。[因为ETHREAD的第一项便是KTHREAD,ETHREAD在后面讨论,现在讨论进程相关] [通过 [/bgcolor][bgcolor=#ffffff]KeGetCurrentPrcb()[/bgcolor][bgcolor=#ffffff] 函数即可得到PKPRCB,具体参见WRK][/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]展开KTHREAD,其中的_KAPC_STATE结构中包含当前KPROCESS的地址[/bgcolor]
[bgcolor=#ffffff]nt!_KTHREAD[/bgcolor]
[bgcolor=#ffffff] +0x000 Header : _DISPATCHER_HEADER[/bgcolor]
[bgcolor=#ffffff] ...[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]+0x034 ApcState : _KAPC_STATE[/bgcolor]
[bgcolor=#ffffff]+0x034 ApcState : struct _KAPC_STATE, 5 elements, 0x18 bytes[/bgcolor]
[bgcolor=#ffffff] +0x000 ApcListHead : [2] struct _LIST_ENTRY, 2 elements, 0x8 bytes[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]+0x010 Process[/bgcolor][bgcolor=#ffffff] : Ptr32 to struct [/bgcolor][bgcolor=#ffffff]_KPROCESS[/bgcolor][bgcolor=#ffffff], 29 elements, 0x6c bytes[/bgcolor]
[bgcolor=#ffffff] +0x014 KernelApcInProgress : UChar[/bgcolor]
[bgcolor=#ffffff] +0x015 KernelApcPending : UChar[/bgcolor]
[bgcolor=#ffffff] +0x016 UserApcPending : UChar[/bgcolor]
[bgcolor=#ffffff]而EPROCESS的第一项正是KPROCESS。联想我们熟悉的断EPROCESS链表隐藏进程的手法。通过[/bgcolor][bgcolor=#ffffff]PsGetCurrentProcess[/bgcolor][bgcolor=#ffffff]得到的其实是当前KPROCESS的地址,而KPROCESS就是EPROCESS结构体的第一项,这样就得到了当前的EPROCESS。然后遍历整个链表。。。[/bgcolor]
[bgcolor=#ffffff]---->>大致流程:[/bgcolor][bgcolor=#ffffff]PsGetCurrentProcess()函数---->_PsGetCurrentProcess()宏----->KeGetCurrentThread()函数[/bgcolor]
[bgcolor=#ffffff]---->>具体细节:[/bgcolor]
[bgcolor=#ffffff]#define _PsGetCurrentProcess() (CONTAINING_RECORD(((KeGetCurrentThread())->ApcState.Process),EPROCESS,Pcb))[/bgcolor]
[bgcolor=#ffffff]// 很明显,KeGetCurrentThread()得到KTHREAD结构体,KTHREAD偏移0x034处的
// ApcState中process即为EPROCESS的第一项KPROCESS的地址。CONTAINING_RECORD宏
// 将此地址减去它在EPROCESS中的偏移值,得到当前EPROCESS的实际地址[/bgcolor]
[bgcolor=#ffffff]FORCEINLINE[/bgcolor]
[bgcolor=#ffffff]struct _KTHREAD *[/bgcolor]
[bgcolor=#ffffff]NTAPI KeGetCurrentThread (VOID)[/bgcolor]
[bgcolor=#ffffff]{[/bgcolor]
[bgcolor=#ffffff]#if (_MSC_FULL_VER >= 13012035)[/bgcolor]
[bgcolor=#ffffff] return (struct _KTHREAD *) (ULONG_PTR) __readfsdword (FIELD_OFFSET (KPCR, PrcbData.CurrentThread));[/bgcolor]
[bgcolor=#ffffff]#else[/bgcolor]
[bgcolor=#ffffff] __asm { mov eax, fs:[0] KPCR.PrcbData.CurrentThread }[/bgcolor]
[bgcolor=#ffffff]#endif[/bgcolor]
[bgcolor=#ffffff]}[/bgcolor]
[bgcolor=#ffffff]// fs在用户模式下指向TEB结构,在内核模式下指向KPCR[前面第一个描述的结构体][/bgcolor]
[bgcolor=#ffffff]呵呵,偶画个图更直观些,也更方便记忆[/bgcolor][bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]关于[/bgcolor][bgcolor=#ffffff]KPROCESS[/bgcolor][bgcolor=#ffffff]。里面保存了一些有用的信息,我们来简单的瞅下。[/bgcolor]
[bgcolor=#ffffff]nt!_KPROCESS[/bgcolor]
[bgcolor=#ffffff] +0x000 Header : _DISPATCHER_HEADER[/bgcolor]
[bgcolor=#ffffff] +0x010 ProfileListHead : _LIST_ENTRY[/bgcolor]
[bgcolor=#ffffff] +0x018 [/bgcolor][bgcolor=#ffffff]DirectoryTableBase[/bgcolor][bgcolor=#ffffff] : [2] Uint4B [/bgcolor][bgcolor=#ffffff]// 进程的页目录PDT [涉及内存管理知识]
[/bgcolor][bgcolor=#ffffff] +0x020 [/bgcolor][bgcolor=#ffffff]LdtDescriptor[/bgcolor][bgcolor=#ffffff] : _KGDTENTRY [/bgcolor][bgcolor=#ffffff]// GDT的入口
[/bgcolor][bgcolor=#ffffff] +0x028 [/bgcolor][bgcolor=#ffffff]Int21Descriptor[/bgcolor][bgcolor=#ffffff] : _KIDTENTRY [/bgcolor][bgcolor=#ffffff]// IDT的入口[/bgcolor]
[bgcolor=#ffffff] +0x030 IopmOffset : Uint2B[/bgcolor]
[bgcolor=#ffffff] +0x032 Iopl : UChar[/bgcolor]
[bgcolor=#ffffff] +0x033 Unused : UChar[/bgcolor]
[bgcolor=#ffffff] +0x034 ActiveProcessors : Uint4B[/bgcolor]
[bgcolor=#ffffff] +0x038 KernelTime : Uint4B[/bgcolor]
[bgcolor=#ffffff] +0x03c UserTime : Uint4B[/bgcolor]
[bgcolor=#ffffff] +0x040 ReadyListHead : _LIST_ENTRY[/bgcolor]
[bgcolor=#ffffff] +0x048 SwapListEntry : _SINGLE_LIST_ENTRY[/bgcolor]
[bgcolor=#ffffff] +0x04c VdmTrapcHandler : Ptr32 Void[/bgcolor]
[bgcolor=#ffffff] +0x050 [/bgcolor][bgcolor=#ffffff]ThreadListHead[/bgcolor][bgcolor=#ffffff] : _LIST_ENTRY [/bgcolor][bgcolor=#ffffff]// 指向KTHREAD链[/bgcolor]
[bgcolor=#ffffff] +0x058 ProcessLock : Uint4B[/bgcolor]
[bgcolor=#ffffff] +0x05c Affinity : Uint4B[/bgcolor]
[bgcolor=#ffffff] +0x060 StackCount : Uint2B[/bgcolor]
[bgcolor=#ffffff] +0x062 BasePriority : Char[/bgcolor]
[bgcolor=#ffffff] +0x063 ThreadQuantum : Char[/bgcolor]
[bgcolor=#ffffff] +0x064 AutoAlignment : UChar[/bgcolor]
[bgcolor=#ffffff] +0x065 State : UChar[/bgcolor]
[bgcolor=#ffffff] +0x066 ThreadSeed : UChar[/bgcolor]
[bgcolor=#ffffff] +0x067 DisableBoost : UChar[/bgcolor]
[bgcolor=#ffffff] +0x068 PowerState : UChar[/bgcolor]
[bgcolor=#ffffff] +0x069 DisableQuantum : UChar[/bgcolor]
[bgcolor=#ffffff] +0x06a IdealNode : UChar[/bgcolor]
[bgcolor=#ffffff] +0x06b Flags : _KEXECUTE_OPTIONS[/bgcolor]
[bgcolor=#ffffff] +0x06b ExecuteOptions : UChar[/bgcolor]
[bgcolor=#ffffff]PEB[/bgcolor][bgcolor=#ffffff]是很有用的东西,写shellcode、定位EPROCESS等都可以用到它。PEB在EPROCESS偏移0x1b0处[/bgcolor]
[bgcolor=#ffffff]nt!_EPROCESS[/bgcolor]
[bgcolor=#ffffff] +0x000 Pcb : _KPROCESS[/bgcolor]
[bgcolor=#ffffff] ...[/bgcolor]
[bgcolor=#ffffff] +0x084 UniqueProcessId : Ptr32 Void[/bgcolor]
[bgcolor=#ffffff] +0x088 ActiveProcessLinks : _LIST_ENTRY[/bgcolor]
[bgcolor=#ffffff] ...[/bgcolor]
[bgcolor=#ffffff] +0x160 PhysicalVadList : _LIST_ENTRY[/bgcolor]
[bgcolor=#ffffff] +0x168 PageDirectoryPte : _HARDWARE_PTE[/bgcolor]
[bgcolor=#ffffff] ...[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]+0x1b0 Peb : Ptr32 _PEB[/bgcolor]
[bgcolor=#ffffff] ...[/bgcolor]
[bgcolor=#ffffff]---->>获得PEB的地址是非常简单的。可以通过EPROCESS的偏移,也可以用硬编码实现[不同进程的PEB高位都是一样的][/bgcolor]
[bgcolor=#ffffff]xor esi, esi ; FS寄存器 -> TEB结构,TEB+0x30 -> PEB结构[/bgcolor]
[bgcolor=#ffffff]mov esi, fs:[esi + 30H] ; 而PEB中包含有_PEB_LDR_DATA。通过一系列的[/bgcolor]
[bgcolor=#ffffff]mov eax, esi ; 偏移可以定位到Kernel32.dll基地址。。。[/bgcolor]
[bgcolor=#ffffff]ret ; 呵呵,参看gz1X大虾的文章:[/bgcolor]WIN下获取kernel基址的shellcode探讨
[bgcolor=#ffffff]当然可以直接用Windbg来查看当前的PEB的结构 lkd>dt _peb[/bgcolor]
[bgcolor=#ffffff]lkd> !peb[/bgcolor]
[bgcolor=#ffffff]PEB at 7ffdc000 [/bgcolor][bgcolor=#ffffff]//高位都是7ffd
[/bgcolor][bgcolor=#ffffff] InheritedAddressSpace: No[/bgcolor]
[bgcolor=#ffffff] ReadImageFileExecOptions: No[/bgcolor]
[bgcolor=#ffffff] BeingDebugged: No[/bgcolor]
[bgcolor=#ffffff] ImageBaseAddress: 01000000[/bgcolor]
[bgcolor=#ffffff] Ldr 00191e90[/bgcolor]
[bgcolor=#ffffff] Ldr.Initialized: Yes[/bgcolor]
[bgcolor=#ffffff] Ldr.InInitializationOrderModuleList: 00191f28 . 00193330[/bgcolor]
[bgcolor=#ffffff] Ldr.InLoadOrderModuleList: 00191ec0 . 00193320[/bgcolor]
[bgcolor=#ffffff] Ldr.InMemoryOrderModuleList: 00191ec8 . 00193328[/bgcolor]
[bgcolor=#ffffff] ...// 省略[/bgcolor]
[bgcolor=#ffff00]② 与进程相关的一些内核变量、计数、函数 ----[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]关于PspCidTable参见gz1X大虾的:[/bgcolor]基于pspCidTable的进程检测技术
[bgcolor=#ffffff]这些变量的申明保存在WRK的[/bgcolor][bgcolor=#ffffff]Psinit.c[/bgcolor][bgcolor=#ffffff]中。先看下[/bgcolor][bgcolor=#ffffff]PspCreateProcess[/bgcolor][bgcolor=#ffffff]的参数[/bgcolor]
[bgcolor=#ffffff]PspCreateProcess([/bgcolor]
[bgcolor=#ffffff] OUT PHANDLE ProcessHandle,[/bgcolor]
[bgcolor=#ffffff] IN ACCESS_MASK DesiredAccess,[/bgcolor]
[bgcolor=#ffffff] IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,[/bgcolor]
[bgcolor=#ffffff] IN HANDLE ParentProcess OPTIONAL, [/bgcolor][bgcolor=#ffffff]//如果没有指定,表明此进程没有父进程。是系统进程[/bgcolor]
[bgcolor=#ffffff] IN ULONG Flags,[/bgcolor]
[bgcolor=#ffffff] IN HANDLE SectionHandle OPTIONAL,[/bgcolor]
[bgcolor=#ffffff] IN HANDLE DebugPort OPTIONAL,[/bgcolor]
[bgcolor=#ffffff] IN HANDLE ExceptionPort OPTIONAL,[/bgcolor]
[bgcolor=#ffffff] IN ULONG JobMemberLevel[/bgcolor]
[bgcolor=#ffffff] )[/bgcolor]
[bgcolor=#ffffff]系统启动时,[/bgcolor][bgcolor=#ffffff]PspInitPhase0()[/bgcolor][bgcolor=#ffffff] 函数会做很多事情,这里只是例举与上图全局变量相关的细节:[/bgcolor]
[bgcolor=#ffffff]初始化Queue header:[/bgcolor][bgcolor=#ffffff]InitializeListHead[/bgcolor][bgcolor=#ffffff](& sActiveProcessHead);[/bgcolor]
[bgcolor=#ffffff]初始化PsIdleProcess[这个是系统进程的EPROCESS][/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]创建系统进程,并且把系统进程的EPROCESS保存在[/bgcolor][bgcolor=#ffffff]PsInitialSystemProcess[/bgcolor][bgcolor=#ffffff]中。见代码:[/bgcolor]
[bgcolor=#ffffff]InitializeObjectAttributes (&ObjectAttributes,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] 0,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] NULL);[/bgcolor]
[bgcolor=#ffffff] if (!NT_SUCCESS (PspCreateProcess (& spInitialSystemProcessHandle,[/bgcolor]
[bgcolor=#ffffff] PROCESS_ALL_ACCESS,[/bgcolor]
[bgcolor=#ffffff] &ObjectAttributes,[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]NULL, // 注意这里。没有指定,所以创建的是系统进程
[/bgcolor][bgcolor=#ffffff] 0,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] 0))) {[/bgcolor]
[bgcolor=#ffffff] return FALSE;[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] if (!NT_SUCCESS (ObReferenceObjectByHandle (PspInitialSystemProcessHandle,[/bgcolor]
[bgcolor=#ffffff] 0L,[/bgcolor]
[bgcolor=#ffffff] PsProcessType,[/bgcolor]
[bgcolor=#ffffff] KernelMode,[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]& sInitialSystemProcess[/bgcolor][bgcolor=#ffffff], // 系统的EPROCESS保存于此[/bgcolor]
[bgcolor=#ffffff] NULL))) {[/bgcolor]
[bgcolor=#ffffff] return FALSE;[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] strcpy((char *) & sIdleProcess->ImageFileName[0], "Idle");[/bgcolor]
[bgcolor=#ffffff] strcpy((char *) & sInitialSystemProcess->ImageFileName[0], "System");[/bgcolor]
[bgcolor=#ffffff]// EPROCESS OFFEST+0x1f4 SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO[/bgcolor]
[bgcolor=#ffffff] PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName =[/bgcolor]
[bgcolor=#ffffff] ExAllocatePoolWithTag (PagedPool, [/bgcolor]
[bgcolor=#ffffff] sizeof(OBJECT_NAME_INFORMATION), [/bgcolor]
[bgcolor=#ffffff] 'aPeS');[/bgcolor]
[bgcolor=#ffffff] if (PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName != NULL) {[/bgcolor]
[bgcolor=#ffffff] RtlZeroMemory (PsInitialSystemProcess->SeAuditProcessCreationInfo.ImageFileName, [/bgcolor]
[bgcolor=#ffffff] sizeof (OBJECT_NAME_INFORMATION));[/bgcolor]
[bgcolor=#ffffff] } else {[/bgcolor]
[bgcolor=#ffffff] return FALSE;[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff]下面几个全局变量定义在WRK的[/bgcolor][bgcolor=#ffffff]Psp.h[/bgcolor][bgcolor=#ffffff]文件中:[/bgcolor]
[bgcolor=#ffffff]ULONG PspCreateProcessNotifyRoutineCount;[/bgcolor]
[bgcolor=#ffffff]EX_CALLBACK PspCreateProcessNotifyRoutine[8];[/bgcolor]
[bgcolor=#ffffff]ULONG PspLoadImageNotifyRoutineCount;[/bgcolor]
[bgcolor=#ffffff]EX_CALLBACK PspLoadImageNotifyRoutine[8];[/bgcolor]
[bgcolor=#ffffff]extern PHANDLE_TABLE PspCidTable;[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]相关的函数就更多了,具体请参见原版WINDWOS INTERNALS 6[附件里有][/bgcolor]
[bgcolor=#ffff00]③ 一个进程的诞生,CreateProcess的步骤 ----[/bgcolor]
[bgcolor=#ffffff]用户程序可以调用[/bgcolor][bgcolor=#ffffff]CreateProcess、CreateProcessAsUser、CreateProcessWithTokenWor、CreateProcessWithLogonW[/bgcolor][bgcolor=#ffffff]创建进程。而进程的创建主要由3部分参合进来完成的:[/bgcolor][bgcolor=#ffffff]Kernel32.dll、the Windows executive、子系统进程CSRSS.exe。[/bgcolor]
[bgcolor=#ffffff]CreateProcess创建进程的大致步骤:
1.打开文件[.exe]。
2.创建进程内核对象
3.在进程中创建线程[堆栈、线程上下文、线程内核对象]
4.通知WINDOWS子系统已经创建了一个新进程,便于它进一步的初始化
5.如果标致不是CREATE_ SUSPENDED,那么就开始执行进程中的线程
6.在进程和线程的context里,完成地址空间的初始化[eg.加载需要的DLL],开始执行程序[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]CreateProcess在打开文件运行之前,会检查参数中的flags,决定如何设置新进程的优先级。[/bgcolor]
[bgcolor=#ffffff]---->> stage 1: 打开并运行文件<<----[/bgcolor]
[bgcolor=#ffffff]如果是PE文件,直接运行;如果不是PE格式,系统根据相应的格式选择相应的加载措施:[/bgcolor]
[bgcolor=#ffffff] POSIX的程序 -- 调用 Posix.exe[/bgcolor]
[bgcolor=#ffffff] OS/2 1.x的程序 -- 调用 Os2.exe[/bgcolor]
[bgcolor=#ffffff] .bat/.cmd的程序 -- 调用 Cmd.exe[/bgcolor]
[bgcolor=#ffffff] 16位/MS-DOS .exe/.com/.pif -- 调用 Ntvdm.exe[/bgcolor]
[bgcolor=#ffffff]如果还是不能加载,CreateProcess就会失败.[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]与Ntvdm.exe相关的注册表在HKLM\SYSTEM\CurrentControlSet\Control\WOW下 [/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff]到此,CreateProcess已经成功的打开了一个有效的文件,并且为它创建了一个section object。但并没有映射到内存中,仅仅是打开了而已。a section object被成功的创建了并不能说明此文件是一个有效的Windows image,因为文件可能是DLL或者POSIX。[/bgcolor]
[bgcolor=#ffffff]接着检查注册表[/bgcolor][bgcolor=#ffffff]IFEO[/bgcolor][bgcolor=#ffffff],系统如果发现某个程序文件在IFEO列表中,它就会首先来读取Debugger参数,如果该参数不为空,系统则会把Debugger参数里指定的程序文件名作为用户试图启动的程序执行请求来处理,而仅仅把用户试图启动的程序作为Debugger参数里指定的程序文件名的参数发送过去。 联想到了很久的映像劫持病毒。[/bgcolor]
[bgcolor=#ffffff]---->> stage 2: 创建进程内核对象<<----[/bgcolor]
[bgcolor=#ffffff]CreateProcess-->NtCreateProcess-->NtCreateProcessEx--> spCreateProcess来创建进程内核对象[/bgcolor][bgcolor=#ffffff]。如下:[/bgcolor]
[bgcolor=#ffffff]1.设置EPROCESS[/bgcolor]
[bgcolor=#ffffff]2.创建进程地址空间[/bgcolor]
[bgcolor=#ffffff]3.初始化KPROCESS // 偶在源码里面没有找到耶,太多了,反正没找到[/bgcolor]
[bgcolor=#ffffff]4.完成进程地址空间的设置 // 原文中写着此时Ntdll.dll被映射到进程地址空间中[/bgcolor]
[bgcolor=#ffffff]5.设置PEB [/bgcolor]
[bgcolor=#ffffff]6.完成进程内核对象的创建,审核收尾工作[/bgcolor]
[bgcolor=#ffffff]----- stage2.1 设置EPROCESS-----[/bgcolor]
[bgcolor=#ffffff]1.>创建EPROCESS[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]//系统在启动时在PspInitPhase0()中初始化进程/线程对象的对象类型[Object types][/bgcolor]
[bgcolor=#ffffff] // Create Object types for Thread and Process Objects.[/bgcolor]
[bgcolor=#ffffff] RtlInitUnicodeString (&NameString, L" rocess");[/bgcolor]
[bgcolor=#ffffff] ObjectTypeInitializer.DefaultPagedPoolCharge = PSP_PROCESS_PAGED_CHARGE;[/bgcolor]
[bgcolor=#ffffff] ObjectTypeInitializer.DefaultNonPagedPoolCharge = PSP_PROCESS_NONPAGED_CHARGE;[/bgcolor]
[bgcolor=#ffffff] ObjectTypeInitializer.DeleteProcedure = PspProcessDelete;[/bgcolor]
[bgcolor=#ffffff] ObjectTypeInitializer.ValidAccessMask = PROCESS_ALL_ACCESS;[/bgcolor]
[bgcolor=#ffffff] ObjectTypeInitializer.GenericMapping = PspProcessMapping;[/bgcolor]
[bgcolor=#ffffff] if (!NT_SUCCESS ([/bgcolor][bgcolor=#ffffff]ObCreateObjectType[/bgcolor][bgcolor=#ffffff] (&NameString,[/bgcolor]
[bgcolor=#ffffff] &ObjectTypeInitializer,[/bgcolor]
[bgcolor=#ffffff] (PSECURITY_DESCRIPTOR) NULL,[/bgcolor]
[bgcolor=#ffffff] & sProcessType))) {[/bgcolor]
[bgcolor=#ffffff] return FALSE; [/bgcolor][bgcolor=#ffffff]// PsProcessType是在Psinit.c中定义的全局变量 POBJECT_TYPE PsProcessType;
[/bgcolor][bgcolor=#ffffff] } [/bgcolor][bgcolor=#ffffff] // 用它来保存对象类型的信息[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]// 函数PspCreateProcess中创建EPROCESS[/bgcolor]
[bgcolor=#ffffff] // Create the process object[/bgcolor]
[bgcolor=#ffffff] Status =[/bgcolor][bgcolor=#ffffff] ObCreateObject[/bgcolor][bgcolor=#ffffff] (PreviousMode, [/bgcolor][bgcolor=#ffffff]// PreviousMode = KeGetPreviousModeByThread(&CurrentThread->Tcb);
[/bgcolor][bgcolor=#ffffff] PsProcessType, [/bgcolor][bgcolor=#ffffff]// 就是上面描述的那个全局变量
[/bgcolor][bgcolor=#ffffff] ObjectAttributes, [/bgcolor][bgcolor=#ffffff]// 函数的参数[/bgcolor]
[bgcolor=#ffffff] PreviousMode,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] sizeof (EPROCESS),[/bgcolor]
[bgcolor=#ffffff] 0,[/bgcolor]
[bgcolor=#ffffff] 0,[/bgcolor]
[bgcolor=#ffffff] & rocess); [/bgcolor][bgcolor=#ffffff]// 创建后的EPROCESS保存在此[/bgcolor]
[bgcolor=#ffffff] RtlZeroMemory (Process, sizeof(EPROCESS));[/bgcolor]
[bgcolor=#ffffff] ExInitializeRundownProtection (& rocess->RundownProtect);[/bgcolor]
[bgcolor=#ffffff] PspInitializeProcessLock (Process);[/bgcolor]
[bgcolor=#ffffff] InitializeListHead (&Process->ThreadListHead);[/bgcolor]
[bgcolor=#ffffff]2.> 设置进程Working set size的最值[20-45][/bgcolor]
[bgcolor=#ffffff]WorkingSetMinimum = PsMinimumWorkingSet; // 20[/bgcolor]
[bgcolor=#ffffff]WorkingSetMaximum = PsMaximumWorkingSet; // 45[/bgcolor]
[bgcolor=#ffffff]3.> 从父进程那里继承一些属性[略过][/bgcolor]
[bgcolor=#ffffff]----- stage2.2 创建进程地址空间-----[/bgcolor]
[bgcolor=#ffffff]1.> page directory 即是PDT相关。 嘿嘿,想必大家都看过操作系统之类的书,上面介绍的有关内存管理的东西必须好好的看[/bgcolor]
[bgcolor=#ffffff]前置知识是必须充分了解[/bgcolor][bgcolor=#ffffff]JT、MBT、PMT、PMTR、PTE、PDE[/bgcolor][bgcolor=#ffffff]等其中页表(PTE映射在系统高2GB中--0xC0000000~0xC03FFFFF的4MB空间,页目录映射在0xC0300000~...)[/bgcolor]
[bgcolor=#ffffff]PS: 进程的地址空间分为4种:[/bgcolor]
[bgcolor=#ffffff] 1. [/bgcolor][bgcolor=#ffffff]Boot Process[/bgcolor][bgcolor=#ffffff]--Address space is initialized during MmInit. Parent is not specified[/bgcolor]
[bgcolor=#ffffff] 2. [/bgcolor][bgcolor=#ffffff]System Process[/bgcolor][bgcolor=#ffffff]--系统地址空间,看看前面介绍的这个全局变量PspInitialSystemProcess,熟悉了吧[/bgcolor]
[bgcolor=#ffffff] 3. [/bgcolor][bgcolor=#ffffff]User Process (Cloned Address Space)[/bgcolor][bgcolor=#ffffff] 从指定的进程复制的[/bgcolor]
[bgcolor=#ffffff] 4. [/bgcolor][bgcolor=#ffffff]User Process (New Image Address Space)[/bgcolor][bgcolor=#ffffff] 新的[/bgcolor]
[bgcolor=#ffffff]------------------------------------------------------[/bgcolor]
[bgcolor=#ffffff]if (SectionHandle != NULL) {[/bgcolor]
[bgcolor=#ffffff] // User Process (New Image Address Space).[/bgcolor]
[bgcolor=#ffffff] Status = [/bgcolor][bgcolor=#ffffff]MmInitializeProcessAddressSpace [/bgcolor][bgcolor=#ffffff](Process,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] SectionObject,[/bgcolor]
[bgcolor=#ffffff] &Flags,[/bgcolor]
[bgcolor=#ffffff] &(Process->SeAuditProcessCreationInfo.ImageFileName));[/bgcolor]
[bgcolor=#ffffff]...//省略[/bgcolor]
[bgcolor=#ffffff] } else if (Parent != NULL) { [/bgcolor][bgcolor=#ffffff]//如果存在父进程[/bgcolor]
[bgcolor=#ffffff] if (Parent != PsInitialSystemProcess) { [/bgcolor][bgcolor=#ffffff]// 如果父进程不是系统进程,说明是一个普通的父进程创建的[/bgcolor]
[bgcolor=#ffffff] Process->SectionBaseAddress = Parent->SectionBaseAddress;[/bgcolor]
[bgcolor=#ffffff] // User Process ( Cloned Address Space )[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] Status = MmInitializeProcessAddressSpace (Process,[/bgcolor]
[bgcolor=#ffffff] Parent,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] &Flags,[/bgcolor]
[bgcolor=#ffffff] NULL);[/bgcolor]
[bgcolor=#ffffff] // A cloned process isn't started from an image file, so we give it the name[/bgcolor]
[bgcolor=#ffffff] // of the process of which it is a clone, provided the original has a name.[/bgcolor]
[bgcolor=#ffffff] // 暂时不重要,省略掉[/bgcolor]
[bgcolor=#ffffff] } else {[/bgcolor]
[bgcolor=#ffffff] // System Process[/bgcolor]
[bgcolor=#ffffff] Flags &= ~PROCESS_CREATE_FLAGS_ALL_LARGE_PAGE_FLAGS;[/bgcolor]
[bgcolor=#ffffff] Status = MmInitializeProcessAddressSpace (Process,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] NULL,[/bgcolor]
[bgcolor=#ffffff] &Flags,[/bgcolor]
[bgcolor=#ffffff] NULL);[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff]2.> Hyperspace page[/bgcolor]
[bgcolor=#ffffff]3.> Working set list[/bgcolor]
[bgcolor=#ffffff]----- stage2.5 设置PEB----[/bgcolor]
[bgcolor=#ffffff]if (Parent && CreatePeb) {[/bgcolor]
[bgcolor=#ffffff] RtlZeroMemory (&InitialPeb, FIELD_OFFSET(INITIAL_PEB, Mutant));[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]// PspCreateProcess中申明的局部变量 INITIAL_PEB InitialPeb;
[/bgcolor][bgcolor=#ffffff] InitialPeb.Mutant = (HANDLE)(-1);[/bgcolor]
[bgcolor=#ffffff] InitialPeb.ImageUsesLargePages = (BOOLEAN) UseLargePages;[/bgcolor]
[bgcolor=#ffffff] [/bgcolor]
[bgcolor=#ffffff] if (SectionHandle != NULL) { [/bgcolor][bgcolor=#ffffff]// 如果要创建新的进程.PEB也得从新创建
[/bgcolor][bgcolor=#ffffff] Status =[/bgcolor][bgcolor=#ffffff] MmCreatePeb[/bgcolor][bgcolor=#ffffff] (Process, &InitialPeb, &Process->Peb);[/bgcolor]
[bgcolor=#ffffff] Peb = Process->Peb;[/bgcolor]
[bgcolor=#ffffff] } else { [/bgcolor][bgcolor=#ffffff]// 如果是CLONE进程,PEB只要从父进程里面拷贝一份就可以了
[/bgcolor][bgcolor=#ffffff] SIZE_T BytesCopied;[/bgcolor]
[bgcolor=#ffffff] InitialPeb.InheritedAddressSpace = TRUE;[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]Process->Peb = Parent->Peb;[/bgcolor]
[bgcolor=#ffffff] [/bgcolor][bgcolor=#ffffff]MmCopyVirtualMemory [/bgcolor][bgcolor=#ffffff](CurrentProcess,[/bgcolor]
[bgcolor=#ffffff] &InitialPeb,[/bgcolor]
[bgcolor=#ffffff] Process,[/bgcolor]
[bgcolor=#ffffff] Process->Peb,[/bgcolor]
[bgcolor=#ffffff] sizeof (INITIAL_PEB),[/bgcolor]
[bgcolor=#ffffff] KernelMode,[/bgcolor]
[bgcolor=#ffffff] &BytesCopied);[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff] Peb = Process->Peb;[/bgcolor]
[bgcolor=#ffffff]----- stage2.6 完成进程内核对象的创建-----[/bgcolor]
[bgcolor=#ffffff]1.> Audit the process creation[/bgcolor]
[bgcolor=#ffffff]if (SeDetailedAuditingWithToken (NULL)) {[/bgcolor]
[bgcolor=#ffffff] SeAuditProcessCreation (Process); // Process为当前的EPROCESS[/bgcolor]
[bgcolor=#ffffff] }[/bgcolor]
[bgcolor=#ffffff]2.> See if the parent has a job. If so reference the job and add the process in.[/bgcolor]
[bgcolor=#ffffff]3.> 将EPROCESS插入的系统的active process链表中 [联想的断链和复制链][/bgcolor]
[bgcolor=#ffffff] PspLockProcessList (CurrentThread);[/bgcolor]
[bgcolor=#ffffff] InsertTailList (&PsActiveProcessHead, &Process->ActiveProcessLinks);[/bgcolor]
[bgcolor=#ffffff] PspUnlockProcessList (CurrentThread);[/bgcolor]
[bgcolor=#ffffff]4.> 线程创建的时间被设定,然后当线程的句柄可用的时候,返回到最初的调用者CreateProcess中[Kernel32.dll][/bgcolor] |
|