Windows列舉所有程序

2021-06-22 08:43:06 字數 4749 閱讀 1209

要編寫乙個類似於 windows 任務管理器的軟體,首先遇到的問題是如何實現列舉所有程序。暫且不考慮進入核心態去查隱藏程序一類的,下面提供幾種方法。請注意每種方法的使用侷限,比如使用這些 api 所需要的作業系統是什麼(尤其是是否能在 windows mobile 下使用)。 

本文參考使用者態列舉程序的幾種方法,原文對於每一種方法都給出了完整的**,被我照抄下來。還有一篇:如何用 win32 apis 列舉應用程式視窗和程序。基於我現學現賣的本質,對我演繹的部分請抱著批判的眼光來看,另外**也沒有充分驗證。

使用 toolhelp api 

toolhelp api 的功能就是為了獲取當前執行程式的資訊,從而編寫適合自己需要的工具(@msdn)。它支援的平台比較廣泛,可以在 windows ce 下使用。在 windows mobile sdk 的 samples 裡面有乙個 pviewce 的樣例程式,就是用這個來檢視程序和執行緒資訊的。 

然後呼叫一次 process32first 函式,從快照中獲取第乙個程序,然後重複呼叫 process32next,直到函式返回 false 為止。這樣將遍歷快照中程序列表。這兩個函式都帶兩個引數,它們分別是快照控制代碼和乙個 processentry32 結構。呼叫完 process32first 或 process32next 之後,processentry32 中將包含系統中某個程序的關鍵資訊。其中程序 id 就儲存在此結構的 th32processid。此 id 傳給 openprocess api 可以獲得該程序的控制代碼。對應的可執行檔名及其存放路徑存放在 szexefile 結構成員中。在該結構中還可以找到其它一些有用的資訊。 

需要注意的是:在呼叫 process32first() 之前,要將 processentry32 結構的 dwsize 成員設定成 sizeof(processentry32)。 然後再用 process32first、process32next 來列舉程序。使用結束後要呼叫 closehandle 來釋放儲存的系統快照。

以下為參考**:

#include

#include

#include

void usetoolhelp()

//processentry32 procentry = ;

procentry.dwsize = sizeof(processentry32);

bool bret = process32first(procsnap,&procentry);

while(bret)

closehandle(procsnap);

}void main()

使用 processing status api

在 windows sdk 中可以找到 psapi,通過 psapi 可以獲取程序列表和裝置驅動列表。通過 enumprocesses、enumprocessmodules、getmodulefilenameex 和 getmodulebasename 來實現。

首先使用 enumprocesses 來列舉所有程序,它有三個引數:dword 型別的陣列指標 lpidprocess;該陣列的大小尺寸 cb;以及乙個指向 dword 的指標 cbneeded,它接收返回資料的長度。dword 陣列用於儲存當前執行的程序 ids。cbneeded 返回陣列所用的記憶體大小。下面算式可以得出返回了多少程序:nreturned = cbneeded / sizeof(dword)。

注意:雖然文件將返回的 dword 命名為「cbneeded」,實際上是沒有辦法知道到底要傳多大的陣列的。enumprocesses 根本不會在 cbneeded 中返回乙個大於 cb 引數傳遞的陣列值。所以,唯一確保 enumprocesses 函式成功的方法是分配乙個 dword 陣列,並且,如果返回的 cbneeded 等於 cb,分配乙個較大的陣列,並不停地嘗試直到 cbneeded 小於 cb 。

下面是參考**: 

#include

#include

#include

#include "psapi.h"

#pragma comment(lib,"psapi.lib")

void printprocessnameandid(dword processid)

}wprintf(_t("pid: %d (%s) "),processid,szprocessname);

closehandle(hprocess);

}void main( )

注意到,此方法由於需要進行 openprocess 操作,所以需要一定的許可權,當許可權不夠時,有些程序將不能被開啟。下面給出提公升許可權的相關**:

void raiseprivilege()

}if(htoken)

closehandle(htoken);

}使用 native api

在 使用native api 探測本機系統資訊 中我介紹了 native api 中的 ntquerysysteminformation(zwquerysysteminformation)。當設定查詢的資訊型別為 systemprocessesandthreadsinformation 時(第5號功能),可以用來列舉所有程序和執行緒。

typedef dword (winapi *zwquerysysteminformation)(dword, pvoid, dword, pdword);

typedef struct _system_process_information

system_process_information, *psystem_process_information;

#define systemprocessesandthreadsinformation 5

然後動態載入 ntdll.dll,獲得函式的位址。便可以進行程序的列舉相關**如下:

#include

#include

#include

typedef dword (winapi *zwquerysysteminformation)(dword, pvoid, dword, pdword);

typedef struct _system_process_information

system_process_information, *psystem_process_information;

#define systemprocessesandthreadsinformation 5

void main()

free(pbuffer);

getchar();

}對這個方法有問題的,可以參考我之前的那篇介紹 native api 的文章。

同樣使用 zwquerysysteminformation 函式,查詢型別如果設定為 systemhandleinformation(第16號功能)也可以達到目的。它能獲取系統中所有控制代碼,再加上程序 id 的判斷就可以列舉所有程序了。

#include

#include

#include

#include

typedef ntstatus (winapi *zwquerysysteminformation)(dword, pvoid, dword, pdword);

typedef struct _system_handle_information 

system_handle_information, *psystem_handle_information;

typedef struct _system_handle_information_ex 

system_handle_information_ex, *psystem_handle_information_ex;

#define systemhandleinformation 0x10 //16

void main()

}while(s == status_info_length_mismatch);

psystem_handle_information_ex pinfo = (psystem_handle_information_ex)pbuffer;

ulong oldpid = 0;

for(dword i = 0;inumberofhandles;i++)

}free(pbuffer);

freelibrary(hntdll);

getchar();

}原文中提到,在進行程序「隱藏」工作的時候,此處的控制代碼是一件容易被忽略的地方,因此需要注意隱藏由程式開啟的相關控制代碼。由於系統中控制代碼數量經常變換,所以沒有什麼必要修改其中的 numberofhandles 域,因為如果修改此處的值,則需要不停對控制代碼的變化進行維護,開銷比較大。在使用者態下的程序列舉已經變得不可靠,因為乙個核心級的 rootkit 很容易就能夠更改這些函式的返回結果。所以程序的可靠列舉應在核心態中實現,可以通過編寫驅動來實現。

有關16位程式

根據參考的第二篇文章:在 windows 95,windows 98 和 windows me 中,toolhelp32 對待16位程式一視同仁,它們與 win32 程式一樣有自己的程序 ids。但是在 windows nt,windows 2000 或 windows xp 中情況並不是這樣。在這些作業系統中,16位程式執行在所謂的 vdm 當中(也就是dos機)。

為了在 windows nt,windows 2000 和 windows xp 中列舉16位程式,必須使用乙個名為 vdmenumtaskwowex 的函式。它的宣告包含在 windows sdk 中的 vdmdbg.h 中,並且需要在專案中鏈結 vdmdbg.lib 檔案。

微軟的網上幫助裡面有一篇介紹的文章:如何在 windows nt、 windows 2000 和 windows xp 上使用 vdmdbg 函式。

Windows下如何列舉所有程序

要編寫乙個類似於 windows 任務管理器的軟體,首先遇到的問題是如何實現列舉所有程序。暫且不考慮進入核心態去查隱藏程序一類的,下面提供幾種方法。請注意每種方法的使用侷限,比如使用這些 api 所需要的作業系統是什麼 尤其是是否能在 windows mobile 下使用 本文參考使用者態列舉程序的...

windows列舉所有視窗

目錄 列舉所有視窗,根據視窗的標題進行處理 列舉所有視窗,根據視窗的類進行處理 include include bool callback enumwindowsproc hwnd hwnd,lparam lparam getwindowtext hwnd,sztitle,max path wpri...

列舉程序所有執行緒

include stdafx.h include include include tlhelp32.h 有些位址過低的列舉不到,就給出了位址對照,容錯也沒做怎麼好 typedef enum threadinfoclass threadinfoclass typedef handle stdcall ...