标题让我想起win驱动中修改只读页的内容:新申请一个PTE指向该页,PTE中的权限改为读写,就能修改页面内容啦。
现在阶段我的bootloader还没有建立起分页机制,仅仅开启分段,因此,通过修改PTE啥的肯定不奏效,能做的只有修改段描述符了。
先看下我代码中的段描述表:
mov dword [bx],0x00000000 mov dword [bx+4],0x00000000 ;代码段 0x7c00 权限 读执行 add bx,0x08 mov dword [bx],0x7c0001ff mov dword [bx+4],0x00409A00 ;数据段 0x7c00 权限 读写 add bx,0x08 mov dword [bx],0x7c0001ff mov dword [bx+4],0x00409200 mov word [cs:gdtSize+0x7c00],0x08*3-1 lgdt [cs:0x7c00+gdtSize]读写代码段内存的代码:
Code: ;1)直接读取代码段 lea edx,[cs:Code] mov eax,[cs:edx] ;2)直接修改代码段 xor eax,eax lea edx,[cs:Code] mov [cs:edx],eax ;3)段选择子指向代码段,但是把权限改为数据段 xor eax,eax mov ax,0x10 mov ds,ax lea edx,[cs:Code] mov word [edx],0x9090 jmp Code运行bochs,执行到1)处时:
【黄色高亮处】反汇编内存0x7c76,数值为2e8d1576,执行完mov eax,[cs:edx]后 eax的内容为0x76158d2e (注意是小端机)。可知,代码成功读取了0x7c76处的内容
再往下执行到2)处:出错了,bochs也提示 no write access to seg。
其实,也不算出错,只是一个页面异常,没被捕获处理。怪我了,还是个简单的bootloader。
回过头看下,进入保护模式时,这个代码段的权限:
bochs说的很清楚了,代码段,起始于0x7c00权限是读执行。当然,如果段描述符的TYPE字段改为0x4096即只执行,那运行到第一步时也会出现异常。
好吧,到这有个问题:难道在未开启页机制前,代码段不能写了?再进一步,没法往代码段设置int 0x3断点了(不能实时调试)?
这倒也不是,只要为该段安装一个新的描述符,并把其可读写的数据段,最后加载该描述符,这样就可以修改代码段内的数据了。现在来看下修改后的代码:
flush: Code: ;段选择子指向代码段,但是把权限改为数据段 xor eax,eax mov ax,0x10 mov ds,ax lea edx,[cs:Code] mov word [edx],0x9090 jmp Codebochs运行起来:
ds加载0x10后(第3个段描述符),然后mov ds:[edx],0x90909090,其实就是修改0x7c76处的内存。修改结束后反汇编结果
0x7c76 0x7c77 为nop,修改成功,yes!