浅谈FS段寄存器在用户层和内核层的使用
来源:互联网 发布:unity3d创建材质球 编辑:程序博客网 时间:2024/06/05 20:48
//weibo: @少仲
在R0和R3时,FS段寄存器分别指向GDT中的不同段:在R3下,FS段寄存器的值是0x3B,在R0下,FS段寄存器的值是0x30.分别用OD和Windbg在R3和R0下查看寄存器(XP3),下图:
FS寄存器的改变是从R3进入R0后和从R0退回到R3前完成的,也就是说:都是在R0下给FS赋不同值的.(FS在R0和R3中是不同的值,在KiFastCallEntry / KiSystemService中FS值由0x3B变成0x30在 KiSystemCallExit / KiSystemCallExitBranch / KiSystemCallExit2 中再将R3的FS恢复)
一.R3与R0之间的互相转换
nt!KiSystemService:808696a1 6a00 push 0808696a3 55 push ebp808696a4 53 push ebx808696a5 56 push esi808696a6 57 push edi808696a7 0fa0 push fs //旧的R3 下的FS 保存入栈 808696a9 bb30000000 mov ebx,30h808696ae 668ee3 mov fs,bx //FS=0X30 FS 值变成了0X30808696b1 64ff3500000000 push dword ptr fs:[0]808696b8 64c70500000000ffffffff mov dword ptr fs:[0],0FFFFFFFFh808696c3 648b3524010000 mov esi,dword ptr fs:[124h] //ESI=_ETHEAD808696ca ffb640010000 push dword ptr [esi+140h] //PreviousMode808696d0 83ec48 sub esp,48h 808696d3 8b5c246c mov ebx,dword ptr [esp+6Ch] KiSystemCallExit部分代码80869945 8d6550 lea esp,[ebp+50h]80869948 0fa1 pop fs // 恢复 FS 值 8086994a 8d6554 lea esp,[ebp+54h]8086994d 5f pop edi8086994e 5e pop esi8086994f 5b pop ebx80869950 5d pop ebp80869951 66817c24088000 cmp word ptr [esp+8],80h
二.R3下的FS
当线程运行在R3下时,FS指向的段是GDT中的0x3B段.该段的长度为4K,基地址为当前线程的线程环境块(TEB),所以该段也被称为“TEB段”.因为Windows中线程是不停切换的,所以该段的基地址值将随线程切换而改变的.Windows2000中进程环境块(PEB)的地址为0X7FFDF000,该进程的第一个线程的TEB地址为0X7FFDE000,第二个TEB的地址为0X7FFDD000…..但是在WindowsXP SP3 下这些结构的地址都是随机映射的.所以进程的PEB的地址只能通过FS:[0x30]来获取了.Windows中每个线程都有一个ETHREAD结构,该结构的TEB成员(其实是KTHREAD中的成员,而KTHREAD又是ETHREAD的成员)是用来保存线程的TEB地址的,当线程切换时,Windows就会用该值来更改GDT的0x30段描述符的基地址值.
nt!_TEB +0x000 NtTib : _NT_TIB +0x000 ExceptionList : Ptr32 +0x004 StackBase : Ptr32 +0x008 StackLimit : Ptr32 +0x00c SubSystemTib : Ptr32 +0x010 FiberData : Ptr32 +0x010 Version : Uint4B +0x014 ArbitraryUserPointer : Ptr32 +0x018 Self : Ptr32 //TEB +0x01c EnvironmentPointer : Ptr32 +0x020 ClientId : _CLIENT_ID +0x000 UniqueProcess : Ptr32 +0x004 UniqueThread : Ptr32 +0x028 ActiveRpcHandle : Ptr32 +0x02c ThreadLocalStoragePointer : Ptr32 +0x030 ProcessEnvironmentBlock : Ptr32 //PEB +0x034 LastErrorValue : Uint4B +0x038 CountOfOwnedCriticalSections : Uint4B +0x03c CsrClientThread : Ptr32 +0x040 Win32ThreadInfo : Ptr32FS:[0X18] 就是TEB 所在的地址;FS:[0X30] 就是PEB 所在的地址
三.在R0下的FS
kd> dg 8 0x40 P Si Gr Pr LoSel Base Limit Type l ze an es ng Flags---- -------- -------- ---------- - -- -- -- -- --------0008 00000000 ffffffff Code RE 0 Bg Pg P Nl 00000c9a0010 00000000 ffffffff Data RW 0 Bg Pg P Nl 00000c920018 00000000 ffffffff Code RE 3 Bg Pg P Nl 00000cfa0020 00000000 ffffffff Data RW 3 Bg Pg P Nl 00000cf20028 80042000 000020ab TSS32 Busy 0 Nb By P Nl 0000008b0030 ffdff000 00001fff Data RW 0 Bg Pg P Nl 00000c920038 00000000 00000fff Data RW Ac 3 Bg By P Nl 000004f30040 00000400 0000ffff Data RW 3 Nb By P Nl 000000f2
当线程运行在R0下时, FS指向的段是GDT中的0x30段.该段的长度也为4K,基地址为0xFFDFF000.该地址指向系统的处理器控制区域(KPCR).这个区域中保存这处理器相关的一些重要数据值,如GDT、IDT表的值等等.
kd> dt nt!_kpcrnt!_KPCR +0x000 NtTib : _NT_TIB +0x01c SelfPcr : Ptr32 _KPCR //KPCR +0x020 Prcb : Ptr32 _KPRCB +0x024 Irql : UChar +0x028 IRR : Uint4B +0x02c IrrActive : Uint4B +0x030 IDR : Uint4B +0x034 KdVersionBlock : Ptr32 Void +0x038 IDT : Ptr32 _KIDTENTRY +0x03c GDT : Ptr32 _KGDTENTRY +0x040 TSS : Ptr32 _KTSS +0x044 MajorVersion : Uint2B +0x046 MinorVersion : Uint2B +0x048 SetMember : Uint4B +0x04c StallScaleFactor : Uint4B +0x050 DebugActive : UChar +0x051 Number : UChar +0x052 Spare0 : UChar +0x053 SecondLevelCacheAssociativity : UChar +0x054 VdmAlert : Uint4B +0x058 KernelReserved : [14] Uint4B +0x090 SecondLevelCacheSize : Uint4B +0x094 HalReserved : [16] Uint4B +0x0d4 InterruptMode : Uint4B +0x0d8 Spare1 : UChar +0x0dc KernelReserved2 : [17] Uint4B +0x120 PrcbData : _KPRCB
展开_NT_TIB
kd> dt _NT_TIBnt!_NT_TIB +0x000 ExceptionList : Ptr32 _EXCEPTION_REGISTRATION_RECORD +0x004 StackBase : Ptr32 Void +0x008 StackLimit : Ptr32 Void +0x00c SubSystemTib : Ptr32 Void +0x010 FiberData : Ptr32 Void +0x010 Version : Uint4B +0x014 ArbitraryUserPointer : Ptr32 Void +0x018 Self : Ptr32 _NT_TIB //TEB看两个地址0x18和0x1C.在TEB中0x18指向自己,即 TEB.而 KPCR 中指向自己的确是 0x1C ;0x18 却是指向当前线程的 TEB ,所以 0x18 字段名叫做Self-used 比较确切( WIN2K 源码如此定义).总之,不管是在R3还是R0 ,FS:[0x18] 总是指向当前线程的 TEB.
实例1:
获取KTHREAD
展开KPCR后,再次展开kpcrb
kd> dt nt!_kprcbnt!_KPRCB +0x000 MinorVersion : Uint2B +0x002 MajorVersion : Uint2B +0x004 CurrentThread : Ptr32 _KTHREAD +0x008 NextThread : Ptr32 _KTHREAD +0x00c IdleThread : Ptr32 _KTHREAD展开KPRCB结构继续观察可以看到FS:[0x124]指向了KTHREAD结构
实例2:
获取IdleProcess
kd> dt _KPRCBnt!_KPRCB +0x000 MinorVersion : Uint2B +0x002 MajorVersion : Uint2B +0x004 CurrentThread : Ptr32 _KTHREAD +0x008 NextThread : Ptr32 _KTHREAD +0x00c IdleThread : Ptr32 _KTHREADkd> dt _KTHREADnt!_KTHREAD +0x000 Header : _DISPATCHER_HEADER +0x010 MutantListHead : _LIST_ENTRY +0x018 InitialStack : Ptr32 Void +0x01c StackLimit : Ptr32 Void +0x020 Teb : Ptr32 Void +0x024 TlsArray : Ptr32 Void +0x028 KernelStack : Ptr32 Void +0x02c DebugActive : UChar +0x02d State : UChar +0x02e Alerted : [2] UChar +0x030 Iopl : UChar +0x031 NpxState : UChar +0x032 Saturation : Char +0x033 Priority : Char +0x034 ApcState : _KAPC_STATEkd> dt _KAPC_STATEnt!_KAPC_STATE +0x000 ApcListHead : [2] _LIST_ENTRY +0x010 Process : Ptr32 _KPROCESS +0x014 KernelApcInProgress : UChar +0x015 KernelApcPending : UChar +0x016 UserApcPending : UChar
VOID GetIdleProcess(){ PEPROCESS IdleProcess; _asm { mov eax,fs:[0x20] //取KPCRB mov eax,[eax+0xC] //取IdleThread mov eax,[eax+0x44]//取ApcState->Process mov IdleProcess,eax }}
最后贴一张KPCR结构图
- 浅谈FS段寄存器在用户层和内核层的使用
- 在win32驱动程序中使用事件实现内核层与用户层的同步
- android查看线程内核层和用户层的方法
- Linux内核层和用户层配置GPIO引脚
- 在应用层使用内核链表
- 如果在Action层和DAO层之间不使用Biz层,Action层的代码量将变大
- 使用acegi在业务逻辑层获得Web层的用户ID
- fs段寄存器在WINDOWS系统中的作用
- 新路程------imx6 内核层读写寄存器
- 简单解释Windows如何使用FS段寄存器
- 在linux kernel层调用用户层的方法
- Windows中FS段寄存器
- Windows 中 FS 段寄存器
- Linux在应用层读写寄存器的方法
- Linux在应用层读写寄存器的方法
- 新路程------hi3516a 在应用层对寄存器的操作
- Linux在应用层读写寄存器的方法
- fs:[0]到底表示什么?fs段寄存器在WINDOWS系统中的作用
- 两种日志方式
- jQuery架构 (2.0.3)
- IG&IC&Pra 卸载
- webwork基础学习笔记1
- [LeetCode] Find Peak Element
- 浅谈FS段寄存器在用户层和内核层的使用
- c++编程惯用法读书笔记
- 回首蓝桥杯
- javascript面向对象程序编程
- 弹出框(tooltip)模态modal框的实现原理及Jquery的一个实现实例
- 一步一步开发sniffer(Winpcap+MFC)(三)安得广厦千万间,先画蓝图再砌砖——搭建winpcap抓包框架
- jsp页面元素和内置对象
- 基于ArcEngine开发的ArcGIS特殊符号
- IOS中文件目录递归