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 + -
显示快捷键?