Protection 6 ---- Page-Level Protection
来源:互联网 发布:淘宝苏宁易购退笔记本 编辑:程序博客网 时间:2024/05/20 05:05
页级别的保护类型
对于分页结构的保护分为两种,一种是对于访问权限的检查,一种是对于线性地址是否存在转换进行检查。
访问权限
分页结构中的一些位是用来规定页的访问权限的,例如R/W,U/S以及XD。这些位在不同的访问模式下起着不同的限制作用。对于一个线性地址的访问有两种模式:supervisor-mode以及user-mode。当CPL<3的时候是supervisor-mode,CPL==3是user-mode。下面这些规则是Intel手册中列举出来的不同的访问权限:
- supervisor-mode
- 读数据
- 可以从任何线性地址读取数据
- 可以从任何线性地址读取数据
- 写数据
- CR0.WP==0,可以向任何线性地址写数据
- CR0.WP==1,只能向地址转换过程中使用的分页结构中R/W==1的线性地址写数据
- 执行
- 32-Bit Paging或者IA32_EFER.NXE==0,访问权限依赖于CR4.SEMP
- CR4.SEMP==0,可以执行任何线性地址中的指令
- CR4.SEMP==1,只能执行转换过程中使用的分页结构的U/S==0的线性地址中的指令
- PAE Paging或者IA-32e Paging并且IA32_EFER.NXE==1,访问权限也依赖于CR4.SEMP
- CR4.SEMP==0,只能执行转换过程中使用的分页结构的XD==0的线性地址中的指令
- CR4.SEMP==0,只能执行转换过程中使用的分页结构的U/S==0并且XD==0的现行地址中的指令
- 32-Bit Paging或者IA32_EFER.NXE==0,访问权限依赖于CR4.SEMP
- 读数据
- user-mode
- 读数据
- 只能读取转换过程中使用的分页结构的U/S==1的线性地址中的数据
- 只能读取转换过程中使用的分页结构的U/S==1的线性地址中的数据
- 写数据
- 只能向转换过程中使用的分页结构的U/S==1并且R/W==1的线性地址中写数据
- 只能向转换过程中使用的分页结构的U/S==1并且R/W==1的线性地址中写数据
- 执行
- 32-Bit Paging或者IA32_EFER.NXE==0,可以执行地址转换过程中使用的分页结构的U/S==1的线性地址中的指令
- PAE Paging或者IA-32e Paging并且IA32_EFER.NXE==1,可以执行地址转换过程中分页结构的U/S==1并且XD==0的线性地址中的指令
- 读数据
没有地址转换
另一种检查是检查线性地址在现有的分页结构中有没有转换,所谓没有转换就是线性地址在转换过程中使用的分页结构的P==0或者是保留位被设置。
#PF异常
如果对于一个线性地址的转换过程中违反了上述两种检查,那么就会触发#PF异常。下图是#PF的error code,它描述了#PF的类型:
- P:
- 0:异常是由于不存在的页引起的
- 1:异常是由于违反了Page-Level保护引起的
- W/R:
- 0:异常是由于读访问引起的
- 1:异常是由于写访问一起的
- U/S:
- 0:异常是由于supervisor-mode引起的
- 1:异常是由于user-mode引起的
- RSVD:
- 0:异常不是由于保留位被设置引起的
- 1:异常是由于某些分页结构的保留位被设置引起的
- I/D:
- 0:异常不是由于取指引起的
- 1:异常是由于取指引起的
例子
这里的例子主要是模拟由于没有地址转换导致#PF异常,并且在#PF异常处理程序中修改错误的情况。
首先要准备一段可执行的代码,这段代码要拷贝到能够引起#PF异常的线性地址中以便测试使用。
code_start: movl $puts, %ebx movl $dump_pae_page, %edx movl $msg3, %esi call *%ebx movl $println, %eax call *%eax movl $0x400000, %esi call *%edx movl $println, %eax call *%eax jmp .code_end:这段代码也是通过dump_pae_page来打印一个线性地址的转换过程。
接下来要将这段代码拷贝到测试的地址中,我们使用了0x400000地址为测试地址,不过拷贝的过程要在开启分页之前进行,否则拷贝的过程就会导致#PF。
/* * copy code to 0x400000 */ movl $code_start, %esi movl $0x400000, %edi movl $code_end, %ecx subl %esi, %ecx rep movsb测试代码准备好了,调用init_pae32_paging来初始化PAE Paging结构,这个结构和《PAE Paging》中的分页结构相同,不过就是在0x400000地址转换过程中PDE的保留位被设置了,PTE的P标志被清0,这两种情况都会导致#PF。
################################################################ init_pae32_paging:init_pae32_paging: movl $PDPT_BASE, %esi call clear_4k_page movl $0x201000, %esi call clear_4k_page movl $0x202000, %esi call clear_4k_page # PDPTE[0] movl $PDPT_BASE, %esi movl $0x201001, (%esi) movl $0x00, 4(%esi) # PDE[0] 0x00 ~ 0x1fffff (2M) # PDE[1] 0x200000 ~ 0x3fffff (2M) # PDE[2] 0x400000 ~ 0x400fff (4K) movl $0x201000, %esi movl $0x00, %eax movl $0x00000087, (%esi, %eax, 8) movl $0x00, 4(%esi, %eax, 8) inc %eax movl $0x00200087, (%esi, %eax, 8) movl $0x00, 4(%esi, %eax, 8) inc %eax movl $0x00202007, (%esi, %eax, 8) movl $0x70000000, 4(%esi, %eax, 8) # PTE[0] 0x400000 ~ 0x400fff (4K) movl $0x202000, %esi movl $0x00400000, (%esi) /* movl xd_bit, %eax movl %eax, 4(%esi) */ ret然后就是编写#PF处理代码了,这里能够修改线性地址转换过程中由于数据结构中保留位被设置以及P标志为0的异常。
################################################################ PF_handler():PF_handler: jmp do_PF_handlerpf_msg1: .asciz "----> Now, enter #PF handler, occur at: 0x"pf_msg2: .asciz "----> Error Code: 0x"pf_msg3: .asciz "----> fixup <----"do_PF_handler: popl %esi pushl %ecx pushl %edx pushl %ebx movl %esi, %ebx # puts error address movl $pf_msg1, %esi call puts movl %cr2, %ecx movl %ecx, %esi call print_int_value call println # puts error code movl $pf_msg2, %esi call puts movl %ebx, %esi call print_int_value call println call get_maxphyadd pushl %ecx leal -64(%eax), %ecx negl %ecx movl $-1, %edi shll %cl, %edi shrl %cl, %edi popl %ecx# fix errorget_pdpte: movl %ecx, %eax shrl $30, %eax andl $0x03, %eax movl $PDPT_BASE, %ebx # PDPTE pushl %edi movl 4(%ebx, %eax, 8), %edx notl %edi andl %edx, %edi jz get_pdpte_low popl %edi andl %edi, %edx movl %edx, 4(%ebx, %eax, 8) jmp do_PF_handler_doneget_pdpte_low: popl %edi movl (%ebx, %eax, 8), %edx btsl $0, %edx movl %edx, (%ebx, %eax, 8) jnc do_PF_handler_doneget_pde: #PDE movl %edx, %ebx andl $0xfffff000, %ebx movl %ecx, %eax shrl $21, %eax andl $0x01ff, %eax pushl %edi movl 4(%ebx, %eax, 8), %edx notl %edi andl $0x7fffffff, %edi andl %edx, %edi jz get_pde_low popl %edi orl $0x80000000, %edi andl %edi, %edx movl %edx, 4(%ebx, %eax, 8) jmp do_PF_handler_doneget_pde_low: popl %edi movl (%ebx, %eax, 8), %edx btsl $0, %edx movl %edx, (%ebx, %eax, 8) jnc do_PF_handler_done bt $7, %edx movl %edx, (%ebx, %eax, 8) jc do_PF_handler_doneget_pte: #PTE movl %edx, %ebx andl $0xfffff000, %ebx movl %ecx, %eax shrl $12, %eax andl $0x01ff, %eax pushl %edi movl 4(%ebx, %eax, 8), %edx notl %edi andl $0x7fffffff, %edi andl %edx, %edi jz get_pte_low popl %edi orl $0x80000000, %edi andl %edi, %edx movl %edx, 4(%ebx, %eax, 8) jmp do_PF_handler_doneget_pte_low: popl %edi movl (%ebx, %eax, 8), %edx btsl $0, %edx movl %edx, (%ebx, %eax, 8) jc do_PF_handler_donedo_PF_handler_done: movl $pf_msg3, %esi call puts call println call println popl %ebx popl %edx popl %ecx iret
最后在开启分页之后,首先对线性地址0x400000的转换过程进行打印,然后逃转到0x400000地址去执行其中的指令,由于0x400000地址中的指令也是打印对于线性地址0x400000的转换过程,所以执行结构应该看到两次对于0x400000线性地址的转换过程的打印结构。
movl $msg3, %esi call puts call println movl $0x400000, %esi call dump_pae_page call println ljmp $KERNEL_CODE32_SELECTOR, $0x400000
最后的执行结构:
从执行结果可以看出,从第一次打印的结构来看,对线性地址0x400000的转换中使用的PDE的保留位被设置了,PTE的P标志被清0,所以没有对线性地址0x400000的转换。接下来的两次#PF正是由于跳转到0x400000地址去执行指令导致的。
第一次#PF是由PDE的保留位被设置导致的,从错误代码中可以看到,0x19表示P==1,RSVD==1,I/D==1,这说明异常是由于违反了页级别的保护引起的,具体是由于一些分页结构的保留位被设置引起的,同时是在取指令时引起的。接下来#PF处理过程修复了这个错误。
第一次#PF异常处理结束后,会重现执行跳转代码,但是这是线性地址0x400000仍然没有转换,所以导致了第二次#PF异常。
第二次#PF是由PTE的P标记被清0导致的,从错误代码中可以看出,0x10表示P==0,I/D==1,这说明异常是由于页不存在导致的,同时是在取指令时引起的。接下来#PF处理过程也修改了这个错误。
两种错误都被修正之后,代码可以正确的跳转到0x400000地址去执行了,执行的结构就是打印出线性地址0x400000被转换的过程,从结果上看之前的错误都被#PF处理过程修复了。
参考
《Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3 (3A, 3B & 3C): System Programming Guide》
《x86/x64体系探索及编程》
- Protection 6 ---- Page-Level Protection
- oracle dataguard protection level
- SSIS Package Protection Level
- Page protection in Smart Forms
- Protection 4 ---- Priviliege Level Checking 1
- Protection 5 ---- Priviliege Level Checking 2
- protection money
- Java Protection
- Database Protection
- Protection 1
- Clickjacking Protection
- 理解SSIS包保护级别(SSIS Package Protection Level)
- PROTECTiON iD V5.1
- 禁止 Symantec Protection Agent
- Office Software Protection Platform
- System File Protection
- Virtual Machine Protection
- sudo protection bypass exploit
- RSS收藏 设计师必看的苹果设计历代启示录
- UML统一建模语言
- tomcat下多网站、网站下多应用时的配置
- swing中一个Jframe调用另一个Jframe
- public class staticInter
- Protection 6 ---- Page-Level Protection
- (03)开发之游标顾头不顾尾
- 基于opencv人脸检测原理及实现
- 【K-Means】鸢尾花的分类聚类
- 【EasyUse】关于键盘加速键的几点思考
- Android.Manifest.permission权限大全
- Xcode中下载和使用离线文档
- 学习记录
- Mac系统清理