WindowsAPI编程核心技术-栈和函数调用
什么是栈
每个普通用户进程都有俩栈,一个为内核态栈记录在_KTHREAD结构中,另一个为用户态栈记录在_TEB结构中。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207
| 0: kd> .thread Implicit thread is now fffff804`09b27600 0: kd> dt nt!_KTHREAD fffff804`09b27600 +0x000 Header : _DISPATCHER_HEADER +0x018 SListFaultAddress : (null) +0x020 QuantumTarget : 0x791ddc0 +0x028 InitialStack : 0xfffff804`0ba7fc90 Void //原栈顶位置 内核态代码逆向调用用户态代码时使用 +0x030 StackLimit : 0xfffff804`0ba7a000 Void //内核态栈边界 即StackBase-内核态栈大小 +0x038 StackBase : 0xfffff804`0ba80000 Void //内核态栈基地址 +0x040 ThreadLock : 0 +0x048 CycleTime : 0x0000033e`caa858aa +0x050 CurrentRunTime : 0xffffffff +0x054 ExpectedRunTime : 0 +0x058 KernelStack : 0xfffff804`0ba7fc20 Void //内核态栈的栈顶地址 +0x060 StateSaveArea : 0xfffff804`0ba7fcc0 _XSAVE_FORMAT +0x068 SchedulingGroup : (null) +0x070 WaitRegister : _KWAIT_STATUS_REGISTER +0x071 Running : 0x1 '' +0x072 Alerted : [2] "" +0x074 AutoBoostActive : 0y1 +0x074 ReadyTransition : 0y0 +0x074 WaitNext : 0y0 +0x074 SystemAffinityActive : 0y1 +0x074 Alertable : 0y0 +0x074 UserStackWalkActive : 0y0 +0x074 ApcInterruptRequest : 0y0 +0x074 QuantumEndMigrate : 0y0 +0x074 UmsDirectedSwitchEnable : 0y0 +0x074 TimerActive : 0y0 +0x074 SystemThread : 0y1 +0x074 ProcessDetachActive : 0y0 +0x074 CalloutActive : 0y0 +0x074 ScbReadyQueue : 0y0 +0x074 ApcQueueable : 0y0 +0x074 ReservedStackInUse : 0y0 +0x074 UmsPerformingSyscall : 0y0 +0x074 TimerSuspended : 0y0 +0x074 SuspendedWaitMode : 0y0 +0x074 SuspendSchedulerApcWait : 0y0 +0x074 CetUserShadowStack : 0y0 +0x074 BypassProcessFreeze : 0y0 +0x074 Reserved : 0y0000000000 (0) +0x074 MiscFlags : 0n1033 +0x078 ThreadFlagsSpare : 0y00 +0x078 AutoAlignment : 0y1 +0x078 DisableBoost : 0y0 +0x078 AlertedByThreadId : 0y0 +0x078 QuantumDonation : 0y0 +0x078 EnableStackSwap : 0y1 +0x078 GuiThread : 0y0 +0x078 DisableQuantum : 0y0 +0x078 ChargeOnlySchedulingGroup : 0y0 +0x078 DeferPreemption : 0y0 +0x078 QueueDeferPreemption : 0y0 +0x078 ForceDeferSchedule : 0y0 +0x078 SharedReadyQueueAffinity : 0y0 +0x078 FreezeCount : 0y0 +0x078 TerminationApcRequest : 0y0 +0x078 AutoBoostEntriesExhausted : 0y0 +0x078 KernelStackResident : 0y1 //内核态栈是否位于物理内存中 +0x078 TerminateRequestReason : 0y00 +0x078 ProcessStackCountDecremented : 0y0 +0x078 RestrictedGuiThread : 0y0 +0x078 VpBackingThread : 0y0 +0x078 ThreadFlagsSpare2 : 0y0 +0x078 EtwStackTraceApcInserted : 0y00000000 (0) +0x078 ThreadFlags : 0n131140 +0x07c Tag : 0 '' +0x07d SystemHeteroCpuPolicy : 0 '' +0x07e UserHeteroCpuPolicy : 0y0001000 (0x8) +0x07e ExplicitSystemHeteroCpuPolicy : 0y0 +0x07f RunningNonRetpolineCode : 0y0 +0x07f SpecCtrlSpare : 0y0000000 (0) +0x07f SpecCtrl : 0 '' +0x080 SystemCallNumber : 0 +0x084 ReadyTime : 0 +0x088 FirstArgument : (null) +0x090 TrapFrame : (null) +0x098 ApcState : _KAPC_STATE +0x098 ApcStateFill : [43] "???" +0x0c3 Priority : 0 '' +0x0c4 UserIdealProcessor : 0 +0x0c8 WaitStatus : 0n0 +0x0d0 WaitBlockList : (null) +0x0d8 WaitListEntry : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ] +0x0d8 SwapListEntry : _SINGLE_LIST_ENTRY +0x0e8 Queue : (null) +0x0f0 Teb : (null) +0x0f8 RelativeTimerBias : 0 +0x100 Timer : _KTIMER +0x140 WaitBlock : [4] _KWAIT_BLOCK +0x140 WaitBlockFill4 : [20] "" +0x154 ContextSwitches : 0x140fe +0x140 WaitBlockFill5 : [68] "" +0x184 State : 0x2 '' +0x185 Spare13 : 0 '' +0x186 WaitIrql : 0x2 '' +0x187 WaitMode : 0 '' +0x140 WaitBlockFill6 : [116] "" +0x1b4 WaitTime : 0x16c30 +0x140 WaitBlockFill7 : [164] "" +0x1e4 KernelApcDisable : 0n0 +0x1e6 SpecialApcDisable : 0n0 +0x1e4 CombinedApcDisable : 0 +0x140 WaitBlockFill8 : [40] "" +0x168 ThreadCounters : (null) +0x140 WaitBlockFill9 : [88] "" +0x198 XStateSave : (null) +0x140 WaitBlockFill10 : [136] "" +0x1c8 Win32Thread : (null) +0x140 WaitBlockFill11 : [176] "" +0x1f0 Ucb : (null) +0x1f8 Uch : (null) +0x200 ThreadFlags2 : 0n0 +0x200 BamQosLevel : 0y00000000 (0) +0x200 ThreadFlags2Reserved : 0y000000000000000000000000 (0) +0x204 Spare21 : 0 +0x208 QueueListEntry : _LIST_ENTRY [ 0x00000000`00000000 - 0x00000000`00000000 ] +0x218 NextProcessor : 0 +0x218 NextProcessorNumber : 0y0000000000000000000000000000000 (0) +0x218 SharedReadyQueue : 0y0 +0x21c QueuePriority : 0n0 +0x220 Process : 0xfffff804`09b24a00 _KPROCESS +0x228 UserAffinity : _GROUP_AFFINITY +0x228 UserAffinityFill : [10] "???" +0x232 PreviousMode : 0 '' +0x233 BasePriority : 0 '' +0x234 PriorityDecrement : 0 '' +0x234 ForegroundBoost : 0y0000 +0x234 UnusualBoost : 0y0000 +0x235 Preempted : 0 '' +0x236 AdjustReason : 0 '' +0x237 AdjustIncrement : 0 '' +0x238 AffinityVersion : 0x18 +0x240 Affinity : _GROUP_AFFINITY +0x240 AffinityFill : [10] "???" +0x24a ApcStateIndex : 0x1 '' +0x24b WaitBlockCount : 0 '' +0x24c IdealProcessor : 0 +0x250 NpxState : 4 +0x258 SavedApcState : _KAPC_STATE +0x258 SavedApcStateFill : [43] "Xx???" +0x283 WaitReason : 0x19 '' +0x284 SuspendCount : 0 '' +0x285 Saturation : 0 '' +0x286 SListFaultCount : 0 +0x288 SchedulerApc : _KAPC +0x288 SchedulerApcFill0 : [1] "??????" +0x289 ResourceIndex : 0x2 '' +0x288 SchedulerApcFill1 : [3] "???" +0x28b QuantumReset : 0x7f '' +0x288 SchedulerApcFill2 : [4] "???" +0x28c KernelTime : 0x17b9b +0x288 SchedulerApcFill3 : [64] "???" +0x2c8 WaitPrcb : (null) +0x288 SchedulerApcFill4 : [72] "???" +0x2d0 LegoData : (null) +0x288 SchedulerApcFill5 : [83] "???" +0x2db CallbackNestingLevel : 0 '' +0x2dc UserTime : 0 +0x2e0 SuspendEvent : _KEVENT +0x2f8 ThreadListEntry : _LIST_ENTRY [ 0xffffbc81`52e72438 - 0xfffff804`09b24a30 ] +0x308 MutantListHead : _LIST_ENTRY [ 0xfffff804`09b27908 - 0xfffff804`09b27908 ] +0x318 AbEntrySummary : 0x3f '?' +0x319 AbWaitEntryCount : 0 '' +0x31a AbAllocationRegionCount : 0 '' +0x31b SystemPriority : 0 '' +0x31c SecureThreadCookie : 0 +0x320 LockEntries : 0xfffff804`09b27c50 _KLOCK_ENTRY +0x328 PropagateBoostsEntry : _SINGLE_LIST_ENTRY +0x330 IoSelfBoostsEntry : _SINGLE_LIST_ENTRY +0x338 PriorityFloorCounts : [16] "" +0x348 PriorityFloorCountsReserved : [16] "" +0x358 PriorityFloorSummary : 0 +0x35c AbCompletedIoBoostCount : 0n0 +0x360 AbCompletedIoQoSBoostCount : 0n0 +0x364 KeReferenceCount : 0n0 +0x366 AbOrphanedEntrySummary : 0 '' +0x367 AbOwnedEntryCount : 0 '' +0x368 ForegroundLossTime : 0 +0x370 GlobalForegroundListEntry : _LIST_ENTRY [ 0x00000000`00000001 - 0x00000000`00000000 ] +0x370 ForegroundDpcStackListEntry : _SINGLE_LIST_ENTRY +0x378 InGlobalForegroundList : 0 +0x380 ReadOperationCount : 0n0 +0x388 WriteOperationCount : 0n0 +0x390 OtherOperationCount : 0n0 +0x398 ReadTransferCount : 0n0 +0x3a0 WriteTransferCount : 0n0 +0x3a8 OtherTransferCount : 0n0 +0x3b0 QueuedScb : (null) +0x3b8 ThreadTimerDelay : 0 +0x3bc ThreadFlags3 : 0n0 +0x3bc ThreadFlags3Reserved : 0y00000000 (0) +0x3bc PpmPolicy : 0y00 +0x3bc ThreadFlags3Reserved2 : 0y0000000000000000000000 (0) +0x3c0 TracingPrivate : [1] 0 +0x3c8 SchedulerAssist : (null) +0x3d0 AbWaitObject : (null) +0x3d8 ReservedPreviousReadyTimeValue : 0 +0x3e0 KernelWaitTime : 0 +0x3e8 UserWaitTime : 0 +0x3f0 GlobalUpdateVpThreadPriorityListEntry : _LIST_ENTRY [ 0x00000000`00000001 - 0x00000000`00000000 ] +0x3f0 UpdateVpThreadPriorityDpcStackListEntry : _SINGLE_LIST_ENTRY +0x3f8 InGlobalUpdateVpThreadPriorityList : 0 +0x400 SchedulerAssistPriorityFloor : 0n0 +0x404 Spare28 : 0 +0x408 EndPadding : [5] 0
|
用户态栈基本信息记录在线程信息块_NT_TIB结构中,它是TEB的第一部分。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| 0:000> ~ . 0 Id: d24.db0 Suspend: 1 Teb: 00000029`d4850000 Unfrozen 1 Id: d24.1224 Suspend: 1 Teb: 00000029`d4852000 Unfrozen 2 Id: d24.1248 Suspend: 1 Teb: 00000029`d4854000 Unfrozen 3 Id: d24.1230 Suspend: 1 Teb: 00000029`d4856000 Unfrozen 0:000> dt _NT_TIB 00000029`d4850000 MSVCP140!_NT_TIB +0x000 ExceptionList : (null) +0x008 StackBase : 0x00000029`d4b00000 Void //用户态栈基地址 +0x010 StackLimit : 0x00000029`d4afb000 Void //栈边界 +0x018 SubSystemTib : (null) +0x020 FiberData : 0x00000000`00001e00 Void +0x020 Version : 0x1e00 +0x028 ArbitraryUserPointer : (null) +0x030 Self : 0x00000029`d4850000 _NT_TIB
|
栈的创建
创建系统线程用PsCreateSystemThread
和用户线程用NtCreateThread
都用内核线程创建函数PspCreateThread
,后者创建内核态栈。
这节先鸽着。
栈增长与栈溢出
栈空间有自动增长机制:栈创建时系统多提交一个页面的栈空间,该页面称为栈保护页面,具有PAGE_GUARD属性。具有该属性的内存页被访问时CPU产生页错误异常并执行系统内存管理函数。内存管理函数此时先清除PAGE_GUARD属性,用MiCheckForUserStackOverflow
,后者从当前线程TEB中读取用户态栈基本信息并检查导致异常的地址。若导致异常的被访问地址不属于栈空间范围,则返回STATUS_GUARD_PAGE_VIOLATION,否则用ZwAllocateVirtualMemory
从保留空间中再提交一个具有PAGE_GUARD属性的内存页。
保留空间的最后一个页面永远不会被提交,且不设置PAGE_GUARD属性。