探索黑客技术攻防,实战研究与安全创新

导航菜单

四种方法实现VC枚举系统当前进程

在Windows 2000以上的MS操作系统中,通过windows的任务管理器可以列出当前系统的所有活动进程(如图]所示)。在windowsXP中,在控制台下增加了一条Tasklist命令,可让系统下所有进程都无所遁行《如图2所示)。这一切是怎么实现的呢?

图片17.png

引用侯捷大师在《深入浅出MFC》中的一句话”知其然而不知其所以然,真不是个好办法”。既然如此,我们干脆自己动手,自己通过编程来实现吧.这样很有成就感哦!以下所有代码均在WindowsXP SPl+VC6.0 sp6编译环境下通过。Ok,Let’go!

方法一

第1种方法是大家比较熟悉的通过ToolHelpService提供的API函数来实现的。这里用到了3个关键的函数CreateTooIHalp32SnapsHot()、Process32First()和Process32Klext()。下面给出关于这3个函数的原形和参数说明:

首先使用CreateToolHelp32Snapshot()创建系统快照句柄(Hprocess是我们声明用来保存创建的快照句柄):

然后调用Process32First()获得系统快照中的第个进程信息(Report是BOOL型作为判断系统快照中下一条进程记录):

接着用一个循环调用来遍历系统中所有运行的进程:

笔者曾通过对Pstools工具包里的pslist.exe反编译,发现该工具用的就是这种方法。如果你查询MSDN,可以找到一个比这个功能更加完善的源程序。

方法二

第2种方法也很常见,通过MSDn就可以找到例子代码,它是通过Psapi.dll提供的API函数EnumProcesses和EnumProcessModules来实现。有一点要说明的是:ViSual Studio提供的SDK包里没有提供相应的Psapi.H和与之相对应的导入库。笔者当时就很纳闷.M S DN里的例子居然编译不通.后来才发现,编译时根本找不到"psapi。h”。呵呵,还好,MSDn至少告诉我们它们都包含Psapi.dll星.用vc自带的Depend工具一查.果然。这样就好办了.我们可以自己找到这些函数入口地址。

下面是第二种方法的实现过程首先把Psapi.dl里要用到函数都定义好,以方便后面显示调用。

好.通过每个定义函数前的注释你可以清楚地看到这些原函数名.然后当然要加载包含这些函数模块Psapi.dll:

接着通过Dll入口,我们查找每个函数地址

注意第3个函数名GetModuleFileNameExA,在Dll里有以A和W结尾区分函数.A指采用的是ANSi字符串方式,W则是Unicode方式。于是,我们可以用下面的话句枚举进程

当然,在Google上搜索,可以找到不少提供的Psapi.h头文件和对应的Psapi.lib库,这样,你就可以更方便使用这种方法了。

方法三

也许你会说前两种方法全世界都知道了,没什么大不了的!呵呵,那么笔者现在介绍的第3种方法你就未必知道了。本方法利用了Windows NT/2000下终端服务API函数WTSOpenServer()和WTSEnumerateProcess()来实现,这两个函数都定义在Wtsapi32.dll里。具体的关于终端服务方面的知识,大家可以查询MSDN。首先,我们来显示申明这两个函数原形

和前面一样,要先装载Wisapi32.dll模块,获取关键函数地址

通过Argv[l]给终端服务名(这里我们赋本机NetBios名)赋一个值并打开这项服务

然后开始遍历终端服务器上的所有进程,这里我们是指本机的所有进程:怎么样,酷吧,跟前面两种方法效果一样!

方法四

最后笔者介绍一种最少有人用的方法.本方法是从“幻影旅团”论坛上看到的。后面给出的源代码也是从他们那拷贝过来的。呵呵。这种方法也提供给我们一种很好的思路。

第4种方法利用了N a t i v eAp i的NOuerySystemlnformation函数来实现。同样没有该函数的导入库,也要自己定义原形。整个实现不难,可是有点烦,因为在该函数参数结构上,笔者查MSDN很久才找到这些相关的结构,下面我们来看看这个方法的实现吧。

先是自定义函数原形

然后.还是和前面一样,要找到ZwOuerySystemlnformation在Ntdll.dll模块里的入口地址

获得指向进程信息数组链的第一条进程信息

和方法  方法二一样,在获得第一条进程信息后开始循环遍历,列出其余的进程

特别注意的是这里SYSTEM_PHOC E SSN F O R M A T l ON结构里进程名的类型为AllCODE_STRING,而UNICODE_STRlnG里的成员Buffer定义的是Unicode类型。

所以,最后我们要调用WideChar ToMulByte()来还原成ANSI字符串以便输出:

具体参数大家可以参照MSDN.很简单的。以上4种方法的完整源代码见光盘。

从这里可看出,查看系统当前活动进程的实现也不过如此,况且,笔者还没有给出第5种方法(可以通过WMI的COM接口函数CoCreatelnstance()、ConnectServer()、ExecOuery()等函数来实现,留给读者自己练习).呵呵,好玩吧?居然有那么多种方法。

写这篇文章的目的是想告诉大家,有时候通过自己动手,会发现以前认为很高深的东西原来也是很简单的,只要善于总结.常动手,我们自己也可以打造一些方便好用的小工具来,你说呢?