阅读:1235回复:7
怎样读出页表?
我现在有CR3的值,我想读出页表,是否需要先构造一个段描述符,另外需要将PG位置0吗,当我读出来后再将PG位还原,要是系统在PG位是0,还没有被还原时将我的程序切换掉,就会重启,要如何才能防止切换?
|
|
沙发#
发布于:2004-11-23 12:13
我现在有CR3的值,我想读出页表,是否需要先构造一个段描述符,另外需要将PG位置0吗,当我读出来后再将PG位还原,要是系统在PG位是0,还没有被还原时将我的程序切换掉,就会重启,要如何才能防止切换? 一般NT/XP下页表存储于虚拟地址0xC0000000处,既然你有CR3的值,你可以把虚拟地址转换为物理地址,然后用\DEVICE\PhysicalMemory把相应内容映射到你的进程空间中. 你是怎样读到CR3值的?我一直想知道怎么做 |
|
板凳#
发布于:2004-11-23 12:30
我用的98,读CR3很容易
|
|
地板#
发布于:2004-11-23 12:31
NT我还不熟,另外我想到了,切换PG位是不行的,后面的代码就会错位了,不知道会执行到什么地方,似乎如果系统不把分页表映射到一个固定的地方,我们就没有办法读出分页表
[编辑 - 11/23/04 by nhchmg] |
|
地下室#
发布于:2004-11-23 15:53
;******************************************************
;文件:l2p.asm * ;功能:由线性地址得到相应的物理地址,并显示其页属性 * ;****************************************************** .386p .model flat,stdcall include win32.inc extrn ExitProcess:PROC extrn MessageBoxA:PROC extrn _wsprintfA:PROC CALL32 MACRO selector ,offsetv DB 09AH DD offsetv DW selector ENDM LinearAddr equ offset Start ;要查看的线性地址 .data PhysAddr dd ? ;存放得到的物理地址 User db 'User',0 System db 'System',0 Read db 'Read',0 Write db 'Write',0 Caption db '线性地址到物理地址的转换',0 Text db 150 dup (0) ErrParam db '线性地址 %8XH 不在内存中!',0 SucParam db '线性地址:%8XH',0dh,0ah db '物理地址:%8XH',0Dh,0Ah db '页属性:%s/%s',0 .code Start: call ToRing0Code,offset L2P ;取物理地址及页信息 call Show ;显示物理地址及页信息 call ExitProcess,0 ;退出进程 Show Proc test eax,1 ;存在否? jnz Present call _wsprintfA,offset Text,offset ErrParam,LinearAddr add esp,4*3 call MessageBoxA,0,offset Text,offset Caption,MB_OK call ExitProcess,1 Present: mov esi,offset User mov edi,offset Read test eax,100B ;用户页还是系统页? jnz Usr mov esi,offset System Usr:test eax,10B ;只读还是可写? jz RD mov edi,offset Write RD: call _wsprintfA,offset Text,offset SucParam,LinearAddr,[PhysAddr],esi,edi add esp,4*6 call MessageBoxA,0,offset Text,offset Caption,MB_OK ret Show endp ToRing0Code proc Ring0Proc:DWORD ;生成调用门并调用Ring0子程序Ring0Proc LOCAL Temp,Temp1 call GetLdtAddress ;取出LDT的地址,返回结果在eax中 mov ecx,[eax] ;保存LDT第一个描述符 mov [Temp],ecx ; mov ecx,[eax+4] ; mov [Temp1],ecx ; mov edx,Ring0Proc ;把调用门的内容写入LDT mov [eax],dx ;偏移量的低16位 mov word ptr [eax+2],28h ;段选择子 mov word ptr [eax+4],0ec00h ;属性 shr edx,16 ;偏移量的高16位 mov [eax+6],dx ; push eax CALL32 7,0 ;调用 Ring0 子程序 pop ebx mov edx,[Temp] ;恢复LDT第一个描述符 mov [ebx],edx ; mov edx,[Temp1] ; mov [ebx+4],edx ; ret ToRing0Code endp GetLdtAddress proc ;取LDT的地址 push ebx ;先要取GDT的地址 sgdt [esp-2] ; pop ebx ; sldt ax ;取LDT内容 and eax,0fff8H ;屏蔽掉低3位、eax的高16位清0 add ebx,eax ;算出LDT描述符的位置 mov eax,[ebx+2] ;从描述符中取出LDT的地址 mov dl,[ebx+7] ; shl edx,24 ; and eax,0ffffffh ; or eax,edx ; ret GetLdtAddress endp L2P proc far ;Ring0程序,由线性地址取得物理地址及其页属性 mov eax,cr3 ;CR3是页表目录寄存器 push eax ;取页表目录的线性地址 call P2L ; mov edx,LinearAddr ;取出线性地址 shr edx,22 ;取高10位 shl edx,2 ;乘4(每项4字节) mov eax,[eax+edx] ;取对应页表的(物理)地址 test eax,1 ;存在否? jz Quit and eax,0fffff000H ;清除属性位 push eax ;取对应页表的线性地址 call P2L ; mov edx,LinearAddr ;取线性地址第12-21位 shl edx,10 ; shr edx,22 ; shl edx,2 ;乘4 mov eax,[eax+edx] ;取出物理页地址 test eax,1 ;存在否? jz Quit push eax ;保存eax,用作返回值 and eax,0fffff000H ;填入页内偏移 mov edx,LinearAddr ; and edx,00000FFFH ; or eax,edx ; mov [PhysAddr],eax ;保存好物理地址 pop eax ;返回对应的物理页和属性 Quit: ret L2P endp P2L proc ,Physcial ;由物理地址得到线性地址 push Physcial int 20H ;VxDCall _MapPhysToLinear dd 0001006cH add esp,4 ;调整堆栈 ret P2L endp END Start |
|
|
5楼#
发布于:2004-11-23 20:31
谢谢上面的回复
P2L proc ,Physcial ;由物理地址得到线性地址 push Physcial int 20H ;VxDCall _MapPhysToLinear dd 0001006cH add esp,4 ;调整堆栈 ret P2L endp 这个int 20H 内部是不是也要访问页表?我的意思是从理论上,如果页表并不映射到一个固定的地址,我们是不是不可能访问到页表? |
|
6楼#
发布于:2004-11-26 04:57
也是可以的啊...不然os怎么去修改page table呢..
内存的访问总是以线性地址为方式的啊... os也是通过线性地址访问page table的... 而且如果page table不映射到固定的地址.. 那么这个地址保存到哪里呢?某个变量里面? 那这个变量的地址又是什么呢?固定还是不固定? 如果不固定的话?又怎么去获取呢?难道又用一个变量保存? 那就无穷尽了.... 所以os总是把page table映射到一个固定的地址 |
|
7楼#
发布于:2004-11-26 12:59
嗯
[编辑 - 11/26/04 by nhchmg] |
|