Windows下如何列舉所有程序

2021-09-07 21:26:42 字數 4761 閱讀 6922

要編寫乙個類似於 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( )

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

#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();

}

同樣使用 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 //

16void

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...

windows伺服器下殺死ORACLE程序

1.查詢死程序的作業系統id,spid select s.username,s.osuser,s.sid,s.serial p.spid from v session s,v process p where s.paddr p.addr and s.username is not null 2.資料...