Windows2000下用户模式的内存扫描

简述:
本文简要介绍了在Windows2000下实现内存扫描的基本理论和实现的办
法 。内存扫描是一项重要的技术,有相当广泛的应用范围:如病毒扫描、
游戏修改等 。Windows2000是一个完全保护的系统,且具有两种工作模式,
即用户态和核心态(User Model and Kernel Model) 。内存扫描也可分为
用户态的内存扫描与核心态的内存扫描 。本文主要讲述的是工作于用户态
的内存扫描 。
一.相关理论
早期在Dos坏境下进行内存扫描是一件相对简单的事情 。因为DOS工作在
CPU的实模式下,没有采用虚存技术也没有提供内存的保护机制,只要实实
在在的扫描完所有的物理内存,一切工作也就完成了,早期有一些防毒软
件就是用了这样的办法 。当然为了提高效率,我们并不用扫描所有的内存
区域,因为有些空间是没有被用到的,扫描这些地方也是只浪费时间 。这
可以通过遍历DOS系统的MCB(Memory Control Block)链,来得到实际内
存的使用区域,从而使扫描的效率大大提高 。相似的思路在Windows2000下
的内存扫描也是适用的 。
Windows2000则是一个完全保护的系统,工作于CPU的保护模式下,引入
了虚存技术 。每个进程拥有独立的4GB的地址空间,其中低的2GB为进程的私有空间,高的2GB为系统空间的映射(如果在Boot.ini文件中使用
“/3GB”的开关可以使进程的私有空间增大到3GB,系统空间1GB) 。对于
每个进程来讲其虚拟的地址空间是连续的,实际上它们是以页面为单位
离 散的存在于物理内存中,一些可能被交换到硬盘上的页面文件中,而
且还有大部分的空间是未提交(Uncommitted)的 。因此在Windows2000
中对进程的用户空间进行扫描必须依次对每个进程的空间进行扫描 。一
个进程的低2GB有空间的分布如下表:
范围
大小
作用
0x0~~ 0xFFFF
64 KB
不可访问区域,只是用来防止非法的指针访问,访问该范围的地址会导致访问违例 。
0x10000~~
0x7FFEFFFF
2 GB 减去至少 192 KB
进程的私有地址空间
0x7FFDE000~~
0x7FFDEFFF
4 KB
【Windows2000下用户模式的内存扫描】进程中第一个线程的线程环境块,即 TEB ( Thread environment block )
0x7FFDF000~~ 0x7FFDFFFF
4 KB
进程的进程环境块,即 PEB ( Process environment block )
0x7FFE0000~~
0x7FFE0FFF
4 KB
一个共享的只读用户数据块,该块映射到到系
统空间的一个数据块,其中存放的是一些系统
信息如系统时间、时钟的滴答数、系统版本号
等 。这样访问这些信息的时候系统就不用切换
到核心模式 。
0x7FFE1000~~
0x7FFEFFFF
60 KB
不可访问
0x7FFF0000~~ 0x7FFFFFFF
64 KB
不可访问,用于防止线程的缓冲跨越两种模式
空间的边界
表 1
二.实现 从上表可以看出,我们要扫描范围的起点和终点不是从 0~~2GB,而只是其中的一 部分 。要得到这个起点和终点可以使用API函数GetSystemInfo,函数的原型如下: VOID GetSystemInfo( LPSYSTEM_INFO lpSystemInfo // system information ); 而在结构SYSTEM_INFO中有两个域: lpMinimumApplicationAddress 和 lpMaximumApplicationAddress (类型都是 LPVOID) 中 ,我们就可以得到一个应用程序可用的最小和最大的地址空间 。这样我们就得到了要扫描的地址的起点和终点 。那么是不是这起点和终点间所有的地址都要扫描呢?并不是这样的,因为一般情况下一个进程是用不着这么大(接近2GB)的地址空间的 。因此一个进程的大部分地址空间都是未用(Free)或是保留(Reserved)的,真正用到的只是那些已提交(Committed)的内存而已 。内存页面可以有三种状态: 未用( Free)、保留(Reserved)和提交

推荐阅读