![](https://img-blog.csdnimg.cn/20201014180756927.png?x-oss-process=image/resize,m_fixed,h_64,w_64)
Windows内核编程
QQQqQqqqqrrrr
这个作者很懒,什么都没留下…
展开
-
[windows内核]分析MmIsAddressValid
如果有过驱动编程经验的人一定会了解这个函数MmIsAddressValid(),这个函数的作用简单来说就是验证一个地址可否使用,因为在驱动编程里稍有不慎就会导致BSOD,会在读取和写入数据的时候都要非常谨慎,做好充足的判断。这是MSDN中的解释https://docs.microsoft.com/en-us/windows-hardware/drivers/ddi/ntddk/nf-ntddk-mmisaddressvalidIf no page fault would occur from r原创 2020-09-19 16:56:47 · 3139 阅读 · 0 评论 -
[windows内核]PWT&PCD
更多详细解释请看手册第三卷: 4.9 PAGING AND MEMORY TYPING手册第三卷: CHAPTER 11 MEMORY CACHE CONTROL在学习PDE与PTE的属性时,我们对两个位做只做了简单的说明,并没有说明其实际作用,那就是今天要学习的PWT位与PCD位CPU缓存描述:CPU缓存是位于CPU与物理内存之间的临时存储器,它的容量比内存小的多,但是交换速度(读写速度)比内存要快得多CPU缓存可以做的很大,有几K、几十K、几百K、甚至上M,这决定于CPU的版本原创 2020-09-06 21:43:55 · 618 阅读 · 0 评论 -
[windows内核]控制寄存器
更详细的内容请看手册中第三卷中的2.5 CONTROL REGISTERS更多参考《软件调试第二版:卷1硬件基础》 中的第2.44章 控制寄存器控制寄存器描述:控制寄存器有五个,分别是:Cr0 Cr1 Cr2 Cr3 和Cr4,在64位模式下还有个Cr8Control registers (CR0, CR1, CR2, CR3, and CR4; see Figure 2-7)Register CR8 is available in 64-bit mode only.控原创 2020-09-06 16:06:57 · 724 阅读 · 0 评论 -
[windows内核]中断与异常处理
详细解释在手册中的:CHAPTER 6INTERRUPT AND EXCEPTION HANDLING一、中断描述:中断通常是由CPU外部的输入输出设备(硬件)所触发的,供外部设备通知CPU“有事情需要处理”,因此又叫中断请求(Interrupt Request)中断请求的目的是希望CPU暂时停止执行当前正在执行的程序,转去执行中断请求所对应的中断处理例程(中断处理程序在哪有IDT表决定)80x86有两条中断请求线:可屏蔽中断线,称为INTR(Interrupt Requi原创 2020-09-05 23:56:12 · 1998 阅读 · 0 评论 -
[windows内核]TLB
地址解析当我们通过一个线性地址访问一个物理页(比如:MOV EAX,[0x12345678])时,实际上CPU未必只读了4个字节。10-10-12分页CPU先通过线性地址找到对应的PDE:4个字节CPU再通过PDE和线性地址找到PTE:4个字节最后再通过PTE找到对应物理页:4个字节一共访问了12个字节,如果跨页可能更多。2-9-9-12分页找到PDPTE:8个字节找到PDE:8个字节找到PTE:8个字节最后找到物理页:4个字节一共访问了20个字节,如果跨页可能更多。为了提高访问原创 2020-08-30 02:15:19 · 521 阅读 · 0 评论 -
[windows内核]2-9-9-12分页
回顾之前我们解了10-10-12分页方式,在这种分页方式下物理地址最多可达4GB。但随着硬件的发展,4GB的物理地址范围已经无法满足要求Intel在1996年就已经意识到这个问题了,所以设计了新的分页方式,也就是我们这次要说的2-9-9-12分页,又称为PAE(物理地址扩展)分页。具体细节可以再手册第3卷中的4.4 PAE PAGING查看10-10-12分页 原理Intel认为一张页的大小为4K是比较合理的,所以先确定页的大小为4K,4KB等于4096个字节,也就是2的12次方,所以32位原创 2020-08-17 02:02:06 · 772 阅读 · 0 评论 -
[windows内核]页目录表基址/页表基址
如果系统要保证某个线性地址是有效的,那么必须为其填充正确的PDE与PTE.如果我们想填充PDE与PTE,那么必须能够访问PDT与PTT,这样就存在2个问题:系统已经为我们访问PDT与PTT挂好了PDE与PTE,我们只用找到这个线性地址就可以了系统是怎么帮我们挂好PDE与PTE的?注意:CR3中存储的是物理地址,不能在程序中直接读取的。如果想读取,也要把Cr3的值挂到PDT和PTT中才能访问,那么怎么通过线性地址访问PDT和PTT呢?一.页目录表基址页目录表基址 = 线性地址:0xC0原创 2020-08-15 17:27:13 · 2579 阅读 · 0 评论 -
[windows内核]PDE&PTE
Cr3描述:在所有的寄存器中,只有Cr3存储的是物理地址,其它寄存器存的都是线性地址Cr3所存储的物理地址指向了一个页目录表(PDT)在Windows中,一个页的大小通常为4KB,即一个页可以存储1024个页目录表项(PDE)下面是手册中的描述在第3卷2.5 CONTROL REGISTERS物理页结构图:注意:但其实上面这种结构方式是错误的,这个以后再解释,先这样理解PDE(页目录表项)描述:页目录表(PDT)的每一项元素称为页目录表项(PDE)每个页目录表项指向一个页表(原创 2020-08-10 01:53:36 · 2275 阅读 · 0 评论 -
[windows内核]10-10-12分页
基本概念4GB内存空间我们都了解过每个进程都有独立的4GB空间4GB的虚拟内存结构:虚拟内存地址范围 描述0x00000000~0x0000FFFF 64kb大小的空指针区域,当然就不可以访问了0x00001000~0x7FFFFFFF 加上上述的空指针区域,低2GB的用户态空间0x80000000~0xFFFFFFFF 高2GB的内核态空间但这个4GB空间并不是完全都使用或者真实存在的。实际上,进程被分配到的“4GB内存空间”只是虚拟的的内存空间,并不是指真正意义上的物理内存,虚拟原创 2020-08-09 20:57:55 · 818 阅读 · 0 评论 -
[windows内核]任务门
任务门存在于IDT表中,下面是任务门的段描述符下图是任务门触发的时候的执行过程下面总体概述一下如何使用任务门来进行任务切换:1.当中断发生时,处理器用中断号乘以8作为索引访问中断描述符表。当它发现这是一个任务门描述符时,就知道应当发起任务切换。2.取出任务门描述符。3.从任务门描述符中取出新任务的TSS选择子;4.再用TSS选择子访问GDT,取出新任务的TSS描述符5.在执行新任务前,处理器会把当前任务状态保存起来。也就是将当前任务的状态保存到TR寄存器指向的TSS状态段。6.然后处理器原创 2020-08-02 20:22:08 · 427 阅读 · 0 评论 -
[windows内核]任务状态段
任务状态段(Task-state segment, TSS)之前讲到了,因为SS段的CPL必须与CS段的CPL一致,所以当使用调用门、中断门或陷阱门并产生权限切换时,必然会引起堆栈的切换。通过门描述符的学习可以知道CPL切换时,CS由门描述符决定,但是新的SS和ESP由何而来的呢?答案是 任务状态段(Task-state segment, TSS)任务状态段是一块大小为104字节的内存,它保存了一些重要的值图在手册中7.2.1 Task-State Segment (TSS)抽象成结构体就是下面这原创 2020-08-02 01:05:15 · 431 阅读 · 0 评论 -
[windows内核]陷阱门
陷阱门和中断门差不多,都是存在于IDT表中的下面是陷阱门的段描述符构造虽然陷阱门和中断门差不多,但是具体还是有区别的,区别如下6.12.1.2Flag Usage By Exception- or Interrupt-Handler ProcedureWhen accessing an exception or interrupt handler through either an interrupt gate or a trap gate, the processorclears the原创 2020-07-19 14:37:54 · 495 阅读 · 0 评论 -
[windows内核]中断门
要说中断门,不得不先说一个概念就是IDT表(中断描述符表),用来存放中断门描述符的地方,IDT也用来存放任务门,以及陷阱门描述符,具体在手册中第三卷:6.11 IDT DESCRIPTORS我们在windbg中可以使用如下指令查看idt表地址以及表的大小下图是中断门描述符的格式字段的具体含义如下现在我们了大概了解了中断门描述符,我们再来了解一下异常和中断处理大概意思是说处理器对异常和中断调用的处理方式与用 CALL 指令调用例程和任务的处理十分相近。响应异常和中断时,处理器将异常或中断原创 2020-07-12 22:58:28 · 679 阅读 · 0 评论 -
[windows内核]调用门
Windows系统并没有使用调用门,但是没用并不等于没有,所以我们这次主要是靠自己实现,来完成这次的探究关于调用门的说明在手册第三卷的5.83中下面是调用门的段描述符格式可以看到有些值是固定的,这是调用门特有的,我们来逐个看一下段描述符格式里的各个意思The segment selector field in a call gate specifies the code segment to be accessed. The offset field specifies theentry p原创 2020-07-05 16:54:23 · 698 阅读 · 0 评论 -
[windows内核]长调用与短调用
相信大家都不陌生call指令了,但除了常见的段内调用(CS当前指向的段)外,还有其他几种不同的调用,手册上说明是有4种,在第 2A 卷: 指令集参考(A-L)中的CALL—Call Procedure其中我们要说的另一种就是Far Call(段间调用),Far Call也分为两种类型,一种是特权级别相同的段间调用,一种是特权级别不同的段间调用我们先来看看段内调用和段间调用的区别,在手册中第 1 卷: 基本架构的6.31中共同点是都会改变Stack和EIP,不同点是Far Call还会改变CS并且原创 2020-06-22 00:31:48 · 500 阅读 · 0 评论 -
[windows内核]代码段跳转实验
本次实验是为了加深对跨段跳转流程的印象首先选一个已有的非一致代码段的段寄存器,将其复制过来,写入一个GDT表里无效的位置中,怎么区分段寄存器是否是代码段前面已经有了,这里不再重复成功写入之后打开R3调试器输入汇编指令修改JMP FAR 004B:0040130C4B是因为我们刚才修改GDT表里段寄存器的位置在第9个,RPL不变如果成功执行那么cs和eip都会改变我们单步一下可以看到成功执行了如果我们把我们修改的段寄存器DPL修改为0是否还能执行成功呢我们来尝试一下还是原来的位原创 2020-06-21 02:34:36 · 345 阅读 · 0 评论 -
[windows内核]代码段跳转流程
代码段间的跳转(非调用门之类的)段间跳转,有两种情况,要跳转的是一致代码段还是非一致代码段同时修改CS和EIP的指令JMP FAR / CALL FAR / RETF / INT / IRETD注意只改变EIP的指令JMP/CALL/JCC/RET关于代码段间跳转可以在手册中5.8和5.81中有详细解释那么我们就来简单的分析一下它的代码段间跳转执行流程举一个例子JMP FAR 指令格式:JMP 0x20:0x004183D71.段选择子拆分0x20会被拆分成 0000原创 2020-06-14 22:27:17 · 334 阅读 · 0 评论 -
[windows内核]段权限检查
之前我们有提到过RPL和DPL的概念,RPL在段选择子里,DPL在段描述符里可以看到在Intle32手册里是这样解释他们的,但是关于段权限还有一个新的概念要提,也就CPL(当前特权级)简单理解就是特指CS段选择子的第1和第二位描述了当前运行的进程的特权级,举一个简单的例子使用OD打开一个程序,查看CS的段选择子拆开就是00011011 后两位就是11=3 也就是特权级别为3我们再使用内核调试器,中断下来可以看到我们的cs是8 拆开也就是1000 后两位为00=0 也就是特权原创 2020-06-01 00:42:53 · 420 阅读 · 0 评论 -
[windows内核]段描述符属性:D/B位
我们可以看一下段描述符,发现D/B位在这里也有简单的说明在下面表示了D/B位的影响,下面我们就来详细说一下具体的影响情况一:对CS段的影响D = 1 采用32位寻址方式D = 0 采用16位寻址方式前缀67 改变寻址方式(人为改变默认寻址方式)情况二:对SS段的影响D = 1 隐式堆栈访问指令(如:PUSH POP CALL)使用32位堆栈指针寄存器ESPD = 0 隐式堆栈访问指令(如:PUSH POP CALL) 使用16位堆栈指针寄存器SP情况三:向下拓展的数据段D = 1 段上原创 2020-05-30 22:24:30 · 530 阅读 · 0 评论 -
[windows内核]段描述符属性:S位_TYPE域
GDT表里的段描述符可以简单的分成两大类1.代码或者数据段描述符2.系统段描述符怎么区分这个就需要靠S位S = 1 代码段或者数据段描述符S = 0 系统段描述符我们先说S=1时候的情况,如果S位等于1那么他就是一个代码段或者数据段的描述符,我们怎么快速区分呢首先,S位在高32位的第5个字节里,也就是和这几个属性看起来是一起的我们首先前提条件就是P位是1,是有效的如果P位和S位都要同时为1那么满足条件的有以下两个(ps:DPL位只能全部为0(访问本段权限0)或者全部为1(访问本段权原创 2020-05-25 01:58:20 · 580 阅读 · 0 评论 -
[windows内核]段描述符属性:P位_G位
先说一下段描述符里属性P位的作用,也非常简洁明了,P位的作用就是决定这个段描述符是否有效P = 1 段描述符有效P = 0 段描述符无效那怎么快速确定一个段描述符是否有效呢?我们来举一个例子可以看到图中红色部分对应的高4字节,蓝色部分对应这低4字节,对应GDT表里也就是这样看可以看到我们的p位就对应低四个字节的左边第一个字节的第一个二进制位,也就是这里而我们将9拆分一下就是1001第一个二进制位为1所以这个段描述符是 有效的而快速确定的方法就是这个字节大于或者等于8,想实验一原创 2020-05-24 23:11:38 · 795 阅读 · 0 评论 -
[windows内核]段描述符和段选择子
上面我们已经提到根据段引申出来的一个概念就是GDT(Global Descriptor Table 全局描述符表)GDT表与LDT表通常情况下,在设计程序时,我们认为段寄存器为16-bit(虽然每个段寄存器事实上有一个64-bit长的不可见部分,但对于程序员来说,段寄存器就是16-bit),但是为了描述一个段,还需要【Base Address, Limit, Attr】三方面因素,它们加在一起被放在一个64-bit长的数据结构中,被称为段描述符(上面所说的缺少了80位数据,但是这里只存储64位数据是因为原创 2020-05-17 17:42:48 · 1426 阅读 · 0 评论 -
[windows内核]段寄存器属性探测
上篇说到段寄存器一共有96位,可见部分只有16位,也就是我们在od看到的段选择子,还有80位是不可见的,我们可以通过mov指令进行读写[LDTR和TR除外]段寄存器具有以下结构struct SegMent{ WORD Selector; // 段选择子 16位 可见 WORD Attributes; // 段属性 16位 不可见 只有少数几个属性位是有效的 DWORD Base // 段起始地址 32位 不可见 仅对于FS和GS有效 DWORD Limit // 段大小 32位原创 2020-05-17 01:09:05 · 606 阅读 · 0 评论 -
[windows内核]段寄存器
什么是段寄存器?其实我们平常在OD调试中就可以看到,但是不会在意的,这里显示其实是段寄存器的一部分,称为段选择子,下面我们具体会讲。还有就是我们平时在调试中经常会看到的汇编代码这里其实我们真正写入的地址是ds.base+0x12345678除了在od中显示的6个段寄存器以外其实还有2个,通常情况下,我们认为有8个段寄存器,他们分别是ES CS SS DS FS GS LDTR TR其中,后四个寄存器没有处理器定义,是由操作系统运行它们来赋予目的的。段寄存器一共有96位,可见部分只有16位原创 2020-05-16 15:25:54 · 1006 阅读 · 0 评论 -
[windows内核]保护模式
x86 CPU的三个模式:实模式、保护模式和虚拟8086模式现代的操作系统大多运行再保护模式下,所以我们重点关注在保护模式保护模式最大的特点就是拥有1.段的机制2.页的机制这些都涉及保护模式下的内核如何寻址的问题,后面我们再展开说。...原创 2020-05-16 13:46:19 · 472 阅读 · 0 评论 -
Win764位系统下使用ObRegisterCallbacks内核函数来实现进程保护
先发代码参考了:https://bbs.pediy.com/thread-200048.htm forwardbobhttps://bbs.pediy.com/thread-168023-1.htm tianhzhttp://www.cnblogs.com/aliflycoris/p/5468175.html LycorisGuard这三位大牛的代码以及原理#ifndef C...原创 2018-11-16 22:18:46 · 943 阅读 · 0 评论