我们进行Windows安全编程的时候,经常需要检测进程,我们来实践一下枚举进程与进程加载模块。请见代码实现与注释分析。



/* 头文件 */
#include <Windows.h>
#include <Psapi.h>
#include <Tlhelp32.h>
#include <stdio.h>
/* 预处理声明 */
#pragma comment (lib, "psapi.lib")
/* 函数声明 */
VOID WINAPI EnumProcess1();
VOID WINAPI EnumProcess2();
VOID ListProcessModules1( DWORD dwPID );
VOID ListProcessModules2( DWORD dwPID);
VOID PrintMemoryInfo( DWORD dwPID );
VOID ShowProcessMemoryInfo( DWORD dwPID );
VOID ListHeapInfo( DWORD dwPID );
VOID ListProcessThreads( DWORD dwPID );
VOID PrintError( LPTSTR msg );

/*************************************
* VOID WINAPI EnumProcess1()
* 功能 调用EnumProcesses遍历进程,
* 并调用ListProcessModules1函数和
* ListProcessThreads函数列举模块和线程
*
* 无参数,无返回值
**************************************/
VOID WINAPI EnumProcess1()
{
// 假设不超过1024个进程
DWORD aProcesses[1024], cbNeeded, cProcesses;
unsigned int i;
// 调用EnumProcesses
if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )
return;
// 进程数
cProcesses = cbNeeded / sizeof(DWORD);
for ( i = 0; i < cProcesses; i++ )
{
// 显示进程信息
printf( "\n\n**************************************************" );
printf("\nPROCESS : %u\n\n",aProcesses[i]);
printf( "\n****************************************************" );
// 列举模块信息和线程信息
ListProcessModules1( aProcesses[i] );
ListProcessThreads( aProcesses[i] );
}
}
/*************************************
* VOID WINAPI EnumProcess2()
* 功能 调用Process32First和Process32Next遍历进程,
* 并调用ListProcessModules2函数列举模块,
* 调用ShowProcessMemoryInfo函数显示内存使用情况
*
* 无参数,无返回值
**************************************/
VOID WINAPI EnumProcess2()
{
HANDLE hProcessSnap;
HANDLE hProcess;
PROCESSENTRY32 pe32;
DWORD dwPriorityClass;
// Snapshot
hProcessSnap = CreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hProcessSnap == INVALID_HANDLE_VALUE )
{
PrintError( "CreateToolhelp32Snapshot (of processes)" );
return ;
}
// 设置输入参数,结构的大小
pe32.dwSize = sizeof( PROCESSENTRY32 );

// 开始列举进程
if( !Process32First( hProcessSnap, &pe32 ) )
{
PrintError( "Process32First" ); // 出错信息
CloseHandle( hProcessSnap );
return ;
}
do
{
// 打印进程名
printf( "\n\n=====================================================" );
printf( "\nPROCESS NAME: %s", pe32.szExeFile );
printf( "\n-----------------------------------------------------" );

// 获取优先级
dwPriorityClass = 0;
hProcess = OpenProcess( PROCESS_ALL_ACCESS, FALSE, pe32.th32ProcessID );
if( hProcess == NULL )
PrintError( "OpenProcess" );
else
{
dwPriorityClass = GetPriorityClass( hProcess );
if( !dwPriorityClass )
PrintError( "GetPriorityClass" );
CloseHandle( hProcess );
}
// 打印进程相关信息
printf( "\n process ID = 0x%08X", pe32.th32ProcessID );
printf( "\n thread count = %d", pe32.cntThreads );
printf( "\n parent process ID = 0x%08X", pe32.th32ParentProcessID );
printf( "\n Priority Base = %d", pe32.pcPriClassBase );
if( dwPriorityClass )
printf( "\n Priority Class = %d", dwPriorityClass );

// 获取模块信息,显示内存使用情况
ListProcessModules2( pe32.th32ProcessID );
PrintMemoryInfo(pe32.th32ProcessID);
ListHeapInfo(pe32.th32ProcessID);

} while( Process32Next( hProcessSnap, &pe32 ) );

CloseHandle( hProcessSnap ); //关闭句柄
return ;
}

/*************************************
* VOID ListProcessModules1( DWORD dwPID )
* 功能 调用EnumProcessModules函数
* 列举和显示进程加载的模块
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID ListProcessModules1( DWORD dwPID )
{
HMODULE hMods[1024];
HANDLE hProcess;
DWORD cbNeeded;
unsigned int i;

printf( "\nListProcessModules1 Process ID %u\n", dwPID );

// 打开进程,获得句柄
hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, dwPID );
if (NULL == hProcess)
return;
// 调用EnumProcessModules
if( EnumProcessModules(hProcess, hMods, sizeof(hMods), &cbNeeded))
{
for ( i = 0; i < (cbNeeded / sizeof(HMODULE)); i++ )
{
TCHAR szModName[MAX_PATH];
// 获取获取的路径
if ( GetModuleFileNameEx( hProcess, hMods[i], szModName,
sizeof(szModName)/sizeof(TCHAR)))
{
// 打印
printf( TEXT("\t%s (0x%08X)\n"), szModName, hMods[i] );
}
}
}
CloseHandle( hProcess ); // 关闭进程句柄
}

/*************************************
* VOID ListProcessModules2( DWORD dwPID )
* 功能 调用Module32First和Module32Next函数
* 列举和显示进程加载的模块
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID ListProcessModules2( DWORD dwPID)
{
HANDLE hModuleSnap = INVALID_HANDLE_VALUE;
MODULEENTRY32 me32;
printf( "\nListProcessModules2 Process ID %u\n", dwPID );
// Snapshot
hModuleSnap = CreateToolhelp32Snapshot( TH32CS_SNAPMODULE, dwPID );
if( hModuleSnap == INVALID_HANDLE_VALUE )
{
PrintError( "CreateToolhelp32Snapshot (of modules)" );
return ;
}
// 设置输入参数,结构的大小
me32.dwSize = sizeof( MODULEENTRY32 );
// 开始获取模块信息
if( !Module32First( hModuleSnap, &me32 ) )
{
PrintError( "Module32First" ); // Show cause of failure
CloseHandle( hModuleSnap ); // Must clean up the snapshot object!
return ;
}
do
{
printf( "\n\n MODULE NAME: %s", me32.szModule );
printf( "\n executable = %s", me32.szExePath );
printf( "\n process ID = 0x%08X", me32.th32ProcessID );
printf( "\n ref count (g) = 0x%04X", me32.GlblcntUsage );
printf( "\n ref count (p) = 0x%04X", me32.ProccntUsage );
printf( "\n base address = 0x%08X", (DWORD) me32.modBaseAddr );
printf( "\n base size = %d", me32.modBaseSize );

} while( Module32Next( hModuleSnap, &me32 ) );
CloseHandle( hModuleSnap ); // 关闭句柄
return ;
}

/*************************************
* VOID PrintMemoryInfo( DWORD dwPID )
* 功能 显示进程的内存使用情况
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID PrintMemoryInfo( DWORD dwPID )
{
HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc;

printf( "\nProcess ID: %u\n", dwPID );

hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |
PROCESS_VM_READ,
FALSE, dwPID );
if (NULL == hProcess)
return;

if ( GetProcessMemoryInfo( hProcess, &pmc, sizeof(pmc)) )
{
printf( "\tPageFaultCount: 0x%08X\n", pmc.PageFaultCount );
printf( "\tPeakWorkingSetSize: 0x%08X\n",
pmc.PeakWorkingSetSize );
printf( "\tWorkingSetSize: 0x%08X\n", pmc.WorkingSetSize );
printf( "\tQuotaPeakPagedPoolUsage: 0x%08X\n",
pmc.QuotaPeakPagedPoolUsage );
printf( "\tQuotaPagedPoolUsage: 0x%08X\n",
pmc.QuotaPagedPoolUsage );
printf( "\tQuotaPeakNonPagedPoolUsage: 0x%08X\n",
pmc.QuotaPeakNonPagedPoolUsage );
printf( "\tQuotaNonPagedPoolUsage: 0x%08X\n",
pmc.QuotaNonPagedPoolUsage );
printf( "\tPagefileUsage: 0x%08X\n", pmc.PagefileUsage );
printf( "\tPeakPagefileUsage: 0x%08X\n",
pmc.PeakPagefileUsage );
}
CloseHandle( hProcess );
}

/*************************************
* VOID ListHeapInfo( DWORD dwPID )
* 功能 显示进程的堆分配情况
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID ListHeapInfo( DWORD dwPID )
{
HEAPLIST32 hl;
HEAPENTRY32 he;
HANDLE hSnapshot = INVALID_HANDLE_VALUE;

printf( "\\ListHeapInfo Process ID %u\n", dwPID );

// Snapshot
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPHEAPLIST , dwPID );
if( hSnapshot == INVALID_HANDLE_VALUE )
{
PrintError( "CreateToolhelp32Snapshot (of heaplist)" );
return ;
}
// 设置输入参数,结构的大小
hl.dwSize = sizeof( HEAPLIST32 );

// 开始获取信息
if( !Heap32ListFirst( hSnapshot, &hl ) )
{
PrintError( "Heap32ListFirst" );
CloseHandle( hSnapshot );
return ;
}
do
{
printf( "\n\tHeap ID =%u", hl.th32HeapID );
printf( "\tHeap Flags = %u", hl.dwFlags );
he.dwSize = sizeof(HEAPENTRY32);
if( !Heap32First(&he,dwPID,hl.th32HeapID) )
{
PrintError( "Heap32First" ); // 出错
CloseHandle( hSnapshot );
return ;
}
do
{
// 显示信息
printf( "\n\t\t Heap Address\t= %u",he.dwAddress );
printf( "\t Heap Size\t= %u",he.dwBlockSize);
printf( "\t Heap Flags\t= %u",he.dwFlags);
printf( "\t Heap Handle\t= %u",he.hHandle);
} while( Heap32Next(&he ));

} while( Heap32ListNext( hSnapshot, &hl ) );
CloseHandle( hSnapshot ); // 关闭句柄
return ;
}

/*************************************
* VOID ListProcessThreads( DWORD dwPID )
* 功能 调用Thread32First和Thread32Next
* 显示一个进程的线程
*
* 参数 DWORD dwPID 进程PID
**************************************/
VOID ListProcessThreads( DWORD dwPID )
{
HANDLE hThreadSnap = INVALID_HANDLE_VALUE;
THREADENTRY32 te32;

printf( "\\ListProcessThreads Process ID %u\n", dwPID );

// Snapshot
hThreadSnap = CreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hThreadSnap == INVALID_HANDLE_VALUE )
return ;

// 设置输入参数,结构的大小
te32.dwSize = sizeof(THREADENTRY32 );

// 开始获取信息
if( !Thread32First( hThreadSnap, &te32 ) )
{
PrintError( "Thread32First" ); // Show cause of failure
CloseHandle( hThreadSnap ); // Must clean up the snapshot object!
return ;
}
do
{
if( te32.th32OwnerProcessID == dwPID )
{
// 显示相关信息
printf( "\n THREAD ID = 0x%08X", te32.th32ThreadID );
printf( "\t base priority = %d", te32.tpBasePri );
printf( "\t delta priority = %d", te32.tpDeltaPri );
}
} while( Thread32Next(hThreadSnap, &te32 ) );

CloseHandle( hThreadSnap );
return ;

}

// 打印出错信息
VOID PrintError( LPTSTR msg )
{
DWORD eNum;
TCHAR sysMsg[256];
TCHAR* p;

eNum = GetLastError( );
FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, eNum,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
sysMsg, 256, NULL );
p = sysMsg;
while( ( *p > 31 ) || ( *p == 9 ) )
++p;
do { *p-- = 0; } while( ( p >= sysMsg ) &&
( ( *p == '.' ) || ( *p < 33 ) ) );
printf( "\n WARNING: %s failed with error %d (%s)", msg, eNum, sysMsg );
}

void main()
{
printf("EnumProcess1 \n");
EnumProcess1();
printf("\n\n\nEnumProcess2 \n");
EnumProcess2();
}