cow95.asm
来自「windows下汇编语言 学习汇编语言好助手」· 汇编 代码 · 共 153 行
ASM
153 行
;***************************************************
;文件:COW95.asm *
;功能:演示WIN 95/98的写时拷贝(Copy On Write)功能 *
;***************************************************
.386p
.model flat,stdcall
include win32.inc
extrn ExitProcess:PROC
extrn MessageBoxA:PROC
extrn _wsprintfA:PROC
extrn GetCurrentProcess:PROC
extrn WriteProcessMemory:PROC
CALL32 MACRO selector ,offsetv
DB 09AH
DD offsetv
DW selector
ENDM
.data
LinearAddr dd offset Start
PhysAddr dd ?
User db 'User',0
System db 'System',0
Read db 'Read',0
Write db 'Write',0
CaptionBefore db '写时拷贝——写之前',0
CaptionAfter db '写时拷贝——写之后',0
Text db 150 dup (0)
ErrParam db '线性地址 %8XH 未映射入进程!',0
SucParam db '线性地址:%8XH',0dh,0ah
db '物理地址:%8XH',0Dh,0Ah
db '页属性:%s/%s',0
Written db ?
.code
Start:
push offset L2P
call ToRing0Code
push offset CaptionBefore
call Show
Call GetCurrentProcess
call WriteProcessMemory,eax,offset Modify,offset src,1,offset Written
push offset L2P
call ToRing0Code
push offset CaptionAfter
call Show
call ExitProcess,0
Show proc Caption:DWORD ;显示结果
test eax,1
jnz Present
call _wsprintfA,offset Text,offset ErrParam,LinearAddr
add esp,4*3
call MessageBoxA,0,offset Text,[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 R
mov edi,offset Write
R: call _wsprintfA,offset Text,offset SucParam,LinearAddr,[PhysAddr],esi,edi
add esp,4*6
call MessageBoxA,0,offset Text,[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
Modify dd ?
src dd 'AAAA'
End Start
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?