滴水核心学习记录
- 看前须知
- 保护模式
-
- 学习保护模式的意义
- 段寄存器
- 段描述符
- 门
- 页
- TLB
- 中断与异常
- PEB与TEB
- 驱动编程
-
- 分页和非分页内存
- 通信三环和0环
看前须知
从今天开始,记录文章。你我一起学习,体验学习的快乐。因为我以前在当地记录过这些东西,所以我一次发表更多。就我个人而言,我更喜欢以问答的方式记录学习,所以也许如果你只是看不懂我的文章,你可以把我的文章当作学习后的文章一种方式,文章也是根据学习路线写的。当然,有些我个人觉得很简单或不重要,我没有记录,你也可以提出,方便你我一起进步。
保护模式
学习保护模式的意义
答:因为x64向下兼容,学习x86能更好地理解x64体系
答:真实模式、保护模式、虚拟8086模式
答:只有学习保护模式,我们才能真正理解核心,否则我们只能停留在API层面
答:内存,特权指令
答:段落机制,页面机制
答:由于段的机制比较复杂,只有学习段的寄存器才能理解段的机制
段寄存器
答:段寄存器是访问某个地址时的前缀寄存器。段寄存器有8个,分别是ES CS SS DS FS GS LDTR TR
答:Attribute属性 Limit长度 Base开始位置 答:通过16位寄存器,mov、SLDT/LLDT、STR/LTR读写指令只能读16位,写96位。
答:红色机器的不同值可能不同,GS寄存器Windows未使用 答: 测试Attribute:通过对cs:[400000h] 和ds:[400000h]地址写入数据证明Selector 测试Base: 通过对fs:[0]和ds:[0]写入数据证明Base 测试Limit: 通过对fd:[1000]和ds:[0x7FFDE000 0x1000]写入数据证明limit 综上所述,写作时写入96位
答:通过GDT找到段描述符并将其加载到段寄存器中
段描述符
答:GDT表(全局描述符表)LDT表(局部描述符表)LDT表Windows未使用系统
答:段描述符是GDT记录在表中的段选择子是我们可以直接看到的16位段寄存器
答: TI为0是GDT表 TI为1是LDT表 答:除了MOV我们也可以使用指令LES、LSS、LDS、LFS、LGS指令修改寄存器. les ecx,fword ptr ds:[buffer] //高2字节es,给低四个字节ecx
答:CS寄存器不能随意修改,需要和解EIP一起修改,所以没有这样的指令
答:P定位段描述符是否有意义,G位决定limit剩下的12位填0还是1,G为0,limit为000FFFFF,G为1,limit为FFFFFFFF
答:S系统段描述符位为0,S说明是数据/代码段描述符,A表示是否访问过 答:数据段表示扩展方向,0是向上扩展(左图红色区域),1是向下扩展(右图红色区域) 代码段是否为一致代码段,0为非一致代码段,1为一致代码段 答: :对CS段的影响 D = 1 32位寻址 D = 0 采用16位寻址 前缀67 改变寻址方式 :对SS段的影响 (本质上也是数据段) D = 1 (如:PUSH POP CALL) 使用32个堆栈指针ESP D = 0 (如:PUSH POP CALL) 使用16个堆栈指针SP :向下拓展的数据段 D = 1 段上线为4GB D = 0 段上线为64KB 答:DPL是段的权限级别,每段固定 CPL是当前进程的权限级别CS段和SS段的后两位 RPL是过程对段访问的请求权限,每段选择子都有自己的RPL
答:就像我们用读写权限打开文件一样,有时只用只读权限打开以避免出错。
答:数据段 CPL<=DPL且RPL<=DPL 代码段 非一致代码段 CPL==DPL且RPL<=DPL 一致代码段 CPL>=DPL
答:一致代码段的高权限不能访问低权限,只能访问低权限 要求非一致代码段的权限必须相等 无论哪种操作都不对CPL只有通过调用门才能提权
答:JMP FAR / CALL FAR / RETF / INT /IRETED JMP / CALL / JCC / RET(不修改CS)
答:1.段选择子的拆分 2.查表得到段落描述符 只有四种情况可以跳转(代码段、调用门、TSS任务段、任务门) 3.权限检查 4.加载段描述符 5.代码执行
答:jmp far只是段与段之间的跳转,但不能提权,因为提权要换栈,涉及SS和ESP的保存 call far提权远跳转可以保存寄存器的值
跨段不提权: 跨段提权: 答:TSS段给的
答:它就像一块内存,一个核一份,填满了ESP在线程切换时有什么变化?TSS创建时每个线程的值TSS准备好的值准备好了 每个线程有两个堆栈,每个线程的0环堆栈在TSS中告诉你了,Windows给我们系统TSS填好了,所以调用门进入0环的时候,即使堆栈不平衡,我们还是会重新进入那个地方。
门
答:1.根据cs段选择子找到段描述符,是调用门 2.另一个代码段选择子存储在调用门描述符中 3.新段选择子指向段base 偏移地址是真正需要执行的地址
答: 答:Param.Count是参数个数,参数会在0环的堆栈中,将参数的值放入cs和esp中间
答:1.权限未改变的时候只PUSH两个值,返回地址和CS 2.权限改变的时候PUSH4个值,除返回地址和CS外,再PUSH ESP和SS 3.进入调用门的时候去的地址必须给出,但是回来的时候返回地址是从堆栈中取出来的,所以返回地址可以修改
答:IDT表叫做中断描述符表,值得注意的是GDT表第一项为NULL,但是IDT表第一项不为NULL,IDT表中包含了三种描述 符,任务门描述符、中断门描述符、陷阱门描述符
答:有1024个,第二级叫页表(PTT)有1024个,物理页有4096个字节 答:PDE、PTE属性决定物理页的可读写属性
答: 答:P位为有效位,为0无效,为1有效 R/W位可读写位,为0是只读,为1是可读写
答:U/S位为0是特权用户可访问,为1是普通用户也可以访问 P/S位只针对PDE,当P/S位为1时,PDE直接指向物理页,没有PTE,低22位为页内偏移,页大小为4MB A位是否被访问过,访问过为1 D位是否被写过,写过为1
答:INT E
答: 答:页目录表基址C0300000,页表基址C0000000
答: 答:12是因为页的大小还是4KB,所以需要12位 第二个9是因为页表的大小不变还是4096字节,但是现在一个PTE就占8字节,所以只有9 第一个9同理 2是将PBPT划分为4个
答: 答:G为对于PTE有意义, 当G位为0时,表示是进程独享物理页,由VirtualAlloc分配 当G为位1时,表示是全局页,由CreateFileMapping分配
答: 答:XD位是为了补充可执行这个条件,XD位为1时,不可执行,程序会卡死 答:PWT位为1,在存储CPU缓存时也同时往内存写数据;为0只在CPU缓存中写入 PCD位为1,禁止写入CPU缓存;为0时可以写入
TLB
答:为了保存方便快速快速访问,保存了线性地址与物理地址的对应关系和属性,统计是为了进行更换时参考,一页只有一个 切记:跟G位没有关系,G位决定的是全局还是局部 答:有4种,大页数据表缓存、大页代码表缓存,一般页表数据缓存、一般页表代码缓存
答:它是特权指令,需要在0环使用,清除某个线性地址TLB的记录
中断与异常
答:CLI清空当前的IF位,STI设置当前的IF位
答:分为可屏蔽中断(INTR)和不可屏蔽中断(NMI) 不可屏蔽中断走INT 2,可屏蔽中断由IRQ决定 答:中断请求级别 答: 答:CR0 PE位决定启用段的机制,PG决定启用页的机制,PG开启时PE必须开启 WP位决定超级用户对地址的写权限的总开关,为0无限制,为1限制,但是地址可写时也是可以写入 CR1 保留 CR2 对于发生异常时存放异常地址 CR3 存放页目录表地址 CR4 PAE决定是什么分页模式,为0是10-10-12分页,为1是2-9-9-12分页模式 PSE是PS的总开关,PSE为0时,不管PS为什么都是小页,只有PSE开启时,PS为1才是大页 答:在CPU与内存之间,速度比内存要快 CPU缓存是 物理地址<---->内容 TLB是 线性地址<---->物理地址
答:中断一般是由硬件触发的,异常是由CPU引起的(如除0)
PEB与TEB
答:是三环用来查看进程模块的, TEB的位置在fs:[0x0]存储 PEB的位置在fs:[0x30]的位置 PEB其中成员指向3个链表的结构体,三个链表都起作用
驱动编程
分页与非分页内存
答:分页内存是可以放到硬盘上的,而非分页内存是必须存放在物理页上。
答:数据类型 typedef unsigned char UCHAR; typedef unsigned short USHORT; typedef unsigned long ULONG; NTSTATUS返回值 STATUS_SUCCESS 0x00000000 成功 STATUS_INVALID_PARAMETER 0xC000000D 参数无效 STATUS_BUFFER_OVERFLOW 0x80000005 缓冲区长度不够 异常处理 __try{ //可能出错的代码 } __except(filter_value) { //出错时要执行的代码 } 答:四步,安装 执行 卸载函数 卸载
答:是一个循环链表
答: nt!_DRIVER_OBJECT +0x000 Type : Int2B +0x002 Size : Int2B +0x004 DeviceObject : Ptr32 _DEVICE_OBJECT +0x008 Flags : Uint4B +0x00c DriverStart : Ptr32 Void +0x010 DriverSize : Uint4B +0x014 DriverSection : Ptr32 Void //_LDR_DATA_TABLE_ENTRY +0x018 DriverExtension : Ptr32 _DRIVER_EXTENSION +0x01c DriverName : _UNICODE_STRING +0x024 HardwareDatabase : Ptr32 _UNICODE_STRING +0x028 FastIoDispatch : Ptr32 _FAST_IO_DISPATCH +0x02c DriverInit : Ptr32 long +0x030 DriverStartIo : Ptr32 void +0x034 DriverUnload : Ptr32 void +0x038 MajorFunction : [28] Ptr32 long
nt!_LDR_DATA_TABLE_ENTRY +0x000 InLoadOrderLinks : _LIST_ENTRY +0x008 InMemoryOrderLinks : _LIST_ENTRY +0x010 InInitializationOrderLinks : _LIST_ENTRY +0x018 DllBase : Ptr32 Void +0x01c EntryPoint : Ptr32 Void +0x020 SizeOfImage : Uint4B +0x024 FullDllName : _UNICODE_STRING +0x02c BaseDllName : _UNICODE_STRING +0x034 Flags : Uint4B +0x038 LoadCount : Uint2B +0x03a TlsIndex : Uint2B +0x03c HashLinks : _LIST_ENTRY +0x03c SectionPointer : Ptr32 Void +0x040 CheckSum : Uint4B +0x044 TimeDateStamp : Uint4B +0x044 LoadedImports : Ptr32 Void +0x048 EntryPointActivationContext : Ptr32 Void +0x04c PatchInformation : Ptr32 Void
三环与0环通信
答:是0环类似于消息的一个结构体,需要与设备对象对应
答:1.创建设备 IoCreateDevice 2.设置交互方式 在设备对象的Flags中 3.创建符号链接 IoCreateSymbolicLink 4.设置派遣函数 在驱动对象的MajorFunction结构体中 5.3环程序通讯 IoGetCurrentIrpStackLocation获取IRP 6.卸载设备与符号链接
答:发生异常时,会检测VAD树中的内存类型,如果是写拷贝会拷贝一份内存