内核学习记录【保护模式与驱动编程】

看前须知

从今天起开始记录文章,你我共同学习,体会学习的快乐。因为之前这些东西我都在本地记录,所以一次发布的比较多。我个人比较喜欢以问答的方式记录学习,所以可能如果大家光看我的文章是看不懂,你可以把我文章当成是已经学习过后进行快速复习的一种途径,文章也是按照学习路线进行书写的。当然有些我个人感觉很简单或者不重要的我就没有记录,大家也可以提出,方便你我共同进步。

学习的过程就是不断遗忘不断回顾的过程,所以不用担心学的扎实后又遗忘了,多看多回顾就会越来越深刻。

保护模式

学习保护模式意义

问:为什么学习x86,不学习x64?
答:因为x64向下兼容,学习了x86能更好的理解x64体系

问:x86有哪几种模式?
答:实模式、保护模式、虚拟8086模式

问:为什么要学习保护模式?
答:学习保护模式才能真正理解内核,不然只是停留在API层面

问:保护模式保护什么?
答:内存、特权指令

问:保护模式通过什么机制进行保护?
答:段的机制、页的机制

问:为什么不先学习段的机制?
答:因为段的机制比较复杂,只有学习段寄存器才能理解段的机制

段寄存器

问:段寄存器是什么?有哪些?
答:段寄存器是访问某一地址时的一个前缀寄存器,段寄存器有8个,分别为ES CS SS DS FS GS LDTR TR

问:段寄存器的结构是什么样的?
答:Attribute属性 Limit长度 Base开始位置
在这里插入图片描述
问:段寄存器如何进行读写?
答:通过16位寄存器,mov、SLDT/LLDT、STR/LTR指令进行读写,读只能读16位,写能写96位

问:段寄存器的成员各属性是什么?
答:红色部分机器不同数值可能不同,GS寄存器Windows没有进行使用在这里插入图片描述
问:为什么说读能读16位,写能写96位呢?
答:
测试Attribute:通过对cs:[400000h] 和ds:[400000h]地址写入数据证明有Selector
测试Base: 通过对fs:[0]和ds:[0]进行写入数据证明有Base
测试Limit: 通过对fd:[1000]和ds:[0x7FFDE000+0x1000]进行写入数据证明有limit
综上所述,在进行写的时候写入的是96位

问:写段寄存器时,只有16位,其余80位填什么?
答:通过GDT表找到段描述符,加载到段寄存器中

段描述符

问:GDT表和LDT表是什么?
答: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

问:为什么没有LCS指令?
答:CS寄存器不能随意修改,需要和EIP一起修改,所以没有这种指令

问:段描述符中P位和G位什么含义?
答:P位决定段描述符是否有意义,G位决定limit剩余的12位填0还是1,G为0,limit为000FFFFF,G为1,limit为FFFFFFFF

问:段描述符S位和type位什么含义?
答:S位为0说明是系统段描述符,S为1说明是数据/代码段描述符,A表示是否访问过
在这里插入图片描述在这里插入图片描述
问:数据/代码段中第10位什么含义?
答:在数据段中表示拓展方向,为0是向上拓展(左图红色区域),为1是向下拓展(右图红色区域)
在代码段中表示是否为一致代码段,为0为非一致代码段,为1为一致代码段
在这里插入图片描述
问:D/B位有什么作用?
答:
情况一:对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、RPL分别是什么?
答:DPL是段的权限级别,每个段是固定的
CPL是当前进程权限级别,是CS段和SS段的后两位
RPL是进程对段访问的请求权限,每个段选择子有自己的RPL

问:为什么都有CPL还要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 与call far与什么区别?
答:jmp far只是段与段之间进行跳转,但是不能提权,因为提权要换栈,涉及到SS和ESP的保存
call far可以进行提权远跳转,他可以保存寄存器的值

跨段不提权:
在这里插入图片描述
跨段提权:
在这里插入图片描述问:ESP和SS从哪里获取到呢?
答:TSS段给的

问:什么是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表是什么?
答:IDT表叫做中断描述符表,值得注意的是GDT表第一项为NULL,但是IDT表第一项不为NULL,IDT表中包含了三种描述 符,任务门描述符、中断门描述符、陷阱门描述符

问:中断门的结构是什么样?
答:![在这里插入图片描述](https://img-blog.csdnimg.cn/c1b7458ef804412ea1692714da858916.png

问:如何触发IDT表的使用?
答:使用INT指令,后面跟的是IDT表的索引

问:INT N指令在权限切换和不切换时堆栈是什么样?
答:权限不变:返回地址 EFLAG CS
权限变化:返回地址 CS EFLAG ESP SS

问:在调用门、中断门中返回时用什么指令?
答:调用门用retf,中断门用iret/iretd

问:iret和iretd的区别是什么?
答:iret是32位16位都能使用,iretd只能32使用

问:在中断门中,描述符中的段选择子查哪个表?
答:查GDT表

问:陷阱门是什么?
答:在这里插入图片描述问:陷阱门和中断门的区别是什么?
答:中断门会将EFALG寄存器的IF位清0,陷阱门不会改变IF位

问:IF位有什么用?
答:IF位为0可以屏蔽可屏蔽中断,可屏蔽中断如键盘按下等,不可屏蔽中断如断电,在主板上有电容,当断电的时候,CPU还会工作一段时间用于处理中断

问:CPU可以停下来吗?
答:停不下来,就算没有线程跑的时候,也会有空闲线程让CPU不断运行

问:直接关机走的是什么中断?
答:是INT 2

问:如果在走中断的时候又出错了,走什么?
答:INT 8

问:TSS是什么?
答:
在这里插入图片描述
问:TSS段描述符是什么?
答:
在这里插入图片描述
问:TSS、TR、TSS段描述符之间什么关系?
答:TSS是一块内存,地址大小在TR寄存器中的base、limit给出,TR寄存器的值是由GDT表中的TSS段描述符给出

问:如何将TSS段描述符加载到TR寄存器中?
答:使用LTR和STR进行加载和读取,但是LTR是特权指令,只能在0环使用,STR不是特权指令

问:Windows如何使用TSS的?
答:Windows只使用了TSS中SS0、ESP0,其他的没有使用,它使用堆栈进行模拟

问:我们如何使用TSS?
答:使用jmp far指令,当段选择子指向的段描述符是TSS段描述符就会加载TSS到TR寄存器,然后就会调用TSS将其他的寄存器进行替换

问:使用jmp far 和call far指令进行TSS实验时,有什么区别?
答:区别一:jmp far不会改变TSS中的Previous Task Link,call far会填写上一个寄存器
区别二:jmp far不会改变NT位,call far会将NT位置1

问:NT位有什么用?
答:当NT位为0,iret指令将从堆栈中取
当NT位为1,iret指令会找Previous Task Link

问:有效地址、线性地址、物理地址、都是什么?
答:
如下指令:
MOV eax,dword ptr ds:[0x12345678]
其中,0x12345678 是有效地址
ds.Base + 0x12345678 是线性地址

问:CR3的作用是什么?
答:存放的是物理地址,指向一个表,通过这个表能将线性地址放到物理页上

问:物理地址怎么找呢?
答:通过CR3寄存器,里面存放的就是索引表,通过索引表依次找到对应的物理地址
在这里插入图片描述
注意:第一级和第二级是地址,需要乘4+CR3

问:第一级、第二级、物理页是什么?
答:第一级叫页目录表(PDT)有1024个,第二级叫页表(PTT)有1024个,物理页有4096个字节
在这里插入图片描述
问:一个地址是否可读写由什么决定?
答:PDE、PTE属性决定物理页的可读写属性

问:PDE与PTE的属性是什么?
答:
在这里插入图片描述在这里插入图片描述问:P位与R/W位的含义是什么?
答:P位为有效位,为0无效,为1有效
R/W位可读写位,为0是只读,为1是可读写

问:U/S位与P/S位、A位、D位的含义是什么?
答:U/S位为0是特权用户可访问,为1是普通用户也可以访问
P/S位只针对PDE,当P/S位为1时,PDE直接指向物理页,没有PTE,低22位为页内偏移,页大小为4MB
A位是否被访问过,访问过为1
D位是否被写过,写过为1

问:缺页异常走几号中断?
答:INT E

问:缺页异常有四种情况,都是什么原因?
答:
在这里插入图片描述
问:页目录表基址与页表基址是多少?
答:页目录表基址C0300000,页表基址C0000000

问:物理页的真实样子是什么?
答:
在这里插入图片描述
问:2-9-9-12分页每位代表什么?
答:12是因为页的大小还是4KB,所以需要12位
第二个9是因为页表的大小不变还是4096字节,但是现在一个PTE就占8字节,所以只有9
第一个9同理
2是将PBPT划分为4个

问:2-9-9-12分页模式什么样子?
答:
在这里插入图片描述问:G位什么含义?
答:G为对于PTE有意义,
当G位为0时,表示是进程独享物理页,由VirtualAlloc分配
当G为位1时,表示是全局页,由CreateFileMapping分配

问:PDPTE、PDE、PTE的结构是什么?
答:
在这里插入图片描述
问:PDE、PTE在2-9-9-12分页下的XD位是什么?
答:XD位是为了补充可执行这个条件,XD位为1时,不可执行,程序会卡死
在这里插入图片描述
问:PWT位和PCD位的作用是什么?
答:PWT位为1,在存储CPU缓存时也同时往内存写数据;为0只在CPU缓存中写入
PCD位为1,禁止写入CPU缓存;为0时可以写入

TLB

问:TLB是什么样子,是干嘛的?
答:为了保存方便快速快速访问,保存了线性地址与物理地址的对应关系和属性,统计是为了进行更换时参考,一页只有一个
切记:跟G位没有关系,G位决定的是全局还是局部
在这里插入图片描述
问:TLB有几种,各是什么?
答:有4种,大页数据表缓存、大页代码表缓存,一般页表数据缓存、一般页表代码缓存

问:invlpg指令做什么的?
答:它是特权指令,需要在0环使用,清除某个线性地址TLB的记录

中断与异常

问:对IF位操作的指令是什么?
答:CLI清空当前的IF位,STI设置当前的IF位

问:中断分为什么?
答:分为可屏蔽中断(INTR)和不可屏蔽中断(NMI)
不可屏蔽中断走INT 2,可屏蔽中断由IRQ决定
在这里插入图片描述
问:IRQL是什么?
答:中断请求级别
在这里插入图片描述
问:各种异常所对应的中断号是什么?
答:
在这里插入图片描述
问:CR0~CR4控制寄存器都是做什么的?
答: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缓存是什么?与TLB有什么关系?
答:在CPU与内存之间,速度比内存要快
CPU缓存是 物理地址<---->内容
TLB是 线性地址<---->物理地址

问:中断和异常的区别是什么?
答:中断一般是由硬件触发的,异常是由CPU引起的(如除0)

PEB与TEB

问: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) {
//出错时要执行的代码
}
在这里插入图片描述
问:驱动加载分为几步?
答:四步,安装 执行 卸载函数 卸载

问:内核模块其实是什么?
答:是一个循环链表

问:内核DRIVER_OBJECT和_LDR_DATA_TABLE_ENTRY结构体是什么?
答:
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环通信

问:IRP是什么?
答:是0环类似于消息的一个结构体,需要与设备对象对应

问:3环与0环设备通信的过程实施什么?
答:1.创建设备 IoCreateDevice
2.设置交互方式 在设备对象的Flags中
3.创建符号链接 IoCreateSymbolicLink
4.设置派遣函数 在驱动对象的MajorFunction结构体中
5.3环程序通讯 IoGetCurrentIrpStackLocation获取IRP
6.卸载设备与符号链接

问:写拷贝是什么?
答:发生异常时,会检测VAD树中的内存类型,如果是写拷贝会拷贝一份内存

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值