Windows2000下用户模式的内存扫描( 三 )


三 相关的问题:
在实际操作中会遇到一些问题 。如果我们指定了写相关的访问权(如
PROCESS_VM_WRITE 、 PROCESS_SET_INFORMATION 、 PROCESS_ALL_ACCESS 等 ),用
OpenProcess打开一些普通进程是没什么问题,但要是打开的是系统安全进程
(如Sy stem、Winlogon、smss、csRSS、services、lsass等)或是一些注册为
服务的进程时,就会遇到“访问拒绝”的错误,这是为了系统的安全而采取的保
护手段 。说明了当前的进程没有足够的权限来进行此操作 。在进程控制结构中
有一个“访问令牌”(Access tokens),里面包含有本进程的权限信息 。一些常
用的权限如表1所示(摘自Inside Windows2000,Third Edition) 。
权限名
权限含义
SeBackup
在备份的时候绕过安全检查
SeDebug
可对一个进程进行调试
SeShutdown
可关闭本地系统
SeTakeOwnerShip
在没有得到自由访问权的情况下得到一个对象的所有权
表 2
要对一个任意进程(包括系统安全进程和服务进程)进行 指定了写相 关的访问权的 OpenProcess操作,只要当前进程具有SeDeDebug权限就 可 以了 。要是一个用户是Administrator或是被给予了相应的权限,就可以具 有该权限 。可是,就算我们用Administrator帐号对一个系统安全进程执行 OpenProcess(PROCESS_ALL_ACCESS,FALSE, dwProcessID)还是会遇到 “访 问拒绝”的错误 。什么原因呢?原来在默认的情况下进程的一些访问权限 是没有被使能( Enabled)的,所以我们要做的首先是使能这些权限 。与此 相关的一些API函数有OpenProcessToken、 LookupPrivilegeValue 、 AdjustTokenPrivileges。我们要修改一个进程的访问令牌,首先要获得进 程访问令牌的句柄,这可以通过 OpenProcessToken得到,函数的原型如:
BOOL OpenProcessToken( HANDLE ProcessHandle , DWORD DesiredAccess , PHANDLE TokenHandle ); 第一参数是要修改访问权限的进程句柄;第三个参数就是返回的访问令牌指针;第二个参数指定你要进行的操作类型,如要修改令牌我们要指定第二个参数为 TOKEN_ADJUST_PRIVILEGES( 其它一些参数可参考 Platform SDK ) 。通过这个函数我们就可以得到当前进程的访问令牌的句柄(指定函数的第一个参数为 GetCurrentProcess()就可以了) 。接着我们可以调用AdjustTokenPrivileges对这个访问令牌进行修改 。AdjustTokenPrivileges的原型如下: BOOL AdjustTokenPrivileges( HANDLE TokenHandle , // handle to token BOOL DisableAllPrivileges , // disabling option PTOKEN_PRIVILEGES NewState , // privilege information DWORD BufferLength , // size of buffer PTOKEN_PRIVILEGES PreviousState , // original state buffer PDWORD ReturnLength // required buffer size ); 第一个参数是访问令牌的句柄;第二个参数决定是进行权限修改还是除能( Disable)所有权限;第三个参数指明要修改的权限,是一个指向 TOKEN_PRIVILEGES 结构的指针,该结构包含一个数组,数据组的每个项指明了权限的类型和要进行的操作 ; 第四个参数是结构 PreviousState 的长度,如果 PreviousState 为空,该参数应为 NULL ;第五个参数也是一个 指向 TOKEN_PRIVILEGES 结构的指针,存放修改前的访问权限的信息,可空;最后一个参数为实际 PreviousState 结构返回的大小 。在使用这个函数前再看一下 TOKEN_PRIVILEGES 这个结构,其声明如下:
typedef struct _TOKEN_PRIVILEGES { DWORD PrivilegeCount ; LUID_AND_ATTRIBUTES Privileges []; } TOKEN_PRIVILEGES, *PTOKEN_PRIVILEGES;PrivilegeCount 指的数组原素的个数,接着是一个 LUID_AND_ATTRIBUTES 类型的数组,再来看一下 LUID_AND_ATTRIBUTES 这个结构的内容,声明如下:
typedef struct _LUID_AND_ATTRIBUTES { LUID Luid ; DWORD Attributes ;} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES

推荐阅读