[原创]X86内核笔记
1.API初识
API(应用程序编程接口)是微软为开发者提供的一套函数接口,可以用于与系统进行交互、实现一些复杂的功能等。
我们日常在3环写的API如:ReadMemory、CloseHandle、OpenProcess等。其真正的功能实现全部在驱动层,3环中我们使用的只是一个门票,用于通知驱动层我们要实现的功能。而这些API函数从3环的校验代码进入到0环的功能代码的步骤,就称为系统调用。
一些常见的动态链接库如下:
1 2 3 4
|
Kernel32.dll : 最核心的功能模块,如内存管理,进程线程相关函数等。 User32.dll : 用户界面相关的函数。 GDI32.dll : 图形设备接口,用于绘制和显示文本等。 Ntdll.dll : 大多数API都会通过这个dll进入 0 环。 |
2.了解系统调用好处
于防来说,了解系统调用可以更好的了解程序流程。对于一些恶意样本,攻击者会将API调用改为直接进入0环的方式,这样对于一些3环的监控工具则无法监控该样本的行为,一些3环的APIHOOK也将失效。同样的,IDA一类的反汇编工具也无法直接查看样本使用了哪些API函数。
于攻来说,了解系统调用可以让你真正知道API函数执行的本质,无论是自实现系统调用、驱动层HOOK或是以服务号调用API,都可以让你的攻击手段很难被安全从业者察觉、分析。而HOOK住驱动层的功能函数,也可以达到另类的驱动通信效果。
由于现在的系统带有PG保护,使得系统调用这个技术点无法被直接利用,现已作为基础知识慢慢的与其他技术相融合。
3.ReadProcessMemory实战分析(3环)
在MSDN上搜索该函数,发现其所属模块为kernel32.dll,但是当你去追kernel32里的流程,你会发现最终都是执行了一个return 0。这是历史遗留问题,所以不能盲目相信MSDN。
KernelBase->ntdll
在WIN7镜像中,随便找个程序拖到OD里,Ctrl+G定位至ReadProcessMemory函数。发现该函数已经隶属于KernelBase模块了。且其内部没有什么有用的代码,只调用了ntdll的NtReadVirtualMemory函数。该函数是KernelBase的导入函数。
使用IDA打开ntdll,在导出函数选项卡中搜索NtReadVirtualMemory。
跟过去看一下该函数的实现。发现函数内部仅调用了[7FFE0300]处的函数,同时为eax赋值。
总结
至此,3环绝大部分告一段落。可以发现ReadProcessMemory函数的3环执行流程就是跳来跳去,然后执行一个call [7FFE0300]。接下来我们需要探求7FFE0300里面存的是什么。
4.实战分析-3环进入0环
_KUSER_SHARED_DATA
在继续分析之前,我们需要补充一个知识点:_KUSER_SHARED_DATA。这是一个3环与0环共享的结构体。
在3环,它的地址为7ffe0000,具备只读权限。在0环,它的地址为ffdf0000,具备读写权限。这两个地址指向同一个物理页,只是访问权限不同。该结构会在操作系统启动时由操作系统自己填充。
结构体信息如下:
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
|
/ / 0x5f0 bytes (sizeof) struct _KUSER_SHARED_DATA { ULONG TickCountLowDeprecated; / / 0x0 ULONG TickCountMultiplier; / / 0x4 volatile struct _KSYSTEM_TIME InterruptTime; / / 0x8 volatile struct _KSYSTEM_TIME SystemTime; / / 0x14 volatile struct _KSYSTEM_TIME TimeZoneBias; / / 0x20 USHORT ImageNumberLow; / / 0x2c USHORT ImageNumberHigh; / / 0x2e WCHAR NtSystemRoot[ 260 ]; / / 0x30 ULONG MaxStackTraceDepth; / / 0x238 ULONG CryptoExponent; / / 0x23c ULONG TimeZoneId; / / 0x240 ULONG LargePageMinimum; / / 0x244 ULONG Reserved2[ 7 ]; / / 0x248 enum _NT_PRODUCT_TYPE NtProductType; / / 0x264 UCHAR ProductTypeIsValid; / / 0x268 ULONG NtMajorVersion; / / 0x26c ULONG NtMinorVersion; / / 0x270 UCHAR ProcessorFeatures[ 64 ]; / / 0x274 ULONG Reserved1; / / 0x2b4 ULONG Reserved3; / / 0x2b8 volatile ULONG TimeSlip; / / 0x2bc enum _ALTERNATIVE_ARCHITECTURE_TYPE AlternativeArchitecture; / / 0x2c0 ULONG AltArchitecturePad[ 1 ]; / / 0x2c4 union _LARGE_INTEGER SystemExpirationDate; / / 0x2c8 ULONG SuiteMask; / / 0x2d0 UCHAR KdDebuggerEnabled; / / 0x2d4 UCHAR NXSupportPolicy; / / 0x2d5 volatile ULONG ActiveConsoleId; / / 0x2d8 volatile ULONG DismountCount; / / 0x2dc ULONG ComPlusPackage; / / 0x2e0 ULONG LastSystemRITEventTickCount; / / 0x2e4 ULONG NumberOfPhysicalPages; / / 0x2e8 UCHAR SafeBootMode; / / 0x2ec union { UCHAR TscQpcData; / / 0x2ed struct { UCHAR TscQpcEnabled: 1 ; / / 0x2ed UCHAR TscQpcSpareFlag: 1 ; / / 0x2ed UCHAR TscQpcShift: 6 ; / / 0x2ed }; }; UCHAR TscQpcPad[ 2 ]; / / 0x2ee union { ULONG SharedDataFlags; / / 0x2f0 struct { ULONG DbgErrorPortPresent: 1 ; / / 0x2f0 ULONG DbgElevationEnabled: 1 ; / / 0x2f0 ULONG DbgVirtEnabled: 1 ; / / 0x2f0 ULONG DbgInstallerDetectEnabled: 1 ; / / 0x2f0 ULONG DbgSystemDllRelocated: 1 ; / / 0x2f0 ULONG DbgDynProcessorEnabled: 1 ; / / 0x2f0 ULONG DbgSEHValidationEnabled: 1 ; / / 0x2f0 ULONG SpareBits: 25 ; / / 0x2f0 }; }; ULONG DataFlagsPad[ 1 ]; / / 0x2f4 ULONGLONG TestRetInstruction; / / 0x2f8 ULONG SystemCall; / / 0x300 ULONG SystemCallReturn; / / 0x304 ULONGLONG SystemCallPad[ 3 ]; / / 0x308 union { volatile struct _KSYSTEM_TIME TickCount; / / 0x320 volatile ULONGLONG TickCountQuad; / / 0x320 ULONG ReservedTickCountOverlay[ 3 ]; / / 0x320 }; ULONG TickCountPad[ 1 ]; / / 0x32c ULONG Cookie; / / 0x330 ULONG CookiePad[ 1 ]; / / 0x334 LONGLONG ConsoleSessionForegroundProcessId; / / 0x338 ULONG Wow64SharedInformation[ 16 ]; / / 0x340 USHORT UserModeGlobalLogger[ 16 ]; / / 0x380 ULONG ImageFileExecutionOptions; / / 0x3a0 ULONG LangGenerationCount; / / 0x3a4 ULONGLONG Reserved5; / / 0x3a8 volatile ULONGLONG InterruptTimeBias; / / 0x3b0 volatile ULONGLONG TscQpcBias; / / 0x3b8 volatile ULONG ActiveProcessorCount; / / 0x3c0 volatile USHORT ActiveGroupCount; / / 0x3c4 USHORT Reserved4; / / 0x3c6 volatile ULONG AitSamplingValue; / / 0x3c8 volatile ULONG AppCompatFlag; / / 0x3cc ULONGLONG SystemDllNativeRelocation; / / 0x3d0 ULONG SystemDllWowRelocation; / / 0x3d8 ULONG XStatePad[ 1 ]; / / 0x3dc struct _XSTATE_CONFIGURATION XState; / / 0x3e0 }; |
其中偏移0x300处的成员为SystemCall,该成员指明了当发生系统调用时,3环进入0环走哪个函数,该成员就存储对应函数的地址
。
由于现在的处理器均支持快速调用(sysenter指令),而旧处理器不支持,所以此处存储的函数地址有两种情况。后文仅演示快速调用。(中断门(0x2E)进0环已经在历史的长河中被替代了,有兴趣的可以了解下。)
为了查看7FFE0300的值,我们需要借助windbg动态调试。
在windbg中输入 !process 0 0遍历所有进程,随便附加其中一个即可。
输入 dt _KUSER_SHARED_DATA 7FFE0000查看该结构体的成员信息。可以发现偏移0x300处存储的值为0x77a470b0。
使用命令 u 77a470b0 查看该地址的函数。可以看到windbg帮我们识别出来是ntdll模块中的KiFastSystemCall函数。回到IDA中,定位至该函数,观察函数执行流程。
KiFastSystemCall
可以发现该函数只有两行代码:mov edx,esp sysenter。 sysenter将会进入0环。
sysenter指令
在保护模式章节中,我们知道3环进0环必备的几个条件:
- 权限发生切换时,需要新的CS
- 与CS保持权限一致,也需要新的SS
- 0环的堆栈:ESP
- 0环代码从哪执行:EIP
在旧CPU中,使用中断门(0x2E)进行系统调用,需要查询TSS来获取这几个寄存器的值。内存查询是很慢的。
而sysenter指令将会直接从MSR寄存器中读取并写入至CS、SS、EIP、ESP中,速度很快,因此称为快速调用。
MSR寄存器
MSR寄存器很大,存了很多的数据。
在偏移0x174处,存储着系统调用时0环的CS。
在偏移0x175处,存储着系统调用时0环的ESP。
在偏移0x176处,存储着系统调用时0环的EIP。
SS的值通过CS+8得到(具体原因参考保护模式章节,CS与SS的段描述符是相邻的)。
通过指令RDMSR/WRMSR可以对MSR寄存器进行读写。
在windbg中查看CS ESP EIP的值:
在windbg中输入命令 u 83e420c0查看这个函数
可以得知当我们在3环调用sysenter指令时,将会执行内核模块(ntoskrnl、ntkrnlpa)中的KiFastCallEntry函数
总结
当发生系统调用时,若CPU支持快速调用,则走KiFastSystemCall函数,内部执行sysenter指令。并在0环执行KiFastCallEntry函数。同时携带了edx(3环堆栈)、eax(系统调用号)
5.前置知识-内核结构体
以下结构体均在内核空间,3环无法直接访问
TrapFrame
在进入0环时,该结构体用于保存3环寄存器。由windows进行维护。
结构体成员:
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
|
/ / 0x8c bytes (sizeof) struct _KTRAP_FRAME { ULONG DbgEbp; / / 0x0 ULONG DbgEip; / / 0x4 ULONG DbgArgMark; / / 0x8 ULONG DbgArgPointer; / / 0xc USHORT TempSegCs; / / 0x10 UCHAR Logging; / / 0x12 UCHAR Reserved; / / 0x13 ULONG TempEsp; / / 0x14 ULONG Dr0; / / 0x18 ULONG Dr1; / / 0x1c ULONG Dr2; / / 0x20 ULONG Dr3; / / 0x24 ULONG Dr6; / / 0x28 ULONG Dr7; / / 0x2c ULONG SegGs; / / 0x30 ULONG SegEs; / / 0x34 ULONG SegDs; / / 0x38 ULONG Edx; / / 0x3c ULONG Ecx; / / 0x40 ULONG Eax; / / 0x44 ULONG PreviousPreviousMode; / / 0x48 struct _EXCEPTION_REGISTRATION_RECORD * ExceptionList; / / 0x4c ULONG SegFs; / / 0x50 ULONG Edi; / / 0x54 ULONG Esi; / / 0x58 ULONG Ebx; / / 0x5c ULONG Ebp; / / 0x60 ULONG ErrCode; / / 0x64 ULONG Eip; / / 0x68 ULONG SegCs; / / 0x6c ULONG EFlags; / / 0x70 ULONG HardwareEsp; / / 0x74 ULONG HardwareSegSs; / / 0x78 ULONG V86Es; / / 0x7c ULONG V86Ds; / / 0x80 ULONG V86Fs; / / 0x84 ULONG V86Gs; / / 0x88 }; |
KPCR
在3环时,FS指向TEB结构。在0环时,FS指向KPCR结构。该结构体用于描述对应的CPU的状态。(一核对应一个KPCR)
windbg中输入 dd KeNumberProcessor 查看核数
windbg中输入 dd KiProcessorBlock LXXX 查看每个核的KPCR结构地址。
结构体成员:
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
|
/ / 0x3748 bytes (sizeof) struct _KPCR { union { struct _NT_TIB NtTib; / / 0x0 struct { struct _EXCEPTION_REGISTRATION_RECORD * Used_ExceptionList; / / 0x0 VOID * Used_StackBase; / / 0x4 VOID * Spare2; / / 0x8 VOID * TssCopy; / / 0xc ULONG ContextSwitches; / / 0x10 ULONG SetMemberCopy; / / 0x14 VOID * Used_Self; / / 0x18 }; }; struct _KPCR * SelfPcr; / / 0x1c struct _KPRCB * Prcb; / / 0x20 UCHAR Irql; / / 0x24 ULONG IRR; / / 0x28 ULONG IrrActive; / / 0x2c ULONG IDR; / / 0x30 VOID * KdVersionBlock; / / 0x34 struct _KIDTENTRY * IDT; / / 0x38 struct _KGDTENTRY * GDT; / / 0x3c struct _KTSS * TSS; / / 0x40 USHORT MajorVersion; / / 0x44 USHORT MinorVersion; / / 0x46 ULONG SetMember; / / 0x48 ULONG StallScaleFactor; / / 0x4c UCHAR SpareUnused; / / 0x50 UCHAR Number; / / 0x51 UCHAR Spare0; / / 0x52 UCHAR SecondLevelCacheAssociativity; / / 0x53 ULONG VdmAlert; / / 0x54 ULONG KernelReserved[ 14 ]; / / 0x58 ULONG SecondLevelCacheSize; / / 0x90 ULONG HalReserved[ 16 ]; / / 0x94 ULONG InterruptMode; / / 0xd4 UCHAR Spare1; / / 0xd8 ULONG KernelReserved2[ 17 ]; / / 0xdc struct _KPRCB PrcbData; / / 0x120 }; |
KPRCB
结构体成员:
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 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264
|
/ / 0x3628 bytes (sizeof) struct _KPRCB { USHORT MinorVersion; / / 0x0 USHORT MajorVersion; / / 0x2 struct _KTHREAD * CurrentThread; / / 0x4 struct _KTHREAD * NextThread; / / 0x8 struct _KTHREAD * IdleThread; / / 0xc UCHAR LegacyNumber; / / 0x10 UCHAR NestingLevel; / / 0x11 USHORT BuildType; / / 0x12 CHAR CpuType; / / 0x14 CHAR CpuID; / / 0x15 union { USHORT CpuStep; / / 0x16 struct { UCHAR CpuStepping; / / 0x16 UCHAR CpuModel; / / 0x17 }; }; struct _KPROCESSOR_STATE ProcessorState; / / 0x18 ULONG KernelReserved[ 16 ]; / / 0x338 ULONG HalReserved[ 16 ]; / / 0x378 ULONG CFlushSize; / / 0x3b8 UCHAR CoresPerPhysicalProcessor; / / 0x3bc UCHAR LogicalProcessorsPerCore; / / 0x3bd UCHAR PrcbPad0[ 2 ]; / / 0x3be ULONG MHz; / / 0x3c0 UCHAR CpuVendor; / / 0x3c4 UCHAR GroupIndex; / / 0x3c5 USHORT Group; / / 0x3c6 ULONG GroupSetMember; / / 0x3c8 ULONG Number; / / 0x3cc UCHAR PrcbPad1[ 72 ]; / / 0x3d0 struct _KSPIN_LOCK_QUEUE LockQueue[ 17 ]; / / 0x418 struct _KTHREAD * NpxThread; / / 0x4a0 ULONG InterruptCount; / / 0x4a4 ULONG KernelTime; / / 0x4a8 ULONG UserTime; / / 0x4ac ULONG DpcTime; / / 0x4b0 ULONG DpcTimeCount; / / 0x4b4 ULONG InterruptTime; / / 0x4b8 ULONG AdjustDpcThreshold; / / 0x4bc ULONG PageColor; / / 0x4c0 UCHAR DebuggerSavedIRQL; / / 0x4c4 UCHAR NodeColor; / / 0x4c5 UCHAR PrcbPad20[ 2 ]; / / 0x4c6 ULONG NodeShiftedColor; / / 0x4c8 struct _KNODE * ParentNode; / / 0x4cc ULONG SecondaryColorMask; / / 0x4d0 ULONG DpcTimeLimit; / / 0x4d4 ULONG PrcbPad21[ 2 ]; / / 0x4d8 ULONG CcFastReadNoWait; / / 0x4e0 ULONG CcFastReadWait; / / 0x4e4 ULONG CcFastReadNotPossible; / / 0x4e8 ULONG CcCopyReadNoWait; / / 0x4ec ULONG CcCopyReadWait; / / 0x4f0 ULONG CcCopyReadNoWaitMiss; / / 0x4f4 volatile LONG MmSpinLockOrdering; / / 0x4f8 volatile LONG IoReadOperationCount; / / 0x4fc volatile LONG IoWriteOperationCount; / / 0x500 volatile LONG IoOtherOperationCount; / / 0x504 union _LARGE_INTEGER IoReadTransferCount; / / 0x508 union _LARGE_INTEGER IoWriteTransferCount; / / 0x510 union _LARGE_INTEGER IoOtherTransferCount; / / 0x518 ULONG CcFastMdlReadNoWait; / / 0x520 ULONG CcFastMdlReadWait; / / 0x524 ULONG CcFastMdlReadNotPossible; / / 0x528 ULONG CcMapDataNoWait; / / 0x52c ULONG CcMapDataWait; / / 0x530 ULONG CcPinMappedDataCount; / / 0x534 ULONG CcPinReadNoWait; / / 0x538 ULONG CcPinReadWait; / / 0x53c ULONG CcMdlReadNoWait; / / 0x540 ULONG CcMdlReadWait; / / 0x544 ULONG CcLazyWriteHotSpots; / / 0x548 ULONG CcLazyWriteIos; / / 0x54c ULONG CcLazyWritePages; / / 0x550 ULONG CcDataFlushes; / / 0x554 ULONG CcDataPages; / / 0x558 ULONG CcLostDelayedWrites; / / 0x55c ULONG CcFastReadResourceMiss; / / 0x560 ULONG CcCopyReadWaitMiss; / / 0x564 ULONG CcFastMdlReadResourceMiss; / / 0x568 ULONG CcMapDataNoWaitMiss; / / 0x56c ULONG CcMapDataWaitMiss; / / 0x570 ULONG CcPinReadNoWaitMiss; / / 0x574 ULONG CcPinReadWaitMiss; / / 0x578 ULONG CcMdlReadNoWaitMiss; / / 0x57c ULONG CcMdlReadWaitMiss; / / 0x580 ULONG CcReadAheadIos; / / 0x584 ULONG KeAlignmentFixupCount; / / 0x588 ULONG KeExceptionDispatchCount; / / 0x58c ULONG KeSystemCalls; / / 0x590 ULONG AvailableTime; / / 0x594 ULONG PrcbPad22[ 2 ]; / / 0x598 struct _PP_LOOKASIDE_LIST PPLookasideList[ 16 ]; / / 0x5a0 struct _GENERAL_LOOKASIDE_POOL PPNPagedLookasideList[ 32 ]; / / 0x620 struct _GENERAL_LOOKASIDE_POOL PPPagedLookasideList[ 32 ]; / / 0xf20 volatile ULONG PacketBarrier; / / 0x1820 volatile LONG ReverseStall; / / 0x1824 VOID * IpiFrame; / / 0x1828 UCHAR PrcbPad3[ 52 ]; / / 0x182c VOID * volatile CurrentPacket[ 3 ]; / / 0x1860 volatile ULONG TargetSet; / / 0x186c VOID ( * volatileWorkerRoutine)(VOID * arg1, VOID * arg2, VOID * arg3, VOID * arg4); / / 0x1870 volatile ULONG IpiFrozen; / / 0x1874 UCHAR PrcbPad4[ 40 ]; / / 0x1878 volatile ULONG RequestSummary; / / 0x18a0 struct _KPRCB * volatile SignalDone; / / 0x18a4 UCHAR PrcbPad50[ 56 ]; / / 0x18a8 struct _KDPC_DATA DpcData[ 2 ]; / / 0x18e0 VOID * DpcStack; / / 0x1908 LONG MaximumDpcQueueDepth; / / 0x190c ULONG DpcRequestRate; / / 0x1910 ULONG MinimumDpcRate; / / 0x1914 ULONG DpcLastCount; / / 0x1918 ULONG PrcbLock; / / 0x191c struct _KGATE DpcGate; / / 0x1920 UCHAR ThreadDpcEnable; / / 0x1930 volatile UCHAR QuantumEnd; / / 0x1931 volatile UCHAR DpcRoutineActive; / / 0x1932 volatile UCHAR IdleSchedule; / / 0x1933 union { volatile LONG DpcRequestSummary; / / 0x1934 SHORT DpcRequestSlot[ 2 ]; / / 0x1934 struct { SHORT NormalDpcState; / / 0x1934 union { volatile USHORT DpcThreadActive: 1 ; / / 0x1936 SHORT ThreadDpcState; / / 0x1936 }; }; }; volatile ULONG TimerHand; / / 0x1938 ULONG LastTick; / / 0x193c LONG MasterOffset; / / 0x1940 ULONG PrcbPad41[ 2 ]; / / 0x1944 ULONG PeriodicCount; / / 0x194c ULONG PeriodicBias; / / 0x1950 ULONGLONG TickOffset; / / 0x1958 struct _KTIMER_TABLE TimerTable; / / 0x1960 struct _KDPC CallDpc; / / 0x31a0 LONG ClockKeepAlive; / / 0x31c0 UCHAR ClockCheckSlot; / / 0x31c4 UCHAR ClockPollCycle; / / 0x31c5 UCHAR PrcbPad6[ 2 ]; / / 0x31c6 LONG DpcWatchdogPeriod; / / 0x31c8 LONG DpcWatchdogCount; / / 0x31cc LONG ThreadWatchdogPeriod; / / 0x31d0 LONG ThreadWatchdogCount; / / 0x31d4 volatile LONG KeSpinLockOrdering; / / 0x31d8 ULONG PrcbPad70[ 1 ]; / / 0x31dc struct _LIST_ENTRY WaitListHead; / / 0x31e0 ULONG WaitLock; / / 0x31e8 ULONG ReadySummary; / / 0x31ec ULONG QueueIndex; / / 0x31f0 struct _SINGLE_LIST_ENTRY DeferredReadyListHead; / / 0x31f4 ULONGLONG StartCycles; / / 0x31f8 volatile ULONGLONG CycleTime; / / 0x3200 volatile ULONG HighCycleTime; / / 0x3208 ULONG PrcbPad71; / / 0x320c ULONGLONG PrcbPad72[ 2 ]; / / 0x3210 struct _LIST_ENTRY DispatcherReadyListHead[ 32 ]; / / 0x3220 VOID * ChainedInterruptList; / / 0x3320 LONG LookasideIrpFloat; / / 0x3324 volatile LONG MmPageFaultCount; / / 0x3328 volatile LONG MmCopyOnWriteCount; / / 0x332c volatile LONG MmTransitionCount; / / 0x3330 volatile LONG MmCacheTransitionCount; / / 0x3334 volatile LONG MmDemandZeroCount; / / 0x3338 volatile LONG MmPageReadCount; / / 0x333c volatile LONG MmPageReadIoCount; / / 0x3340 volatile LONG MmCacheReadCount; / / 0x3344 volatile LONG MmCacheIoCount; / / 0x3348 volatile LONG MmDirtyPagesWriteCount; / / 0x334c volatile LONG MmDirtyWriteIoCount; / / 0x3350 volatile LONG MmMappedPagesWriteCount; / / 0x3354 volatile LONG MmMappedWriteIoCount; / / 0x3358 volatile ULONG CachedCommit; / / 0x335c volatile ULONG CachedResidentAvailable; / / 0x3360 VOID * HyperPte; / / 0x3364 UCHAR PrcbPad8[ 4 ]; / / 0x3368 UCHAR VendorString[ 13 ]; / / 0x336c UCHAR InitialApicId; / / 0x3379 UCHAR LogicalProcessorsPerPhysicalProcessor; / / 0x337a UCHAR PrcbPad9[ 5 ]; / / 0x337b ULONG FeatureBits; / / 0x3380 union _LARGE_INTEGER UpdateSignature; / / 0x3388 volatile ULONGLONG IsrTime; / / 0x3390 ULONGLONG RuntimeAccumulation; / / 0x3398 struct _PROCESSOR_POWER_STATE PowerState; / / 0x33a0 struct _KDPC DpcWatchdogDpc; / / 0x3468 struct _KTIMER DpcWatchdogTimer; / / 0x3488 VOID * WheaInfo; / / 0x34b0 VOID * EtwSupport; / / 0x34b4 union _SLIST_HEADER InterruptObjectPool; / / 0x34b8 union _SLIST_HEADER HypercallPageList; / / 0x34c0 VOID * HypercallPageVirtual; / / 0x34c8 VOID * VirtualApicAssist; / / 0x34cc ULONGLONG * StatisticsPage; / / 0x34d0 VOID * RateControl; / / 0x34d4 struct _CACHE_DESCRIPTOR Cache[ 5 ]; / / 0x34d8 ULONG CacheCount; / / 0x3514 ULONG CacheProcessorMask[ 5 ]; / / 0x3518 struct _KAFFINITY_EX PackageProcessorSet; / / 0x352c ULONG PrcbPad91[ 1 ]; / / 0x3538 ULONG CoreProcessorSet; / / 0x353c struct _KDPC TimerExpirationDpc; / / 0x3540 ULONG SpinLockAcquireCount; / / 0x3560 ULONG SpinLockContentionCount; / / 0x3564 ULONG SpinLockSpinCount; / / 0x3568 ULONG IpiSendRequestBroadcastCount; / / 0x356c ULONG IpiSendRequestRoutineCount; / / 0x3570 ULONG IpiSendSoftwareInterruptCount; / / 0x3574 ULONG ExInitializeResourceCount; / / 0x3578 ULONG ExReInitializeResourceCount; / / 0x357c ULONG ExDeleteResourceCount; / / 0x3580 ULONG ExecutiveResourceAcquiresCount; / / 0x3584 ULONG ExecutiveResourceContentionsCount; / / 0x3588 ULONG ExecutiveResourceReleaseExclusiveCount; / / 0x358c ULONG ExecutiveResourceReleaseSharedCount; / / 0x3590 ULONG ExecutiveResourceConvertsCount; / / 0x3594 ULONG ExAcqResExclusiveAttempts; / / 0x3598 ULONG ExAcqResExclusiveAcquiresExclusive; / / 0x359c ULONG ExAcqResExclusiveAcquiresExclusiveRecursive; / / 0x35a0 ULONG ExAcqResExclusiveWaits; / / 0x35a4 ULONG ExAcqResExclusiveNotAcquires; / / 0x35a8 ULONG ExAcqResSharedAttempts; / / 0x35ac ULONG ExAcqResSharedAcquiresExclusive; / / 0x35b0 ULONG ExAcqResSharedAcquiresShared; / / 0x35b4 ULONG ExAcqResSharedAcquiresSharedRecursive; / / 0x35b8 ULONG ExAcqResSharedWaits; / / 0x35bc ULONG ExAcqResSharedNotAcquires; / / 0x35c0 ULONG ExAcqResSharedStarveExclusiveAttempts; / / 0x35c4 ULONG ExAcqResSharedStarveExclusiveAcquiresExclusive; / / 0x35c8 ULONG ExAcqResSharedStarveExclusiveAcquiresShared; / / 0x35cc ULONG ExAcqResSharedStarveExclusiveAcquiresSharedRecursive; / / 0x35d0 ULONG ExAcqResSharedStarveExclusiveWaits; / / 0x35d4 ULONG ExAcqResSharedStarveExclusiveNotAcquires; / / 0x35d8 ULONG ExAcqResSharedWaitForExclusiveAttempts; / / 0x35dc ULONG ExAcqResSharedWaitForExclusiveAcquiresExclusive; / / 0x35e0 ULONG ExAcqResSharedWaitForExclusiveAcquiresShared; / / 0x35e4 ULONG ExAcqResSharedWaitForExclusiveAcquiresSharedRecursive; / / 0x35e8 ULONG ExAcqResSharedWaitForExclusiveWaits; / / 0x35ec ULONG ExAcqResSharedWaitForExclusiveNotAcquires; / / 0x35f0 ULONG ExSetResOwnerPointerExclusive; / / 0x35f4 ULONG ExSetResOwnerPointerSharedNew; / / 0x35f8 ULONG ExSetResOwnerPointerSharedOld; / / 0x35fc ULONG ExTryToAcqExclusiveAttempts; / / 0x3600 ULONG ExTryToAcqExclusiveAcquires; / / 0x3604 ULONG ExBoostExclusiveOwner; / / 0x3608 ULONG ExBoostSharedOwners; / / 0x360c ULONG ExEtwSynchTrackingNotificationsCount; / / 0x3610 ULONG ExEtwSynchTrackingNotificationsAccountedCount; / / 0x3614 struct _CONTEXT * Context; / / 0x3618 ULONG ContextFlags; / / 0x361c struct _XSAVE_AREA * ExtendedState; / / 0x3620 }; |
Ethread
线程结构体,每一个线程都有一个线程结构体,用于描述对应线程的各种属性。
结构体成员:
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
|
/ / 0x2b8 bytes (sizeof) struct _ETHREAD { struct _KTHREAD Tcb; / / 0x0 union _LARGE_INTEGER CreateTime; / / 0x200 union { union _LARGE_INTEGER ExitTime; / / 0x208 struct _LIST_ENTRY KeyedWaitChain; / / 0x208 }; LONG ExitStatus; / / 0x210 union { struct _LIST_ENTRY PostBlockList; / / 0x214 struct { VOID * ForwardLinkShadow; / / 0x214 VOID * StartAddress; / / 0x218 }; }; union { struct _TERMINATION_PORT * TerminationPort; / / 0x21c struct _ETHREAD * ReaperLink; / / 0x21c VOID * KeyedWaitValue; / / 0x21c }; ULONG ActiveTimerListLock; / / 0x220 struct _LIST_ENTRY ActiveTimerListHead; / / 0x224 struct _CLIENT_ID Cid; / / 0x22c union { struct _KSEMAPHORE KeyedWaitSemaphore; / / 0x234 struct _KSEMAPHORE AlpcWaitSemaphore; / / 0x234 }; union _PS_CLIENT_SECURITY_CONTEXT ClientSecurity; / / 0x248 struct _LIST_ENTRY IrpList; / / 0x24c ULONG TopLevelIrp; / / 0x254 struct _DEVICE_OBJECT * DeviceToVerify; / / 0x258 union _PSP_CPU_QUOTA_APC * CpuQuotaApc; / / 0x25c VOID * Win32StartAddress; / / 0x260 VOID * LegacyPowerObject; / / 0x264 struct _LIST_ENTRY ThreadListEntry; / / 0x268 struct _EX_RUNDOWN_REF RundownProtect; / / 0x270 struct _EX_PUSH_LOCK ThreadLock; / / 0x274 ULONG ReadClusterSize; / / 0x278 volatile LONG MmLockOrdering; / / 0x27c union { ULONG CrossThreadFlags; / / 0x280 struct { ULONG Terminated: 1 ; / / 0x280 ULONG ThreadInserted: 1 ; / / 0x280 ULONG HideFromDebugger: 1 ; / / 0x280 ULONG ActiveImpersonationInfo: 1 ; / / 0x280 ULONG Reserved: 1 ; / / 0x280 ULONG HardErrorsAreDisabled: 1 ; / / 0x280 ULONG BreakOnTermination: 1 ; / / 0x280 ULONG SkipCreationMsg: 1 ; / / 0x280 ULONG SkipTerminationMsg: 1 ; / / 0x280 ULONG CopyTokenOnOpen: 1 ; / / 0x280 ULONG ThreadIoPriority: 3 ; / / 0x280 ULONG ThreadPagePriority: 3 ; / / 0x280 ULONG RundownFail: 1 ; / / 0x280 ULONG NeedsWorkingSetAging: 1 ; / / 0x280 }; }; union { ULONG SameThreadPassiveFlags; / / 0x284 struct { ULONG ActiveExWorker: 1 ; / / 0x284 ULONG ExWorkerCanWaitUser: 1 ; / / 0x284 ULONG MemoryMaker: 1 ; / / 0x284 ULONG ClonedThread: 1 ; / / 0x284 ULONG KeyedEventInUse: 1 ; / / 0x284 ULONG RateApcState: 2 ; / / 0x284 ULONG SelfTerminate: 1 ; / / 0x284 }; }; union { ULONG SameThreadApcFlags; / / 0x288 struct { UCHAR Spare: 1 ; / / 0x288 volatile UCHAR StartAddressInvalid: 1 ; / / 0x288 UCHAR EtwPageFaultCalloutActive: 1 ; / / 0x288 UCHAR OwnsProcessWorkingSetExclusive: 1 ; / / 0x288 UCHAR OwnsProcessWorkingSetShared: 1 ; / / 0x288 UCHAR OwnsSystemCacheWorkingSetExclusive: 1 ; / / 0x288 UCHAR OwnsSystemCacheWorkingSetShared: 1 ; / / 0x288 UCHAR OwnsSessionWorkingSetExclusive: 1 ; / / 0x288 UCHAR OwnsSessionWorkingSetShared: 1 ; / / 0x289 UCHAR OwnsProcessAddressSpaceExclusive: 1 ; / / 0x289 UCHAR OwnsProcessAddressSpaceShared: 1 ; / / 0x289 UCHAR SuppressSymbolLoad: 1 ; / / 0x289 UCHAR Prefetching: 1 ; / / 0x289 UCHAR OwnsDynamicMemoryShared: 1 ; / / 0x289 UCHAR OwnsChangeControlAreaExclusive: 1 ; / / 0x289 UCHAR OwnsChangeControlAreaShared: 1 ; / / 0x289 UCHAR OwnsPagedPoolWorkingSetExclusive: 1 ; / / 0x28a UCHAR OwnsPagedPoolWorkingSetShared: 1 ; / / 0x28a UCHAR OwnsSystemPtesWorkingSetExclusive: 1 ; / / 0x28a UCHAR OwnsSystemPtesWorkingSetShared: 1 ; / / 0x28a UCHAR TrimTrigger: 2 ; / / 0x28a UCHAR Spare1: 2 ; / / 0x28a UCHAR PriorityRegionActive; / / 0x28b }; }; UCHAR CacheManagerActive; / / 0x28c UCHAR DisablePageFaultClustering; / / 0x28d UCHAR ActiveFaultCount; / / 0x28e UCHAR LockOrderState; / / 0x28f ULONG AlpcMessageId; / / 0x290 union { VOID * AlpcMessage; / / 0x294 ULONG AlpcReceiveAttributeSet; / / 0x294 }; struct _LIST_ENTRY AlpcWaitListEntry; / / 0x298 ULONG CacheManagerCount; / / 0x2a0 ULONG IoBoostCount; / / 0x2a4 ULONG IrpListLock; / / 0x2a8 VOID * ReservedForSynchTracking; / / 0x2ac struct _SINGLE_LIST_ENTRY CmCallbackListHead; / / 0x2b0 }; |
Kthread
Ethread的子结构体,里面的成员相对于Ethread更重要。
结构体成员:
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
|
/ / 0x200 bytes (sizeof) struct _KTHREAD { struct _DISPATCHER_HEADER Header; / / 0x0 volatile ULONGLONG CycleTime; / / 0x10 volatile ULONG HighCycleTime; / / 0x18 ULONGLONG QuantumTarget; / / 0x20 VOID * InitialStack; / / 0x28 VOID * volatile StackLimit; / / 0x2c VOID * KernelStack; / / 0x30 ULONG ThreadLock; / / 0x34 union _KWAIT_STATUS_REGISTER WaitRegister; / / 0x38 volatile UCHAR Running; / / 0x39 UCHAR Alerted[ 2 ]; / / 0x3a union { struct { ULONG KernelStackResident: 1 ; / / 0x3c ULONG ReadyTransition: 1 ; / / 0x3c ULONG ProcessReadyQueue: 1 ; / / 0x3c ULONG WaitNext: 1 ; / / 0x3c ULONG SystemAffinityActive: 1 ; / / 0x3c ULONG Alertable: 1 ; / / 0x3c ULONG GdiFlushActive: 1 ; / / 0x3c ULONG UserStackWalkActive: 1 ; / / 0x3c ULONG ApcInterruptRequest: 1 ; / / 0x3c ULONG ForceDeferSchedule: 1 ; / / 0x3c ULONG QuantumEndMigrate: 1 ; / / 0x3c ULONG UmsDirectedSwitchEnable: 1 ; / / 0x3c ULONG TimerActive: 1 ; / / 0x3c ULONG SystemThread: 1 ; / / 0x3c ULONG Reserved: 18 ; / / 0x3c }; LONG MiscFlags; / / 0x3c }; union { struct _KAPC_STATE ApcState; / / 0x40 struct { UCHAR ApcStateFill[ 23 ]; / / 0x40 CHAR Priority; / / 0x57 }; }; volatile ULONG NextProcessor; / / 0x58 volatile ULONG DeferredProcessor; / / 0x5c ULONG ApcQueueLock; / / 0x60 ULONG ContextSwitches; / / 0x64 volatile UCHAR State; / / 0x68 CHAR NpxState; / / 0x69 UCHAR WaitIrql; / / 0x6a CHAR WaitMode; / / 0x6b volatile LONG WaitStatus; / / 0x6c struct _KWAIT_BLOCK * WaitBlockList; / / 0x70 union { struct _LIST_ENTRY WaitListEntry; / / 0x74 struct _SINGLE_LIST_ENTRY SwapListEntry; / / 0x74 }; struct _KQUEUE * volatile Queue; / / 0x7c ULONG WaitTime; / / 0x80 union { struct { SHORT KernelApcDisable; / / 0x84 SHORT SpecialApcDisable; / / 0x86 }; ULONG CombinedApcDisable; / / 0x84 }; VOID * Teb; / / 0x88 struct _KTIMER Timer; / / 0x90 union { struct { volatile ULONG AutoAlignment: 1 ; / / 0xb8 volatile ULONG DisableBoost: 1 ; / / 0xb8 volatile ULONG EtwStackTraceApc1Inserted: 1 ; / / 0xb8 volatile ULONG EtwStackTraceApc2Inserted: 1 ; / / 0xb8 volatile ULONG CalloutActive: 1 ; / / 0xb8 volatile ULONG ApcQueueable: 1 ; / / 0xb8 volatile ULONG EnableStackSwap: 1 ; / / 0xb8 volatile ULONG GuiThread: 1 ; / / 0xb8 volatile ULONG UmsPerformingSyscall: 1 ; / / 0xb8 volatile ULONG VdmSafe: 1 ; / / 0xb8 volatile ULONG UmsDispatched: 1 ; / / 0xb8 volatile ULONG ReservedFlags: 21 ; / / 0xb8 }; volatile LONG ThreadFlags; / / 0xb8 }; VOID * ServiceTable; / / 0xbc struct _KWAIT_BLOCK WaitBlock[ 4 ]; / / 0xc0 struct _LIST_ENTRY QueueListEntry; / / 0x120 struct _KTRAP_FRAME * TrapFrame; / / 0x128 VOID * FirstArgument; / / 0x12c union { VOID * CallbackStack; / / 0x130 ULONG CallbackDepth; / / 0x130 }; UCHAR ApcStateIndex; / / 0x134 CHAR BasePriority; / / 0x135 union { CHAR PriorityDecrement; / / 0x136 struct { UCHAR ForegroundBoost: 4 ; / / 0x136 UCHAR UnusualBoost: 4 ; / / 0x136 }; }; UCHAR Preempted; / / 0x137 UCHAR AdjustReason; / / 0x138 CHAR AdjustIncrement; / / 0x139 CHAR PreviousMode; / / 0x13a CHAR Saturation; / / 0x13b ULONG SystemCallNumber; / / 0x13c ULONG FreezeCount; / / 0x140 volatile struct _GROUP_AFFINITY UserAffinity; / / 0x144 struct _KPROCESS * Process; / / 0x150 volatile struct _GROUP_AFFINITY Affinity; / / 0x154 ULONG IdealProcessor; / / 0x160 ULONG UserIdealProcessor; / / 0x164 struct _KAPC_STATE * ApcStatePointer[ 2 ]; / / 0x168 union { struct _KAPC_STATE SavedApcState; / / 0x170 struct { UCHAR SavedApcStateFill[ 23 ]; / / 0x170 UCHAR WaitReason; / / 0x187 }; }; CHAR SuspendCount; / / 0x188 CHAR Spare1; / / 0x189 UCHAR OtherPlatformFill; / / 0x18a VOID * volatile Win32Thread; / / 0x18c VOID * StackBase; / / 0x190 union { struct _KAPC SuspendApc; / / 0x194 struct { UCHAR SuspendApcFill0[ 1 ]; / / 0x194 UCHAR ResourceIndex; / / 0x195 }; struct { UCHAR SuspendApcFill1[ 3 ]; / / 0x194 UCHAR QuantumReset; / / 0x197 }; struct { UCHAR SuspendApcFill2[ 4 ]; / / 0x194 ULONG KernelTime; / / 0x198 }; struct { UCHAR SuspendApcFill3[ 36 ]; / / 0x194 struct _KPRCB * volatile WaitPrcb; / / 0x1b8 }; struct { UCHAR SuspendApcFill4[ 40 ]; / / 0x194 VOID * LegoData; / / 0x1bc }; struct { UCHAR SuspendApcFill5[ 47 ]; / / 0x194 UCHAR LargeStack; / / 0x1c3 }; }; ULONG UserTime; / / 0x1c4 union { struct _KSEMAPHORE SuspendSemaphore; / / 0x1c8 UCHAR SuspendSemaphorefill[ 20 ]; / / 0x1c8 }; ULONG SListFaultCount; / / 0x1dc struct _LIST_ENTRY ThreadListEntry; / / 0x1e0 struct _LIST_ENTRY MutantListHead; / / 0x1e8 VOID * SListFaultAddress; / / 0x1f0 struct _KTHREAD_COUNTERS * ThreadCounters; / / 0x1f4 struct _XSTATE_SAVE * XStateSave; / / 0x1f8 }; |
6.0环KiFastCallEntry(初始化部分)
分析该函数需要时刻对照上文的几个结构体,否则无法理解函数在做什么。
函数内部首先填充DS ES FS寄存器,并切换堆栈。(由于MSR寄存器所有核共享一个,为了防止互相影响,又从各自的TSS中拿了单独的ESP0 )
然后填充TrapFrame结构,该结构存储在0环堆栈中,通过push依次进行成员的填充。
起始位置为HardwareSegSs,V86那四个寄存器是虚拟8086模式用的,所以直接省略了。
继续填充TrapFrame结构体的其余成员。
填充好后将TrapFrame结构的首地址赋值给Kthread中的TrapFrame成员。
7.前置知识-系统服务表
在上文3环分析部分,可以看到ReadPrcMem函数仅调用了sysenter,并没有直接调用内核的某个对应函数。其真正调用的功能函数的地址,将通过查找系统服务表的方式得到。而3环传入的eax则是这个系统服务表的索引,也叫系统调用号。
系统服务表的宏观架构(系统服务表地址存储在Kthread+E0处):
- ServiceTable:函数地址表地址。每个成员是4字节,指向函数地址。
- Count:当前的系统服务表共被调用了多少次。(未使用)
- ServiceLimit:当前的系统服务表里共有多少个函数。
- ArgumentMent:函数参数个数表,每个成员都是参数的字节数,占1个字节。如对应函数由2个4字节参数,则存8。
3环在调用sysenter之前往eax中存的值决定了要调用哪个函数。
系统调用号仅低13位起作用,结构如下:
下标为12的位(第13位)如果为0,则查第一张系统服务表,为1则查第二张。
低12位(0~11)就是函数地址表和函数参数表的索引。
8.0环KiFastCallEntry(调用部分)
首先拆分系统调用号,找到系统服务表地址,取出索引。
获取函数地址、函数参数个数,复制参数至0环堆栈,并做第一次权限判断(3环堆栈地址判断)。
再次判断3环cs权限,通过后调用最终的功能函数。
9.SSDT
上文通过Kthread+BC去得到了系统服务表地址。Windows中提供了一个导出的全局变量SystemServicesDescriptorTable
。也叫SSDT。这个全局变量存储了系统服务表的地址,但仅存储了第一张表的地址。
在windbg中输入命令 dd KeServiceDescriptorTable查看该全局变量。可以发现只有一张表(16个字节)。第二张表全部为空。
内核中还有一个全局变量称为SSDT Shadow,该变量未导出,但可以查看所有的系统服务表。
在windbg中输入命令 dd KeServiceDescriptorTableShadow查看该全局变量。可以看到所有的系统服务表。
10.系统调用-返回3环
接近上文call ebx后,首先检查IRQL及线程挂靠相关信息。
然后检查ETW日志是否需要记录。并为Kthread->TrapFrame成员赋值。可用于恢复旧TrapFrame或蓝屏时进行堆栈回溯。
随后判断是否虚拟8086模式和之前的特权级。并相应的执行性能统计。
如果有APC需要处理则处理APC。(仅先前模式为用户模式时才会处理,APC知识后续章节学习。)
恢复异常链表及调试寄存器(如果为调试模式的话)。
进行一万个感觉没卵用的判断
最后恢复各种寄存器,并以iret方式返回3环。
总结:
返回的代码真正有用的就是恢复寄存器的几行,其余全是在做先前模式相关的判断。其中穿插了一个处理APC的逻辑。
当有APC需要处理时,会以另一套流程返回3环,由于目前不具备APC知识,暂不做分析。
整体分析流程皆以 先前模式为用户级别 为前提去分析,可以看到判断还是很多的,甚至考虑了其他非正常cs的情况。
11.SSDT HOOK保护进程
SSDT HOOK代码不算难,个人觉得比Inline HOOK简单的多。
取SSDT
1 2 3 4 5 6 7 8
|
ULONG GetSSDTBase() { PULONG pKthread = 0 ; __asm { mov eax,fs:[ 0x124 ] / / 找到Kthread结构指针 mov pKthread,eax } return * (PULONG)((PUCHAR)pKthread + 0xBC ); / / Kthread + BC就是系统服务表位置 } |
SetHook
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
VOID SetSsdtHook(ULONG oldFuncAddr,ULONG newFuncAddr) { PULONG SsdtBase = (PULONG)GetSSDTBase(); / / 0BEh OpenProcess PULONG ServiceTable = (PULONG)SsdtBase[ 0 ]; ULONG ServiceLimit = SsdtBase[ 2 ]; PULONG ArgumentTable = (PULONG)SsdtBase[ 3 ]; / / 遍历函数表,找到函数在ServiceTable中的位置并替换 for (ULONG i = 0 ; i < ServiceLimit; i + + ) { if (ServiceTable[i] = = oldFuncAddr) { ServiceTable[i] = newFuncAddr; } } } |
新函数
1 2 3 4 5 6 7 8 9 10
|
NTSTATUS NewOpenProcess(PHANDLE ProcessHandle, ACCESS_MASK DesiredAccess, POBJECT_ATTRIBUTES ObjectAttributes, PCLIENT_ID ClientId) { if (ClientId - >UniqueProcess = = 2356 || ClientId - >UniqueThread = = 2356 ) { / / 保护一下DbgView进程 DbgPrint( "Catch You!\r\n" ); * ProcessHandle = NULL; return STATUS_INVALID_PARAMETER; } return NtOpenProcess(ProcessHandle, DesiredAccess, ObjectAttributes, ClientId); } |
Main函数
1 2 3 4 5
|
NTSTATUS DriverEntry(PDRIVER_OBJECT pObj,PUNICODE_STRING pReg) { SetSsdtHook((ULONG)NtOpenProcess, (ULONG)NewOpenProcess); pObj - >DriverUnload = DriverUnload; return STATUS_SUCCESS; } |
卸载Hook
1 2 3
|
VOID DriverUnload(PDRIVER_OBJECT pObj) { SetSsdtHook(NewOpenProcess,NtOpenProcess); } |
效果
还挺好玩的,简单的保护了DbgView进程。