以下代码均已Delphi描述...至于为什么...
首先我是一个Delphi Coder...虽然我大部分时间使用的是ASM编译器和C编译器
但是我喜欢Delphi...好了不废话了...
已知的三种方法:如果各位有更好的意见欢迎大家提出
[1]使内存可读写
1.stl+cr0:
这个方法大家想必经常使用...
(参考I-32.3A文档)
由于cr0是一个32位寄存器...假设大家的CPU是32位的.没有64位测试环境
按照图这个结构我们可以了解到的信息
第16位:WP——Write Protect,当设置为1时只提供读页权限
第0位:PE——Paging,当设置为1时提供分页
第1位:MP——Protection Enable,当设置为1时进入保护模式
按照这个说明写出代码:
//1 关闭写保护
asm
push eax
mov eax, CR0
and eax, 0FFFEFFFFh
mov CR0, eax
pop eax
end;
//2 打开写保护
asm
push eax
mov eax, CR0
or eax, NOT 0FFFEFFFFh
mov CR0, eax
pop eax
end;
也许大家看得有点模糊.其实这个代码就是修改第16位
NOT 0FFFEFFFFh = 00010000h
因为要设置第16位为1...所以结果也就是代码那种效果...
鄂~我也不知道说什么了.也就是位操作你也可以直接使用
//1 关闭写保护
asm
push eax
mov eax, cr0
and eax, not 000010000h
mov cr0, eax
pop eax
end;
//2 打开写保护
asm
push eax
mov eax, cr0
or eax, 000010000h
mov cr0, eax
pop eax
end;
一般使用的时候我们都会加上cli和sti,由于这两个指令只能控制当前CPU对于
多核系统是无法起到有效的互斥的...所以一般都是配合"自转锁"使用
关于自转锁的话题我们下面会详细的说的
2.通过内存描述表(MDL)中描述一块内存区域,MDL包含此内存区域的起始地址,
拥有者进程,字节数量以及标志.(据说是Bill提供的方法.难道和VirtualProtect一样?)
type
PMDL = ^_MDL;
_MDL = packed record
Next: PMDL;
Size: USHORT;
MdlFlags: USHORT;
Process: Pointer;
MappedSystemVa: PVOID;
StartVa: PVOID;
ByteCount: ULONG;
ByteOffset: ULONG;
end;
MDL = _MDL;
const
MDL_MAPPED_TO_SYSTEM_VA = $0001;
MDL_PAGES_LOCKED = $0002;
MDL_SOURCE_IS_NONPAGED_POOL = $0004;
MDL_ALLOCATED_FIXED_SIZE = $0008;
MDL_PARTIAL = $0010;
MDL_PARTIAL_HAS_BEEN_MAPPED = $0020;
MDL_IO_PAGE_READ = $0040;
MDL_WRITE_OPERATION = $0080;
MDL_PARENT_MAPPED_SYSTEM_VA = $0100;
MDL_LOCK_HELD = $0200;
MDL_PHYSICAL_VIEW = $0400;
MDL_IO_SPACE = $0800;
MDL_NETWORK_HEADER = $1000;
MDL_MAPPING_CAN_FAIL = $2000;
MDL_ALLOCATED_MUST_SUCCEED = $4000;
// 读写只读内存(源于Gates大叔)
function WriteReadOnlyMemoryGates(lpDest, lpSource: Pointer; Length: Integer):
NTSTATUS;
var
tempSpinLock: KSPIN_LOCK;
oldirql: KIRQL;
mdl: PMDL;
writableAddress: Pointer;
begin
Result := STATUS_UNSUCCESSFUL;
mdl := MmCreateMdl(nil, lpDest, Length);
if (mdl <> nil) then
begin
MmBuildMdlForNonPagedPool(mdl);
mdl^.MdlFlags := mdl^.MdlFlags or MDL_MAPPED_TO_SYSTEM_VA;
writableAddress := MmMapLockedPages(mdl, KernelMode);
if (writableAddress <> nil) then
begin
oldirql := 0;
KeInitializeSpinLock(@tempSpinLock);
fast_KfAcquireSpinLock(@tempSpinLock);
memcpy(writableAddress, lpSource, Length);
fast_KfReleaseSpinLock(@tempSpinLock, oldirql);
MmUnmapLockedPages(writableAddress, mdl);
Result := STATUS_SUCCESS;
end;
MmUnlockPages(mdl);
IoFreeMdl(mdl);
end;
end;
// 写只读内存(源于Mark代码)
function WriteReadOnlyMemoryMark(lpDest, lpSource: Pointer; Length: Integer):
NTSTATUS;
var
tempSpinLock: KSPIN_LOCK;
oldirql: KIRQL;
mdl: PMDL;
writableAddress: Pointer;
begin
Result := STATUS_UNSUCCESSFUL;
mdl := IoAllocateMdl(lpDest, Length, False, False, nil);
if (mdl <> nil) then
begin
MmBuildMdlForNonPagedPool(mdl);
MmProbeAndLockPages(mdl, KernelMode, IoWriteAccess);
writableAddress := MmMapLockedPages(mdl, KernelMode);
if (writableAddress <> nil) then
begin
oldirql := 0;
KeInitializeSpinLock(@tempSpinLock);
fast_KfAcquireSpinLock(@tempSpinLock);
memcpy(writableAddress, lpSource, Length);
fast_KfReleaseSpinLock(@tempSpinLock, oldirql);
MmUnmapLockedPages(writableAddress, mdl);
Result := STATUS_SUCCESS;
end;
MmUnlockPages(mdl);
IoFreeMdl(mdl);
end;
end;
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!