《软件调试 Windows概要》
操作系统是计算机系统中的基本软件。它负责管理系统中的软硬件资源。通常都包括文件管理、内存管理、进程管理、打印管理、网络管理等基本功能。除此之外,支持调试也是操作系统设计的一项根本任务。
0x01 进程和进程空间
进程和程序的关系好比是类和实例的关系,运行一个程序时,操作系统就为这个程序创建一个实例。一个程序可以有多个实例在运行。
操作系统角度的进程称为一个task,而一个进程可以包含多个线程,CPU一级的任务可以看成是Windows系统下每个进程中的一个线程,在这个层面上看,Windows操作系统的一个任务对应CPU的一个或多个任务。
为了保证系统中每个任务或进程的安全,Windows为不同的进程分配了独立的进程空间(process space).进程空间是操作系统分配给每个进程的虚拟地址空间(virtual space address).对于32位的x86系统,每个进程的地址空间是4GB,,即地址0x00000000到地址0xFFFFFFFF。
为了高效地调用和执行操作系统的各种服务,Windows将操作系统的内核数据和代码映射到系统中所有的进程空间中,4G的进程空间因此被划分为两个区域:用户空间和系统空间.x86下,用户空间和系统空间默认大小为2GB,低2GB未用户空间,高2GB为系统空间。
0x02 进程资源
除了虚拟地址空间之外每个进程还拥有:
一:一个全局唯一的进程ID 。
二:一个可执行映像(image),也就是该进程的程序文件(可执行文件)在内存中的表示。
三:一个或多个线程。
四:一个位于内核空间中的名为EPROCESS数据结构(进程执行块)。用以记录该进程的关键信息,包括进程创建时间、映像文件名称等。
五:一个位于内核空间的对象句柄表。用以记录和索引该进程所创建的或打开的内核对象。句柄只是句柄表的索引,操作系统根据句柄表来得到指向内核对象的指针。
六:一个用于描述内存页目录表起始位置的基地址。简称页目录基地址。当cpu切换任务时会将该地址加载到CR3寄存器中。
七:一个位于用户空间中的环境块(Process Environment block)PEB。
八:一个访问权限令牌(access token)。用以表示该进程的用户 、安全组以及优先级别
0x03 EPROCESS结构
kd> dt _eprocess dtx is unsupported for this scenario. It only recognizes dtx [<type>] [<address>] with -a, -h, and -r. Reverting to dt. ntdll!_EPROCESS +0x000 Pcb : _KPROCESS //内核进程块,记录任务调度相关信息 +0x098 ProcessLock : _EX_PUSH_LOCK +0x0a0 CreateTime : _LARGE_INTEGER //创建时间 +0x0a8 ExitTime : _LARGE_INTEGER //退出时间 +0x0b0 RundownProtect : _EX_RUNDOWN_REF +0x0b4 UniqueProcessId : Ptr32 Void //进程ID +0x0b8 ActiveProcessLinks : _LIST_ENTRY +0x0c0 ProcessQuotaUsage : [2] Uint4B +0x0c8 ProcessQuotaPeak : [2] Uint4B +0x0d0 CommitCharge : Uint4B +0x0d4 QuotaBlock : Ptr32 _EPROCESS_QUOTA_BLOCK +0x0d8 CpuQuotaBlock : Ptr32 _PS_CPU_QUOTA_BLOCK +0x0dc PeakVirtualSize : Uint4B +0x0e0 VirtualSize : Uint4B +0x0e4 SessionProcessLinks : _LIST_ENTRY +0x0ec DebugPort : Ptr32 Void +0x0f0 ExceptionPortData : Ptr32 Void +0x0f0 ExceptionPortValue : Uint4B +0x0f0 ExceptionPortState : Pos 0, 3 Bits +0x0f4 ObjectTable : Ptr32 _HANDLE_TABLE//对象句柄表 +0x0f8 Token : _EX_FAST_REF //访问令牌,安全相关信息 +0x0fc WorkingSetPage : Uint4B +0x100 AddressCreationLock : _EX_PUSH_LOCK +0x104 RotateInProgress : Ptr32 _ETHREAD +0x108 ForkInProgress : Ptr32 _ETHREAD +0x10c HardwareTrigger : Uint4B +0x110 PhysicalVadRoot : Ptr32 _MM_AVL_TABLE +0x114 CloneRoot : Ptr32 Void +0x118 NumberOfPrivatePages : Uint4B +0x11c NumberOfLockedPages : Uint4B +0x120 Win32Process : Ptr32 Void +0x124 Job : Ptr32 _EJOB +0x128 SectionObject : Ptr32 Void +0x12c SectionBaseAddress : Ptr32 Void +0x130 Cookie : Uint4B +0x134 Spare8 : Uint4B +0x138 WorkingSetWatch : Ptr32 _PAGEFAULT_HISTORY +0x13c Win32WindowStation : Ptr32 Void +0x140 InheritedFromUniqueProcessId : Ptr32 Void +0x144 LdtInformation : Ptr32 Void +0x148 VdmObjects : Ptr32 Void +0x14c ConsoleHostProcess : Uint4B +0x150 DeviceMap : Ptr32 Void +0x154 EtwDataSource : Ptr32 Void +0x158 FreeTebHint : Ptr32 Void +0x160 PageDirectoryPte : _HARDWARE_PTE_X86 +0x160 Filler : Uint8B +0x168 Session : Ptr32 Void +0x16c ImageFileName : [15] UChar +0x17b PriorityClass : UChar +0x17c JobLinks : _LIST_ENTRY +0x184 LockedPagesList : Ptr32 Void +0x188 ThreadListHead : _LIST_ENTRY //线程链表 +0x190 SecurityPort : Ptr32 Void +0x194 PaeTop : Ptr32 Void +0x198 ActiveThreads : Uint4B +0x19c ImagePathHash : Uint4B +0x1a0 DefaultHardErrorProcessing : Uint4B +0x1a4 LastThreadExitStatus : Int4B +0x1a8 Peb : Ptr32 _PEB //进程环境块 +0x1ac PrefetchTrace : _EX_FAST_REF +0x1b0 ReadOperationCount : _LARGE_INTEGER +0x1b8 WriteOperationCount : _LARGE_INTEGER +0x1c0 OtherOperationCount : _LARGE_INTEGER +0x1c8 ReadTransferCount : _LARGE_INTEGER +0x1d0 WriteTransferCount : _LARGE_INTEGER +0x1d8 OtherTransferCount : _LARGE_INTEGER +0x1e0 CommitChargeLimit : Uint4B +0x1e4 CommitChargePeak : Uint4B +0x1e8 AweInfo : Ptr32 Void +0x1ec SeAuditProcessCreationInfo : _SE_AUDIT_PROCESS_CREATION_INFO +0x1f0 Vm : _MMSUPPORT +0x25c MmProcessLinks : _LIST_ENTRY +0x264 HighestUserAddress : Ptr32 Void +0x268 ModifiedPageCount : Uint4B +0x26c Flags2 : Uint4B +0x26c JobNotReallyActive : Pos 0, 1 Bit +0x26c AccountingFolded : Pos 1, 1 Bit +0x26c NewProcessReported : Pos 2, 1 Bit +0x26c ExitProcessReported : Pos 3, 1 Bit +0x26c ReportCommitChanges : Pos 4, 1 Bit +0x26c LastReportMemory : Pos 5, 1 Bit +0x26c ReportPhysicalPageChanges : Pos 6, 1 Bit +0x26c HandleTableRundown : Pos 7, 1 Bit +0x26c NeedsHandleRundown : Pos 8, 1 Bit +0x26c RefTraceEnabled : Pos 9, 1 Bit +0x26c NumaAware : Pos 10, 1 Bit +0x26c ProtectedProcess : Pos 11, 1 Bit +0x26c DefaultPagePriority : Pos 12, 3 Bits +0x26c PrimaryTokenFrozen : Pos 15, 1 Bit +0x26c ProcessVerifierTarget : Pos 16, 1 Bit +0x26c StackRandomizationDisabled : Pos 17, 1 Bit +0x26c AffinityPermanent : Pos 18, 1 Bit +0x26c AffinityUpdateEnable : Pos 19, 1 Bit +0x26c PropagateNode : Pos 20, 1 Bit +0x26c ExplicitAffinity : Pos 21, 1 Bit +0x26c Spare1 : Pos 22, 1 Bit +0x26c ForceRelocateImages : Pos 23, 1 Bit +0x26c DisallowStrippedImages : Pos 24, 1 Bit +0x26c LowVaAccessible : Pos 25, 1 Bit +0x270 Flags : Uint4B +0x270 CreateReported : Pos 0, 1 Bit +0x270 NoDebugInherit : Pos 1, 1 Bit +0x270 ProcessExiting : Pos 2, 1 Bit +0x270 ProcessDelete : Pos 3, 1 Bit +0x270 Wow64SplitPages : Pos 4, 1 Bit +0x270 VmDeleted : Pos 5, 1 Bit +0x270 OutswapEnabled : Pos 6, 1 Bit +0x270 Outswapped : Pos 7, 1 Bit +0x270 ForkFailed : Pos 8, 1 Bit +0x270 Wow64VaSpace4Gb : Pos 9, 1 Bit +0x270 AddressSpaceInitialized : Pos 10, 2 Bits +0x270 SetTimerResolution : Pos 12, 1 Bit +0x270 BreakOnTermination : Pos 13, 1 Bit +0x270 DeprioritizeViews : Pos 14, 1 Bit +0x270 WriteWatch : Pos 15, 1 Bit +0x270 ProcessInSession : Pos 16, 1 Bit +0x270 OverrideAddressSpace : Pos 17, 1 Bit +0x270 HasAddressSpace : Pos 18, 1 Bit +0x270 LaunchPrefetched : Pos 19, 1 Bit +0x270 InjectInpageErrors : Pos 20, 1 Bit +0x270 VmTopDown : Pos 21, 1 Bit +0x270 ImageNotifyDone : Pos 22, 1 Bit +0x270 PdeUpdateNeeded : Pos 23, 1 Bit +0x270 VdmAllowed : Pos 24, 1 Bit +0x270 CrossSessionCreate : Pos 25, 1 Bit +0x270 ProcessInserted : Pos 26, 1 Bit +0x270 DefaultIoPriority : Pos 27, 3 Bits +0x270 ProcessSelfDelete : Pos 30, 1 Bit +0x270 SetTimerResolutionLink : Pos 31, 1 Bit +0x274 ExitStatus : Int4B +0x278 VadRoot : _MM_AVL_TABLE +0x298 AlpcContext : _ALPC_PROCESS_CONTEXT +0x2a8 TimerResolutionLink : _LIST_ENTRY +0x2b0 RequestedTimerResolution : Uint4B +0x2b4 ActiveThreadsHighWatermark : Uint4B +0x2b8 SmallestTimerResolution : Uint4B +0x2bc TimerResolutionStackRecord : Ptr32 _PO_DIAG_STACK_RECORD
0x04 PEB 进程环境块(win7 x86)
PEB是内核态建立后映射到用户空间的,因此在一个系统中多个进程的虚拟空间可能是同一个值。
kd> dt _peb dtx is unsupported for this scenario. It only recognizes dtx [<type>] [<address>] with -a, -h, and -r. Reverting to dt. ntdll!_PEB +0x000 InheritedAddressSpace : UChar +0x001 ReadImageFileExecOptions : UChar +0x002 BeingDebugged : UChar //是否在被调试 +0x003 BitField : UChar +0x003 ImageUsesLargePages : Pos 0, 1 Bit//执行映像的基地址 +0x003 IsProtectedProcess : Pos 1, 1 Bit +0x003 IsLegacyProcess : Pos 2, 1 Bit +0x003 IsImageDynamicallyRelocated : Pos 3, 1 Bit +0x003 SkipPatchingUser32Forwarders : Pos 4, 1 Bit +0x003 SpareBits : Pos 5, 3 Bits +0x004 Mutant : Ptr32 Void +0x008 ImageBaseAddress : Ptr32 Void +0x00c Ldr : Ptr32 _PEB_LDR_DATA +0x010 ProcessParameters : Ptr32 _RTL_USER_PROCESS_PARAMETERS +0x014 SubSystemData : Ptr32 Void +0x018 ProcessHeap : Ptr32 Void //进程堆 +0x01c FastPebLock : Ptr32 _RTL_CRITICAL_SECTION +0x020 AtlThunkSListPtr : Ptr32 Void +0x024 IFEOKey : Ptr32 Void +0x028 CrossProcessFlags : Uint4B +0x028 ProcessInJob : Pos 0, 1 Bit +0x028 ProcessInitializing : Pos 1, 1 Bit +0x028 ProcessUsingVEH : Pos 2, 1 Bit +0x028 ProcessUsingVCH : Pos 3, 1 Bit +0x028 ProcessUsingFTH : Pos 4, 1 Bit +0x028 ReservedBits0 : Pos 5, 27 Bits +0x02c KernelCallbackTable : Ptr32 Void +0x02c UserSharedInfoPtr : Ptr32 Void +0x030 SystemReserved : [1] Uint4B +0x034 AtlThunkSListPtr32 : Uint4B +0x038 ApiSetMap : Ptr32 Void +0x03c TlsExpansionCounter : Uint4B +0x040 TlsBitmap : Ptr32 Void +0x044 TlsBitmapBits : [2] Uint4B +0x04c ReadOnlySharedMemoryBase : Ptr32 Void +0x050 HotpatchInformation : Ptr32 Void +0x054 ReadOnlyStaticServerData : Ptr32 Ptr32 Void +0x058 AnsiCodePageData : Ptr32 Void +0x05c OemCodePageData : Ptr32 Void +0x060 UnicodeCaseTableData : Ptr32 Void +0x064 NumberOfProcessors : Uint4B //CPU个数 +0x068 NtGlobalFlag : Uint4B +0x070 CriticalSectionTimeout : _LARGE_INTEGER +0x078 HeapSegmentReserve : Uint4B //默认进程堆的总保留空间 +0x07c HeapSegmentCommit : Uint4B //默认进程堆已提交空间 +0x080 HeapDeCommitTotalFreeThreshold : Uint4B +0x084 HeapDeCommitFreeBlockThreshold : Uint4B +0x088 NumberOfHeaps : Uint4B //堆个数 +0x08c MaximumNumberOfHeaps : Uint4B //堆的最多个数 +0x090 ProcessHeaps : Ptr32 Ptr32 Void +0x094 GdiSharedHandleTable : Ptr32 Void +0x098 ProcessStarterHelper : Ptr32 Void +0x09c GdiDCAttributeList : Uint4B +0x0a0 LoaderLock : Ptr32 _RTL_CRITICAL_SECTION +0x0a4 OSMajorVersion : Uint4B //操作系统主版本号 +0x0a8 OSMinorVersion : Uint4B +0x0ac OSBuildNumber : Uint2B +0x0ae OSCSDVersion : Uint2B +0x0b0 OSPlatformId : Uint4B +0x0b4 ImageSubsystem : Uint4B +0x0b8 ImageSubsystemMajorVersion : Uint4B +0x0bc ImageSubsystemMinorVersion : Uint4B +0x0c0 ActiveProcessAffinityMask : Uint4B +0x0c4 GdiHandleBuffer : [34] Uint4B +0x14c PostProcessInitRoutine : Ptr32 void +0x150 TlsExpansionBitmap : Ptr32 Void +0x154 TlsExpansionBitmapBits : [32] Uint4B +0x1d4 SessionId : Uint4B +0x1d8 AppCompatFlags : _ULARGE_INTEGER +0x1e0 AppCompatFlagsUser : _ULARGE_INTEGER +0x1e8 pShimData : Ptr32 Void +0x1ec AppCompatInfo : Ptr32 Void +0x1f0 CSDVersion : _UNICODE_STRING +0x1f8 ActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +0x1fc ProcessAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +0x200 SystemDefaultActivationContextData : Ptr32 _ACTIVATION_CONTEXT_DATA +0x204 SystemAssemblyStorageMap : Ptr32 _ASSEMBLY_STORAGE_MAP +0x208 MinimumStackCommit : Uint4B +0x20c FlsCallback : Ptr32 _FLS_CALLBACK_INFO +0x210 FlsListHead : _LIST_ENTRY +0x218 FlsBitmap : Ptr32 Void +0x21c FlsBitmapBits : [4] Uint4B +0x22c FlsHighIndex : Uint4B +0x230 WerRegistrationData : Ptr32 Void +0x234 WerShipAssertPtr : Ptr32 Void +0x238 pContextData : Ptr32 Void +0x23c pImageHeaderHash : Ptr32 Void +0x240 TracingFlags : Uint4B +0x240 HeapTracingEnabled : Pos 0, 1 Bit +0x240 CritSecTracingEnabled : Pos 1, 1 Bit +0x240 SpareTracingBits : Pos 2, 30 Bits
0x05 ID 页目录地址
进程ID
进程ID是用以标识进程的整数。很多用户态API使用它作为参数。在内核态主要使用_EPROCESS结构地址来标识一个进程。
父进程ID
即创建当前进程的进程ID。
页目录地址
DirBase代表该进程的页目录基地址。即任务切换时CR3寄存器的内容。它是将虚拟地址翻译为物理地址的必须参数。页目录是按4KB对齐的,因此在DirBase只保存了高20位的地址。
0x06 内核模式用户模式
Windows利用权限控制来保护映射到进程虚拟地址空间中的系统空间。
Windows定义了两种访问模式:用户模式和内核模式。应用程序代码运行在用户模式下,操作系统代码运行在内核模式下。
内核模式对应处理器的最高权限级别(Ring0)。在内核模式下执行的代码可以访问所有资源并可以执行所有特权指令。用户模式具有较低的优先级(Ring3),用户模式只能访问用户空间,且不能执行特权指令。
如果用户代码不慎访问了系统空间的数据或执行了特权指令将会导致保护性异常的发生。但是用户代码可以通过调用系统服务来间接的访问系统空间中的数据或间接执行系统空间中的代码。当调用系统服务时,调用线程会从用户模式切换到内核模式,调用结束后再返回用户代码。这就是所谓的模式切换。
在每个线程的_KTHREAD结构中定义了UserTime和KernelTme两个字段,分别记录这个线程在用户模式和内核模式运行的时间。
0x07 INT 2E 与 快速系统调用