01 段寄存器在16位汇编时是什么含义,在32位时是什么含义?
答:段基址;段寄存器在32位下:段选择子 32位基址+32位段长度+16位属性+16位选择子
02 什么是段描述符,存在于哪里?
答:段描述符是GDT和LDT中的一个数据结构项,用于向处理器提供有关一个段的位置,大小以及访问控制的状态信息,每个段描述符的长度是8个字节,含有3个主要的字段:段基地址 段限长 段属性;描述符表中。
03 什么是段选择子,请详细描述段选择子的结构
答:段选择子是段寄存器可见部分存储的值:13位描述符表索引+1位TI+2位RPL
04 请简述DPL,CPL,RPL的含义,谈一谈你的理解
答:
DPL:描述符特权(Descriptor Privilege Level)
存储在描述符中的权限位,用于描述代码的所属的特权等级,也就是代码本身真正的特权级。一个程序可以使用多个段(Data,Code,Stack)也可以只用一个code段等。正常的情况下,当程序的环境建立好后,段描述符都不需要改变——当然DPL也不需要改变,因此每个段的DPL值是固定。
RPL:请求特权级RPL(Request Privilege Level)
RPL保存在选择子的最低两位。 RPL说明的是进程对段访问的请求权限,意思是当前进程想要的请求权限。RPL的值由程序员自己来自由的设置,并不一定RPL>=CPL,但是当RPL<CPL时,实际起作用的就是CPL了,因为访问时的特权检查是判断:EPL=max(RPL,CPL)<=DPL是否成立,所以RPL可以看成是每次访问时的附加限制,RPL=0时附加限制最小,RPL=3时附加限制最大。所以你不要想通过来随便设置一个rpl来访问一个比cpl更内层的段。
CPL:当前任务特权(Current Privilege Level)
表示当前正在执行的代码所处的特权级。CPL保存在CS中的最低两位,是针对CS而言的。当选择子成功装入CS寄存器后,相应的选择子中的RPL就变成了CPL。因为它的位置变了,已经被装入到CS寄存器中了,所表达的意思也发生了变——原来的要求等级已经得到了满足,就是当前自己的等级。
05 段描述符的S位与TYPE位代表什么含义?
答:s与TYPE代表含义:
s=0 系统段 1代码段或数据段
TYPE:
0EWA 数据段 扩展方向 是否可写 访问位
1CRA 代码段 一致性 可读 访问位
06 在windbg中如何查看IDT?如何查看GDT?
答:r idtr;r gdtr
========================
1.windbg应该安装在被调试机上,还是安装在调试机上?
答:调试机上
2.在代码中插入一个int 3指令有什么用?
答:中断,方便调试
3.请简单叙述驱动对象,设备对象,IRP之间的关系
答:
每个驱动程序只有一个驱动对象,每个驱动程序可以生成若干个设备对象,这些设备对象从属于一个驱动对象。驱动对象包含n个设备对象,IRP请求是发送给设备对象的。
4.windows有哪几种驱动开发模型
答:
NT
WDM
WDF
5.什么是IRQL?
答:Interrupt ReQuest Level 中断请求级别
6.设备通讯有三种方式,是哪三种?有什么区别?
答:
缓冲区设备读写方式
直接读写方式
其他方式
具体什么方式取决于创建完设备对象后,设置其flags的值
DO_BUFFERED_IO
DO_DIRECT_IO
0
==========================
1.请叙述IRP和IRP栈的关系
答:
一个IRP是从非分页内存中分配的可变大小的结构,它包括两部分:IRP首部(也称为头部)和I/O堆栈位置(IrpStackLocation)。这两部分都是由I/O Manager(I/O管理器)建立的。IRP结构中的内容并不固定,随着请求类型的不同而有较大不同。
IrpStackLocation的主要目的是,保存一个I/O请求的函数代码和参数。通过检查堆栈位置的MajorFunction字段,驱动程序能够确定执行什么操作及如何解释Parameters共用体(union)字段的内容。
对于一个直接发送到最低级驱动程序的请求,其相应的IRP只有一个I/O堆栈位置。对于发送到较高级驱动程序的请求,I/O 管理器建立一个在每个驱动程序层有不同I/O堆栈位置的IRP。换句话说,I/O StackLocation的数量实际上是参与I/O 请求的I/O 层的数量,或者是设备栈的深度(depth).只允许层次结构中的每个驱动程序接触它自己的I/O Stack Location.如果它想调用一个更低级的驱动程序,它必须保证新的I/O StackLocation在它的下面的位置被正确地建立。这可以使用如IoCopyCurrentIrpStackLocationToText,IoAllcateIrp等例程来设置。
2.目前学习了哪些IRP结构体中的字段,有什么用
Irp->AssociatedIrp.SystemBuffer //输入输出缓冲区 使用DO_BUFFER_IO
Irp->IoStatus.Status //返回给用户层的状态,表示这次通信的结果
Irp->IoStatus.Information //返回给用户层的大小
Irp->UserBuffer //USER_BUFFER时的通信
Irp->MdlAddress //使用MDL映射机制时的通信
3.目前学习了哪些IO_STACK_LOCATION中的字段,有什么作用
PIO_STACK_LOCATION irpStack;
irpStack = IoGetCurrentIrpStackLocation (Irp);//从栈上取IRP信息
irpStack->Parameters.Read.Length //ReadFile/WriteFile传入的大小
irpStack->Parameters.Read.ByteOffset //ReadFile/WriteFile从哪读写偏移
irpStack->Parameters.DeviceIoControl.IoControlCode//控制码
irpStack->Parameters.DeviceIoControl.InputBufferLength//输入缓冲区大小
irpStack->Parameters.DeviceIoControl.OutputBufferLength//输出缓冲区大小
irpStack->MajorFunction//分发函数数组
irpStack->MinorFunction
irpStack->DeviceObject
irpStack->FileObject
4.在内核编程中,文件路径前应该加上什么
答:\??\
5.什么是EPROCESS,PEB,KPROCESS,ETHREAD,TEB
答:
EPROCESS 进程执行体块
KPROCESS位于比EPROCESS更底层的内核层中,KPROCESS被内核用来进行线程调度使用
ETHREAD 线程控制块
TEB(Thread Environment Block,线程环境块)系统在此TEB中保存频繁使用的线程相关的数据。位于用户地址空间,在比 PEB 所在地址低的地方。进程中的每个线程都有自己的一个TEB。一个进程的所有TEB都以堆栈的方式,存放在从0x7FFDE000开始的线性内存中,每4KB为一个完整的TEB,不过该内存区域是向下扩展的。在用户模式下,当前线程的TEB位于独立的4KB段,可通过CPU的FS寄存器来访问该段,一般存储在[FS:0]。在用户态下WinDbg中可用命令$thread取得TEB地址。
PEB(Process Environment Block,进程环境块)存放进程信息,每个进程都有自己的PEB信息。位于用户地址空间。在Win 2000下,进程环境块的地址对于每个进程来说是固定的,在0x7FFDF000处,这是用户地址空间,所以程序能够直接访问。准确的PEB地址应从系统的EPROCESS结构的0x1b0偏移处获得,但由于EPROCESS在系统地址空间,访问这个结构需要有ring0的权限。还可以通过TEB结构的偏移0x30处获得PEB的位置,FS段寄存器指向当前的TEB结构:
mov eax,fs:[0x30]
mov PEB,eax
在用户态下WinDbg中可用命令$proc取得PEB地址。
================================
1、3环函数进入0环我们说有两种方式,请叙述是哪两种方式?
答:
老方法:
大部分函数都会流向NTdll.dll,并最终通过Ntdll.dll进入0环
进入零环的一些途径有:调用门,中断门,任务门,陷阱门
在老式的CPU上,应用程序从3环进入0环实际上就是通过中断门
在IDT的0x2e的位置上,至今还留存着当初进入0环的起始地址。
进入零环就是需要提供四个新的寄存器的值:CS,EIP,SS,ESP
通过中断门进入0环时,CS,EIP是由门描述符提供的。SS,ESP是由TSS段提供的。需要读取内存
新方法:
新式进入0环的方式,称之为快速系统调用-即SYSENTER指令,经过专门的优化,能够以最佳性能有ring3层切换到ring0层。
CPU支持sysenter指令时,CPU会将MSR寄存器中的值直接写入相关的寄存器,没有读内存的过程,快速调用。
2、SYSENTER所需要的ESP,EIP,CS分别放在什么地方?
答:MSRs 175 176 174
3、系统调用进入内核层后,eax中存放的是什么?edx中存放的是什么?
答:调用号,调用内核函数的参数
4、SSDT是什么?我们编程时,如何才能找到SSDT?
答:系统服务描述表,win7_32下直接声明KeServiceDescriptorTable就可以使用
5、FS:[0]在用户层指向哪里?在内核层又是什么?
答:
当线程运行在R3下时,FS指向的段是GDT中的0x3B段.该段的长度为4K,基地址为当前线程的线程环境块(TEB),所以该段也被称为“TEB段”.
当线程运行在R0下时, FS指向的段是GDT中的0x30段.该段的长度也为4K,基地址为0xFFDFF000.该地址指向系统的处理器控制区域(KPCR).这个区域中保存这处理器相关的一些重要数据值,如GDT、IDT表的值等等.
6、请简要叙述Kifastcall中如何得到的SSDT?
答:在windbg中反编译kifastcallentery,跟踪调函数,函数中用Fs:[0]指向KPCR中获取——KTHREAD,然后从_KTHREAD中获取serviceTable系统服务描述表。
========================
1、什么是内核重载
答:内核重载,就是将内核文件即: ntkrnlpa. exe 自己加载一-份到内存,并运行它,这样的好处可以避免一切HOOK,如SSDT,InLineHook 等等
2、请写出内核重载的步骤
答:
1.将文件加载到内存
2.将文件展开到内存中的状态
3.通过LDR链获取ntkrnlpa. exe的基址
4.修复重定位
5.修复SSDT
6.拦截系统调用 让谁走新内核让谁走老内核