8Windows概要
8.24 EPROCESS结构
lkd> !process 93c 0 Searching for Process with Cid == 93c Cid Handle table at a84d9000 with 1384 Entries in use PROCESS 8583c318 SessionId: 1 Cid: 093c Peb: 7ffdc000 ParentCid: 0d30 DirBase: ce266920 ObjectTable: baff6238 HandleCount: 69. Image: notepad.exe
其中8586c318即是进程的EPROCESS结构,很多时候windows内核就是用这个指针来代表一个进程的
lkd> dt _EPROCESS 8583c318 nt!_EPROCESS +0x000 Pcb : _KPROCESS //内核进程块,用来记录任务调度有关的信息 +0x098 ProcessLock : _EX_PUSH_LOCK +0x0a0 CreateTime : _LARGE_INTEGER 0x1ce0dc2`1e084500 //创建时间 +0x0a8 ExitTime : _LARGE_INTEGER 0x0//退出时间 +0x0b0 RundownProtect : _EX_RUNDOWN_REF +0x0b4 UniqueProcessId : 0x0000093c //进程ID +0x0b8 ActiveProcessLinks : _LIST_ENTRY [ 0x877c0b00 - 0xc103fba0 ] +0x0c0 ProcessQuotaUsage : [2] 0x111c +0x0c8 ProcessQuotaPeak : [2] 0x1158 +0x0d0 CommitCharge : 0x1db +0x0d4 QuotaBlock : 0x879b7900 _EPROCESS_QUOTA_BLOCK +0x0d8 CpuQuotaBlock : (null) +0x0dc PeakVirtualSize : 0x486f000 +0x0e0 VirtualSize : 0x3f16000 +0x0e4 SessionProcessLinks : _LIST_ENTRY [ 0x877c0b2c - 0xc103fbcc ] +0x0ec DebugPort : (null) //用户态调试端口 +0x0f0 ExceptionPortData : 0x87d34f00 +0x0f0 ExceptionPortValue : 0x87d34f00 +0x0f0 ExceptionPortState : 0y000 +0x0f4 ObjectTable : 0xbaff6238 _HANDLE_TABLE//对象句柄表 +0x0f8 Token : _EX_FAST_REF//访问令牌 +0x0fc WorkingSetPage : 0x3e097 +0x100 AddressCreationLock : _EX_PUSH_LOCK +0x104 RotateInProgress : (null) +0x108 ForkInProgress : (null) +0x10c HardwareTrigger : 0 +0x110 PhysicalVadRoot : (null) +0x114 CloneRoot : (null) +0x118 NumberOfPrivatePages : 0x172 +0x11c NumberOfLockedPages : 0 +0x120 Win32Process : 0xfdeaa970 +0x124 Job : (null) +0x128 SectionObject : 0xbaf6b1b0 +0x12c SectionBaseAddress : 0x008a0000 +0x130 Cookie : 0x6f6a7e43 +0x134 Spare8 : 0 +0x138 WorkingSetWatch : (null) +0x13c Win32WindowStation : 0x00000038 +0x140 InheritedFromUniqueProcessId : 0x00000d30 +0x144 LdtInformation : (null) +0x148 VdmObjects : (null) +0x14c ConsoleHostProcess : 0 +0x150 DeviceMap : 0xa7167b18 +0x154 EtwDataSource : (null) +0x158 FreeTebHint : 0x7ffdf000 +0x160 PageDirectoryPte : _HARDWARE_PTE +0x160 Filler : 0 +0x168 Session : 0x99323000 //所属会话对象 +0x16c ImageFileName : [15] "notepad.exe" +0x17b PriorityClass : 0x2 '' +0x17c JobLinks : _LIST_ENTRY [ 0x0 - 0x0 ] +0x184 LockedPagesList : (null) +0x188 ThreadListHead : _LIST_ENTRY [ 0x882c8298 - 0x882c8298 ] +0x190 SecurityPort : (null) +0x194 PaeTop : 0x86666920 +0x198 ActiveThreads : 1 +0x19c ImagePathHash : 0x3d2afdb4 +0x1a0 DefaultHardErrorProcessing : 1 +0x1a4 LastThreadExitStatus : 0 +0x1a8 Peb : 0x7ffdc000 _PEB //进程环境块 +0x1ac PrefetchTrace : _EX_FAST_REF +0x1b0 ReadOperationCount : _LARGE_INTEGER 0x2c +0x1b8 WriteOperationCount : _LARGE_INTEGER 0x0 +0x1c0 OtherOperationCount : _LARGE_INTEGER 0xfc +0x1c8 ReadTransferCount : _LARGE_INTEGER 0xe1c +0x1d0 WriteTransferCount : _LARGE_INTEGER 0x0 +0x1d8 OtherTransferCount : _LARGE_INTEGER 0x238 +0x1e0 CommitChargeLimit : 0 +0x1e4 CommitChargePeak : 0x1de +0x1e8 AweInfo : (null) +0x1ec SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO +0x1f0 Vm : _MMSUPPORT +0x25c MmProcessLinks : _LIST_ENTRY [ 0x877c0ca4 - 0xc103fd44 ] +0x264 HighestUserAddress : 0x7fff0000 +0x268 ModifiedPageCount : 1 +0x26c Flags2 : 0xd000 +0x26c JobNotReallyActive : 0y0 +0x26c AccountingFolded : 0y0 +0x26c NewProcessReported : 0y0 +0x26c ExitProcessReported : 0y0 +0x26c ReportCommitChanges : 0y0 +0x26c LastReportMemory : 0y0 +0x26c ReportPhysicalPageChanges : 0y0 +0x26c HandleTableRundown : 0y0 +0x26c NeedsHandleRundown : 0y0 +0x26c RefTraceEnabled : 0y0 +0x26c NumaAware : 0y0 +0x26c ProtectedProcess : 0y0 +0x26c DefaultPagePriority : 0y101 +0x26c PrimaryTokenFrozen : 0y1 +0x26c ProcessVerifierTarget : 0y0 +0x26c StackRandomizationDisabled : 0y0 +0x26c AffinityPermanent : 0y0 +0x26c AffinityUpdateEnable : 0y0 +0x26c PropagateNode : 0y0 +0x26c ExplicitAffinity : 0y0 +0x26c Spare1 : 0y0 +0x26c ForceRelocateImages : 0y0 +0x26c DisallowStrippedImages : 0y0 +0x270 Flags : 0x144d0801 +0x270 CreateReported : 0y1 +0x270 NoDebugInherit : 0y0 +0x270 ProcessExiting : 0y0 +0x270 ProcessDelete : 0y0 +0x270 Wow64SplitPages : 0y0 +0x270 VmDeleted : 0y0 +0x270 OutswapEnabled : 0y0 +0x270 Outswapped : 0y0 +0x270 ForkFailed : 0y0 +0x270 Wow64VaSpace4Gb : 0y0 +0x270 AddressSpaceInitialized : 0y10 +0x270 SetTimerResolution : 0y0 +0x270 BreakOnTermination : 0y0 +0x270 DeprioritizeViews : 0y0 +0x270 WriteWatch : 0y0 +0x270 ProcessInSession : 0y1 +0x270 OverrideAddressSpace : 0y0 +0x270 HasAddressSpace : 0y1 +0x270 LaunchPrefetched : 0y1 +0x270 InjectInpageErrors : 0y0 +0x270 VmTopDown : 0y0 +0x270 ImageNotifyDone : 0y1 +0x270 PdeUpdateNeeded : 0y0 +0x270 VdmAllowed : 0y0 +0x270 CrossSessionCreate : 0y0 +0x270 ProcessInserted : 0y1 +0x270 DefaultIoPriority : 0y010 +0x270 ProcessSelfDelete : 0y0 +0x270 SetTimerResolutionLink : 0y0 +0x274 ExitStatus : 259 +0x278 VadRoot : _MM_AVL_TABLE +0x298 AlpcContext : _ALPC_PROCESS_CONTEXT +0x2a8 TimerResolutionLink : _LIST_ENTRY [ 0x0 - 0x0 ] +0x2b0 RequestedTimerResolution : 0 +0x2b4 ActiveThreadsHighWatermark : 1 +0x2b8 SmallestTimerResolution : 0 +0x2bc TimerResolutionStackRecord : (null)
8.25访问令牌
EPROCESS的Token字段记录着这个进程的TOKEN结构的地址,进程的很多与安全相关的信息是记录在这个结构中的,可以使用!Token命令观察其详细信息:
lkd> !token c13ce028 _TOKEN c13ce028 TS Session ID: 0x1 User: S-1-5-21-1333135361-625243220-14044502-183947 Groups: 00 S-1-5-21-1333135361-625243220-14044502-513 Attributes - Mandatory Default Enabled 01 S-1-1-0 Attributes - Mandatory Default Enabled 02 S-1-5-32-544 Attributes - Mandatory Default Enabled Owner 03 S-1-5-32-545 Attributes - Mandatory Default Enabled 04 S-1-5-4 Attributes - Mandatory Default Enabled 05 S-1-2-1 Attributes - Mandatory Default Enabled 06 S-1-5-11 Attributes - Mandatory Default Enabled 07 S-1-5-15 Attributes - Mandatory Default Enabled 08 S-1-5-5-0-591336 Attributes - Mandatory Default Enabled LogonId
8.26PEB
PEB是在内核态建立后映射到用户空间的,因此,在一个系统中,多个进程的PEB地址可能是同一个值
8.210父进程ID
Parent Cid是父进程的进程ID,即创建该进程的那个进程的进程ID
8.31访问模式
当调用系统服务时,调用线程会从用户模式切换到内核模式,调用结束后再返回到用户模式,也就所谓的模式切换,有时也称为上下文切换(Context Switch)在生个线程的KTRHREAD结构中,有一个名为ContextSwitches的字段,专门用来记灵这个线程的模式切换次数,
8.32使用INT 2E切换到内核模式
我们看下windows2K下ReadFile的调用过程,
ReadFile()->ntDll.dll!NtReadFIle->int 2e进入nt!KiSystemService,KiSystemService会根据服务ID从系统服务分发表中查找到要调用的服务函数地址和参数描述,然后把参数从用户态栈复制到该线程的内核栈中,最后KiSystemService调用内核中真正的NtReadFile函数,执行读文件的操作,操作结束后会返回到KiSystemService,KiSytemService会把操作结果复制回该线程用户态栈,最后通过IRET指令将执行权交回给ntdll.dll中的ntReadFile函数
当然,在win7下是通过sysenter取代int 2e
0:004> uf ntdll!ZwReadFile ntdll!NtReadFile: 771162b8 b811010000 mov eax,111h 771162bd ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 771162c2 ff12 call dword ptr [edx] 771162c4 c22400 ret 24h 0:004> dd 7ffe0300 7ffe0300 77117090 77117094 00000000 00000000 7ffe0310 00000000 00000000 00000000 00000000 7ffe0320 000a4760 00000000 00000000 00000000 7ffe0330 67d4ee40 00000000 000011a0 00000000 7ffe0340 00000000 00000000 00000000 00000000 7ffe0350 00000000 00000000 00000000 00000000 7ffe0360 00000000 00000000 00000000 00000000 7ffe0370 00000000 00000000 00000000 00000000 0:004> uf 77117090 ntdll!KiFastSystemCall: 77117090 8bd4 mov edx,esp 77117092 0f34 sysenter 77117094 c3 retSYSENTER/SYSEXIT这对指令专门用于实现快速调用。在这之前是采用INT 0x2E来实现的。INT 0x2E在系统调用的时候,需要进行栈切换的工作。由于Interrupt/Exception Handler的调用都是通过 call/trap/task这一类的gate来实现的,这种方式会进行栈切换,并且系统栈的地址等信息由TSS提供。这种方式可能会引起多次内存访问 (来获取这些切换信息),因此,从PentiumII开始,IA-32引入了新指令:SYSENTER/SYSEXIT。 有了这两条指令,
从用户级到特权级的堆栈以及指令指针的转换,可以通过这一条指令来实现
8.3.3快速系统调用
1.在GDT中建立4个段描述符,分别用来描述供SYSENTER指令进入内核模式时使用的代码段(CS)和栈段,以及SYSEXIT指令从内核模式返回用户模式时使用的代码段(CS)和栈段(SS)
2.设置专门用于系统调用的MSR寄存器,SYSENTER_EIP_MSR用于指定新的程序指针,也就是SYSENTER指令要跳转的目标例程地址,windows会将其设置为KiFastCallEntry地址,因为KiFastCallEntry例程是windows内核专门用来受理快速系统调用的.SYSENTER_CS_MSR用于指定新的代码段,也就是KiFastCallEntry所在的代码段,SYSENTER_ESP_MSR用来指定新的栈指针(ESP),新的栈段是由SYSENTER_CS_MSR的值加8得来的
3.将一小段名为SystemCallStub的代码复制到SharedUserData内存区,该内存区会被映射到每个win32进程的进程空间,这样,当应用程序每次进行系统调用时,ntdll中的残根函数便调用这段SystemCallStub代码
以下为SYSENTER指令使用的MSR寄存器:
lkd> rdmsr 174 msr[174] = 00000000`00000008 lkd> rdmsr 175 msr[175] = 00000000`8078b000 lkd> rdmsr 176 msr[176] = 00000000`82c84770SYSTENTER_EIP_MSR用于对付如下值.
lkd> ln 82c84770 (82c84770) nt!KiFastCallEntry | (82c848f0) nt!KiServiceExit Exact matches: nt!KiFastCallEntry = <no type information>可见windows把快速系统调用的目目标指向的是内核代码段中的KiFastCallEntry函数.(注意这是内核层的KiFastCallEntry)
0:004> u ntdll!NtReadFile ntdll!NtReadFile: 77a262b8 b811010000 mov eax,111h 77a262bd ba0003fe7f mov edx,offset SharedUserData!SystemCallStub (7ffe0300) 77a262c2 ff12 call dword ptr [edx] 77a262c4 c22400 ret 24h 77a262c7 90 nop
0:004> dd 7ffe0300 7ffe0300 77a27090 77a27094 00000000 00000000 7ffe0310 00000000 00000000 00000000 00000000 7ffe0320 0001455b 00000000 00000000 00000000 7ffe0330 9abe1e74 00000000 00001468 00000000 7ffe0340 00000000 00000000 00000000 00000000 7ffe0350 00000000 00000000 00000000 00000000 7ffe0360 00000000 00000000 00000000 00000000 7ffe0370 00000000 00000000 00000000 00000000 0:004> uf 77a27090 ntdll!KiFastSystemCall: 77a27090 8bd4 mov edx,esp 77a27092 0f34 sysenter 77a27094 c3 ret可见先调用的的确是KiFastSystemCall例程(这是用户层的,对应通过sysenter调用了内核层的nt!KiFastSystemCall)
8.34逆向调用
首先内核代码使用内核函数KiCallUserMode发起调用,接下来的执行过程与从系统调用返回(kiServiecExit)时类似,不过进入用户态时执行的是NtDll中的KiUserCallBackDispatcher,而后KiUserCallBackDispatcher会调用内核希望调用的用户态函数,当用户态的工作完成后,执行返回动作的函数会执行INT 2B指令,也就是触发一个0X2B异常,这个属常的处理函数是内核态的KiCallBackReturn函数,于是,通过INT2B异常,CPU又跳回到内核态继续执行了.
lkd> !idt 2b Dumping IDT: 2b: 82c84e70 nt!KiCallbackReturn
8.44系统和IDLE进程
1.此两进程没有对应的磁盘映像文件,是在系统启动时“捏造”出来的
2.此两个进程只在内核态中执行,没有用户态
3.固定的进程ID,IDLE进程ID为0,系统进程ID为4
8.45用户空间
会话管理器进程(SMSS.EXE)是系统中第一个根据映像文件创建的进程,是在系统启动后期由执行体的初始化函数创建的,它运行后,会加载和初始化win32子系统的内核模块Win32K.sys,创建win32子系统服务器进程(CSRSS.exe),并创建登录进程(WinLogon.exe)
进程文件: smss or smss.exe 进程名称: Session Manager Subsystem
进程文件: csrss 或者 csrss.exe 进程名称: Microsoft Client/Server Runtime Server Subsystem(客户/服务器(运行时)子系统)windows子系统服务器进程(csrss.exe)负责维护windows子系统的“日常事务”,为子系统中的各进程提供服务
登陆进程(WinLogon.exe)负责用户登陆和安全有关的事务,它启动后,会创建LSASS进程和系统服务管理进程(Services.exe)
本地安全和认证进程(LSASS.exe)负责用户身份验证,(local security Authority Subsytem Service)
服务管理进程(Services.exe),负责启动和管理系统服务程序
壳程序(Shell),默认为Explorer.exe,负责显示开始菜单,任务栏和桌面图标等