Windowsプログラミング
そこそこ役に立つサンプル集



プロセスの列挙とプロセスの中身を見る方法

現在起動中のプロセスの一覧を取得する方法と、そのプロセスの中身を見る方法をまとめます。

プロセスの列挙はよく知られていて、CreateToolhelp32Snapshot関数、Process32First関数、Process32Next関数
を使います。

プロセスの中身を見る方法は、ReadProcessMemory関数を使います。
ReadProcessMemoryで取得したデータの中身を解析するために、PEB構造体、PROCESS_PARAMETERS構造体、UNICODE_STRING構造体を使います。

ReadProcessMemory関数はMSのサイトにも載っているのですが、PEB構造体、PROCESS_PARAMETERS構造体、UNICODE_STRING構造体は、なぜかMSのサイトに載っていません。


以下のサイトの情報を参考にしました。
  • プロセス ID またはプロセス ハンドルを使用してジョブ オブジェクトを取得する方法(http://www.microsoft.com/japan/msdn/columns/askgui/askgui09162003.aspx)
  • 他プロセスのカレントディレクトリを取得する (http://d.hatena.ne.jp/topiyama/searchdiary?word=*%5Bsrc%5D)
  • PEB、PROCESS_PARAMETERS構造体 (http://www.vckbase.com/bbs/prime/viewprime.asp?id=345)
  • UNICODE_STRING構造体 (http://www.osronline.com/DDKx/kmarch/k112_401e.htm)


以下がサンプルコードです。リストボックスに、●でプロセスのモジュール名。■でプロセスのモジュール名+コマンドライン引数、★でプロセスのカレントディレクトリを表示します。

(.h)
        CListBox m_list;


(.cpp)
#include "Psapi.h."
#pragma comment(lib, "Psapi.lib")

        ...

const DWORD MAX_MODULES = 4096;   // モジュールのハンドルを格納する HMODULE配列のサイズ
const DWORD MAX_MODULES_USED = 100;       // 表示するモジュール数を制限

typedef struct _PROCESS_BASIC_INFORMATION { 
    PVOID Reserved1; 
    BYTE *PebBaseAddress; 
    PVOID Reserved2[2]; 
    ULONG_PTR UniqueProcessId; 
    PVOID Reserved3; 
} PROCESS_BASIC_INFORMATION; 


typedef enum _PROCESSINFOCLASS { 
    ProcessBasicInformation = 0, 
    ProcessWow64Information = 26 
} PROCESSINFOCLASS; 


typedef LONG WINAPI 
NtQueryInformationProcess ( 
    IN HANDLE ProcessHandle, 
    IN PROCESSINFOCLASS ProcessInformationClass, 
    OUT PVOID ProcessInformation, 
    IN ULONG ProcessInformationLength, 
    OUT PULONG ReturnLength OPTIONAL 
    ); 

typedef struct _UNICODE_STRING {
  USHORT  Length;
  USHORT  MaximumLength;
  PWSTR  Buffer;
} UNICODE_STRING;

typedef struct
{
        ULONG                    AllocationSize;
        ULONG                    ActualSize;
        ULONG                    Flags;
        ULONG                    Unknown1;
        UNICODE_STRING          Unknown2;
        HANDLE                   InputHandle;
        HANDLE                   OutputHandle;
        HANDLE                   ErrorHandle;
        UNICODE_STRING          CurrentDirectory;
        HANDLE                   CurrentDirectoryHandle;
        UNICODE_STRING          SearchPaths;
        UNICODE_STRING          ApplicationName;
        UNICODE_STRING          CommandLine;
        PVOID                     EnvironmentBlock;
        ULONG                    Unknown[9];
        UNICODE_STRING          Unknown3;
        UNICODE_STRING          Unknown4;
        UNICODE_STRING          Unknown5;
        UNICODE_STRING          Unknown6;
} PROCESS_PARAMETERS, *PPROCESS_PARAMETERS; 

typedef struct
{
        ULONG                                     AllocationSize;
        ULONG                                     Unknown1;
        HINSTANCE                                 ProcessHinstance;
        PVOID                                      ListDlls;
        PPROCESS_PARAMETERS                    ProcessParameters;
        ULONG                                     Unknown2;
        HANDLE                                    Heap;
} PEB; 

BYTE *GetPEB(HANDLE hProcess) 
{ 
        NtQueryInformationProcess* NtQip = (NtQueryInformationProcess*) 
	GetProcAddress(GetModuleHandle(_T("ntdll.dll")), "NtQueryInformationProcess"); 
        PROCESS_BASIC_INFORMATION info; 
        NtQip(hProcess, ProcessBasicInformation, &info, sizeof(info), NULL); 
        return info.PebBaseAddress; 
}

        ...

        CString strMsg;
        CString strBuf;
    HANDLE     hProcessSnap = NULL;
    PROCESSENTRY32   pe32;
    BOOL    bRet = FALSE;
    ZeroMemory ( &pe32, sizeof (pe32) );

    hProcessSnap = CreateToolhelp32Snapshot ( TH32CS_SNAPPROCESS, 0);
    if ( INVALID_HANDLE_VALUE == hProcessSnap ) {
                TRACE(_T("CreateToolhelp32Snapshot failed with %u.\n"), GetLastError() );
        return ;
    }

    strMsg += _T("PID  Name             Number of threads\n");
    pe32.dwSize = sizeof ( PROCESSENTRY32 );
    bRet = Process32First ( hProcessSnap, &pe32 );
    if ( bRet ) {
        do {
                        strBuf.Format(_T("%-16s %4u %u \n") , pe32.szExeFile, pe32.th32ProcessID, pe32.cntThreads ); 
                        strMsg += strBuf;
                        strMsg += _T("\n");
                        m_list.AddString(strBuf);

                        TCHAR szProcessName[MAX_PATH];
                        HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION 
                                                                                   | PROCESS_VM_READ,
                                                                                   FALSE, 
                                                                                   pe32.th32ProcessID);
                   if (NULL != hProcess ) {
                                HMODULE hMod;
                                DWORD cbNeeded;

                                if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), 
                                         &cbNeeded) )
                                {
                                        CString strCommandLine = GetCommandLine();
                                        //4.
                                        GetModuleFileNameEx( hProcess, hMod, szProcessName, 
                                                                           sizeof(szProcessName) );

                                        strBuf = "  ● ";
                                        strBuf += szProcessName;
                                        m_list.AddString(strBuf);

                                        wchar_t params[0x200];
                                        DWORD PidTable[0x1000];
                                        int i=0;
                                        BYTE *peb = GetPEB(hProcess); // Process Environment Block 
                                        DWORD dw, read; 
                                        ReadProcessMemory(hProcess, peb+0x10, &dw, sizeof(DWORD), &read); // Process Parameters 
                                        ReadProcessMemory(hProcess, (PVOID)(dw+0x44), &dw, sizeof(DWORD), &read); 
                                        // command line 
                                        ReadProcessMemory(hProcess, (PVOID)dw, &params, sizeof(params), &read); 
                                        wprintf(L"PID %08x: %s\n", PidTable[i], params); 

                                        strBuf = "  ■ ";
                                        strBuf += params;
                                        m_list.AddString(strBuf);

                                        ReadProcessMemory(hProcess, peb+0x10, &dw, sizeof(DWORD), &read); // Process Parameters 
                                        ReadProcessMemory(hProcess, (PVOID)(dw+0x44-sizeof(UNICODE_STRING)*3-sizeof(HANDLE)), &dw, sizeof(DWORD), &read); 
                                        // command line 
                                        ReadProcessMemory(hProcess, (PVOID)dw, &params, sizeof(params), &read); 
                                        wprintf(L"PID %08x: %s\n", PidTable[i], params); 

                                        strBuf = "  ★ ";
                                        strBuf += params;
                                        m_list.AddString(strBuf);
                                }
                                else continue;

                                
                                CloseHandle(hProcess);
                        }

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

    CloseHandle ( hProcessSnap );


カテゴリー
ウィンドウズストア アプリ
WPFアプリ(C#)
MFC
Windows API
ASP.NET
プログラミングトピック
参考書籍
開発ツール





実行すると以下の画像のようになります。