2.常见进程相关编程实例
(1)提升进程权限级别
OpenProcess只能打开普通的进程,而无法打开系统安全进程或服务进程,解决这个问题只是当前进程具有SeDebugPrivilege权限就可以了。如何使当前进程具有这样的权限呢?
在默认情况下,有些进程的访问权限没有被打开,所以首先要做的是打开这个进程的权限。由此有关的API函数有:
OpenProcessToken(),LookupPrivilegeValue(),AdjustTokenPrivileges()。如果要修改进程的访问令牌,首先必须获得进程该进程访问令牌的句柄,这可以通过函数OpenProcessToken(),其原型为:
例子:
void RaisePrivileges()
{
HANDLE hToken ;
TOKEN_PRIVILEGES tkp ;
tkp.PrivilegeCount = 1 ;
tkp.Privileges[0] .Attributes = SE_PRIVILEGE_ENABLE ;
if( OpenProcessToken( GetCurrentProcess() , TOKEN_ALL_ACCESS , &hToken ) )
{
if( LookupPrivilegeValue( NULL , SE_DEBUG_NAME , &tkp.Privilegs[0].Luid ) )
{
AdjustTokenPrivileges( hToken , FALSE , &tkp , 0x10 , (PTOKEN_PRIVILEGES)NULL , 0 ) ;
}
}
if( hToken ) { CloseHandle( hToken ) ; }
}
(2)实现当前进程的枚举
使用系统快照来枚举进程:
使用API CreateToolhelp32Snapshot获得进程链表的句柄
使用Process32First得到进程链表中的第一个进程信息,存储在PROCESSENTRY32结构中。
使用Process32Next得到下一个进程的信息
分别介绍这三个API:
HANDLE WINAPI CreateToolhelp32Snapshot(
__in DWORD dwFlags ,
__in DWORD th32ProcessID
) ;
函数通过获取进程信息为指定的进程、进程使用的堆[HEAP]、模块[MODULE]、线程建立一个快照.
说到底,可以获取系统中正在运行的进程信息,线程信息,等
---------dwFlags用来表示此快照中包含的项目。此处传入TH32CS_SNAPALL,表示此快照包括系统中所有的进程和线程,以及在th32ProcessID中指定的进程的各模块和线程信息。
--------th32ProcessID指定要包括到此快照的进程ID,当传入0时表示当前进程。
函数执行成功返回快照句柄。否则返回INVALID_HANDLE_VALUE。可以调用GetLastError查看更多的错误信息。
BOOL WINAPI Process32First(
__in HANDLE hSnapshot ,
__inout LPPROCESSENTRY32 lppe
) ;
process32First 是一个进程获取函数,当我们利用函数CreateToolhelp32Snapshot()获得当前运行进程的快照后,我们可以利用process32First函数来获得第一个进程的句柄.
BOOL WINAPI Process32Next(
__in HANDLE hSnapshot ,
__inout LPPROCESSENTRY32 lppe
) ;
以上两个函数,运用于在CreateHlpSnapshot中遍历各项。搭配使用,用来枚举当前系统快照相关的所有进程。函数返回值:成功返回true,否则返回false.
其中PROCESSENTRY32结构为:
PROCESSENTRY32 结构如下:
Typedef structtag PROCESSENTRY32 {
DWORD dwSize;// 结构大小;
DWORD cntUsage;// 此进程的引用计数;
DWORD th32ProcessID;// 进程ID;
DWORD th32DefaultHeapID;// 进程默认堆ID;
DWORD th32ModuleID;// 进程模块ID;
DWORD cntThreads;// 此进程开启的线程计数;
DWORD th32ParentProcessID;// 父进程ID;
LONG pcPriClassBase;// 线程优先权;
DWOR DdwFlags;// 保留;
Char szExeFile[MAX_PATH];// 进程全名;
} PROCESSENTRY32;
void SysProcessList()
{
HANDLE hSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS , 0 ) ;
if( INVALID_HANDLE_VALUE == hSnap )
{
GetLastError() ;
return ;
}
HANDLE hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE , 0 ) ;
if( INVALID_HANDLE_VALUE == hModuleSnap )
{
GetLastError() ;
return ;
}
PROCESSENTRY32 ps32 ;
MODULEENTRY32 me32 ;
ps32.dwSize = sizeof( PROCESSENTRY32 ) ;
me32.dwSize = sizeof( MODULEENTRY32 ) ;
bool flag = Process32First( hSnap , &ps32 ) ;
bool bRet = Module32First( hModuleSnap , &me32 ) ;
while( flag )
{
printf("Process ID :%d (%s)\n" , ps32.th32ProcessID , ps32.szExeFile ) ;
flag = Process32Next( hSnap , &ps32 ) ;
}
while( bRet )
{
printf("Module ID:%d Module Name :%s Module Path :%s \n" , me32.th32ModuleID ,
me32.szModule , me32.szExePath ) ;
bRet = Module32Next( hModuleSnap , &me32) ;
}
CloseHandle( hSnap ) ;
CloseHandle( hModuleSnap ) ;
}
也可以通过psapi.dll提供的API来实现进程的枚举
psapi.dll提供了EnumProcess()和EnumProcessModules()来实现。
也可以通过wtsapi32.dll提供的API函数实现进程的枚举:
WTSOpenServerA()和WTSEnumerateProcessA()来实现。
通过ntll.dll提供的API函数实现当前进程的枚举
ntll.dll提供的API函数:ZwQuerySystemInformation()来实现。
关于后面的三种方法,将会在后续的博文中给出相应的代码。