开启辅助访问 切换到宽版

精易论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

用微信号发送消息登录论坛

新人指南 邀请好友注册 - 我关注人的新帖 教你赚取精币 - 每日签到


求职/招聘- 论坛接单- 开发者大厅

论坛版规 总版规 - 建议/投诉 - 应聘版主 - 精华帖总集 积分说明 - 禁言标准 - 有奖举报

查看: 1155|回复: 3
收起左侧

[其它] 枚举本地-远程NT系统进程

[复制链接]

结帖率:100% (11/11)
发表于 2013-8-3 11:15:26 | 显示全部楼层 |阅读模式   河北省衡水市
Windows2000中有个工具taskmgr.exe就可以比较详细的查看当前系统进程信息,但是那是Windows GUI程序,有时候是不是觉得命令行下的东西更方便呢?其实已经有不少命令行下的枚举系统进程的工具了,M$的Resource Kit中好象也有,但去了解他们是怎么实现的,自己动手做出来,是不是更有意思呢:)

  进程通常被定义为一个正在运行的程序的实例,它由两部分组成:

  <1>操作系统用来管理进程的内核对象。内核对象也是系统用来存放关于进程的统计信息的地方。

  <2>地址空间。它包含所有可执行模块或DLL模块的代码和数据。它还包含动态内存分配的空间,如线程的堆栈和堆分配空间。

  枚举系统进程的实现方法大概有四种,其中有一种可以用来枚举远程NT系统的进程,前提是有远程系统的管理员权限。



<<第一部分:调用PSAPI函数枚举系统进程>>

  M$的Windows NT开发小组开发了自己Process Status函数,包含在PSAPI.DLL文件中,这些函数只能在高于NT4.0以后的版本中使用。PSAPI一共有14个函数[实际PSAPI.DLL输出函数有19个,但其中有5个函数有两个版本,分别是ANSI和Unicode版本],通过调用这些函数,我们可以很方便的取得系统进程的所有信息,例如进程名、进程ID、父进程ID、进程优先级、映射到进程空间的模块列表等等。为了方便起见,以下的例子程序只获取进程的名字和ID。

  简单的程序如下:

/*************************************************************************

Module:ps.c

说明:调用PSAPI函数枚举系统进程名和ID,Only for NT/2000

*************************************************************************/
  1. #include <windows.h>

  2. #include <stdio.h>

  3. #include "psapi.h"



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



  5. void PrintProcessNameAndID( DWORD processID )

  6. {

  7.   char szProcessName[MAX_PATH] = "unknown";

  8.   //取得进程的句柄

  9.   HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |

  10.                   PROCESS_VM_READ,

  11.                   FALSE, processID );

  12.   //取得进程名称

  13.   if ( hProcess )

  14.   {

  15.     HMODULE hMod;

  16.     DWORD cbNeeded;

  17.     if ( EnumProcessModules( hProcess, &hMod, sizeof(hMod), &cbNeeded) )

  18.       GetModuleBaseName( hProcess, hMod, szProcessName,

  19. sizeof(szProcessName) );

  20.   }

  21.   //回显进程名称和ID

  22.   printf( "\n%-20s%-20d", szProcessName, processID );

  23.   CloseHandle( hProcess );

  24. }



  25. void main( )

  26. {

  27.   DWORD aProcesses[1024], cbNeeded, cProcesses;

  28.   unsigned int i;

  29.   //枚举系统进程ID列表

  30.   if ( !EnumProcesses( aProcesses, sizeof(aProcesses), &cbNeeded ) )

  31.     return;

  32.   // Calculate how many process identifiers were returned.

  33.   //计算进程数量

  34.   cProcesses = cbNeeded / sizeof(DWORD);

  35.   // 输出每个进程的名称和ID

  36.   for ( i = 0; i < cProcesses; i++ )

  37.     PrintProcessNameAndID( aProcesses[i] );

  38.   return;

  39. }
  40. </stdio.h></windows.h>
复制代码
<<第二部分:调用ToolHelp API枚举本地系统进程>>

  在第一部分提到的PSAPI函数只能枚举NT系统的进程,在Windows9x环境下我们可以通过调用ToolHelp API函数来达到枚举系统进程的目的。M$的Windows NT开发小组因为不喜欢ToolHelp函数,所以没有将这些函数添加给Windows NT,所以他们开发了自己的Process Status函数,就是第一部分提到的PSAPI了。但是后来M$已经将ToolHelp函数添加给了Windows 2000。ToolHelp共有12个函数,通过调用这些函数可以方面的取得本地系统进程的详细信息,以下这个简单的例子只调用了三个函数,获取我们所需要系统进程名字和进程ID。程序如下:

/**********************************************************************

Module:ps.c

说明:调用ToolHelp函数枚举本地系统进程名和ID,Only for 9x/2000

**********************************************************************/
  1. #include <windows.h>

  2. #include <tlhelp32.h>

  3. #include <stdio.h>





  4. int main()

  5. {

  6.   HANDLE     hProcessSnap = NULL;

  7.   PROCESSENTRY32 pe32   = {0};

  8.   hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);

  9.   if (hProcessSnap == (HANDLE)-1)

  10.   {

  11.     printf("\nCreateToolhelp32Snapshot() failed:%d",GetLastError());

  12.   return 1;

  13. }

  14.   pe32.dwSize = sizeof(PROCESSENTRY32);

  15.   printf("\nProcessName     ProcessID");

  16.   if (Process32First(hProcessSnap, &pe32))

  17.   {

  18.     do

  19.     {

  20. printf("\n%-20s%d",pe32.szExeFile,pe32.th32ProcessID);

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

  22.   }

  23.   else

  24.   {

  25.     printf("\nProcess32Firstt() failed:%d",GetLastError());

  26.   }

  27.   CloseHandle (hProcessSnap);

  28. return 0;

  29. }
  30. </stdio.h></tlhelp32.h></windows.h>
复制代码

结帖率:100% (11/11)
 楼主| 发表于 2013-8-3 11:16:19 | 显示全部楼层   河北省衡水市
本帖最后由 小白兔° 于 2013-8-3 11:18 编辑

<<第三部分:调用NTDLL.DLL中未公开API枚举本地系统进程>>





   第一部分和第二部分说的是调用MS公开的API来枚举系统进程,在NTDLL.DLL中其实有一个未公开API,也可以用来枚举系统进程。此方法是从别处看来的,我可没这本事自己发现哦,出处记不清楚了,好像是pwdump2 中的源代码中的一部分吧。

    OK!那个未公开API就是NtQuerySystemInformation,使用方法如下:

////////////////////////////////////////////////////////////////////////////////
  1. #include <windows.h>

  2. #include <stdio.h>

  3. #include <stdlib.h>



  4. typedef unsigned long NTSTATUS;

  5. typedef unsigned short USHORT;

  6. typedef unsigned long ULONG;

  7. typedef unsigned long DWORD;

  8. typedef long LONG;

  9. typedef __int64 LONGLONG;

  10. typedef struct {

  11.   USHORT Length;

  12.   USHORT MaxLen;

  13.   USHORT *Buffer;

  14. } UNICODE_STRING;



  15. struct process_info {

  16.   ULONG NextEntryDelta;

  17.   ULONG ThreadCount;

  18.   ULONG Reserved1[6];

  19.   LARGE_INTEGER CreateTime;

  20.   LARGE_INTEGER UserTime;

  21.   LARGE_INTEGER KernelTime;

  22.   UNICODE_STRING ProcessName;

  23.   ULONG BasePriority;

  24.   ULONG ProcessId;

  25. };



  26. typedef NTSTATUS (__stdcall *NtQuerySystemInformation1)(

  27.     IN ULONG SysInfoClass,

  28. IN OUT PVOID SystemInformation,

  29.     IN ULONG SystemInformationLength,

  30.     OUT PULONG RetLen

  31.         );



  32. int main()

  33. {

  34.   HINSTANCE hNtDll;

  35.   NtQuerySystemInformation1 NtQuerySystemInformation;

  36.   NTSTATUS rc;

  37.   ULONG ulNeed = 0;

  38.   void *buf = NULL;

  39.   size_t len = 0;

  40.   struct process_info *p ;

  41.   int done;



  42.   hNtDll = LoadLibrary ("NTDLL");

  43.   if (!hNtDll)

  44.     return 0;

  45.   NtQuerySystemInformation = (NtQuerySystemInformation1)GetProcAddress (hNtDll,

  46. "NtQuerySystemInformation");

  47.     if (!NtQuerySystemInformation)

  48.       return 0;



  49.   do {

  50.     len += 0x1000;

  51.     buf = realloc (buf, len);

  52.     if (!buf)

  53.       return 0;

  54.     rc = NtQuerySystemInformation (5, buf, len, &ulNeed);

  55.   } while (rc == 0xc0000004); // STATUS_INFO_LEN_MISMATCH



  56.   if (rc <0) {

  57.     free (buf);

  58.     return 0;

  59.   }



  60.   printf("\nProcessName     ProcessID");

  61.   p = (struct process_info *)buf;

  62.   done = 0;



  63.   while (!done) {

  64.     if ((p->ProcessName.Buffer != 0))

  65.     {

  66.       printf("\n%-20S%d",p->ProcessName.Buffer,p->ProcessId);



  67.     }

  68.     done = p->NextEntryDelta == 0;

  69.     p = (struct process_info *)(((char *)p) + p->NextEntryDelta);

  70.   }

  71.   free (buf);

  72.   FreeLibrary (hNtDll);

  73.   return 0;

  74. }
  75. </stdlib.h></stdio.h></windows.h>
复制代码
<<第四部分:从PDH中取得本地/远程系统进程信息>>



  前面说的三种方法都只能枚举本地的系统进程,如何枚举远程系统的进程呢?目前我只知道从PDH中取得进程信息。

  OK!我先简单的说说PDH是什么东西,hoho~难的偶也不会。PDH是英文Performance Data Helper的缩写,Windows NT一直在更新这个称为Performance Data的数据库,这个数据库包含了大量的信息,例如CPU使用率,内存使用率,系统进程信息等等一大堆有用的信息,可以通过注册表函数来访问。注意哦,Windows 9x中并没有配置这个数据库。但是,这个数据库中的信息布局很复杂,很多人并不愿意使用它,包括我。而且刚开始的时候,它也没有自己特定的函数,只能通过现有的注册表函数来操作。后来,为了使该数据库的使用变得容易,MS开发了一组Performance Data Helper函数,包含在PDH.DLL文件中。

Windows 2000默认是允许远程注册表操作的,所以我们就可以通过连接远程系统的注册表,从它的PDH中取得我们所需要的系统进程信息了,当然这需要远程系统的Admin权限。

OK!我们下面所举的例子是直接利用注册表函数来从本地/远程系统的PDH数据库中取得我们所需要的数据的,我们并没有利用PDH API。



    程序代码如下:

/**************************************************************************
  1. Module:ps.c

  2. Author:mikeblas@nwlink.com

  3. Modify:ey4s<EY4S@21CN.COM>

  4. Http://www.ey4s.org

  5. Date:2001/6/23

  6. **************************************************************************/

  7. #include <stdio.h>

  8. #include <windows.h>

  9. #include <winnetwk.h>



  10. #define INITIAL_SIZE    51200

  11. #define EXTEND_SIZE     12800

  12. #define REGKEY_PERF     "software\\microsoft\\windows nt\\currentversion\\perflib"

  13. #define REGSUBKEY_COUNTERS "Counters"

  14. #define PROCESS_COUNTER   "process"

  15. #define PROCESSID_COUNTER  "id process"

  16. #define UNKNOWN_TASK    "unknown"

  17. #define MaxProcessNum      52//最大进程数量



  18. #pragma comment(lib,"mpr.lib")



  19. typedef struct ProcessInfo

  20. {

  21. char ProcessName[128];

  22. DWORD dwProcessID;

  23. }pi;



  24. void banner();

  25. int ConnIPC(char *,char *,char *);

  26. DWORD GetProcessInfo(pi *,char *,char *,char *);



  27. int main(int argc,char **argv)

  28. {

  29. int i,iRet;

  30. pi TaskList[MaxProcessNum];

  31. banner();

  32. if(argc==1)

  33. {

  34. iRet=GetProcessInfo(TaskList,NULL,NULL,NULL);

  35.   printf("\nProcess Info for [LOCAL]:");

  36. }

  37. else if(argc==4)

  38. {

  39. iRet=GetProcessInfo(TaskList,argv[1],argv[2],argv[3]);

  40. printf("\nProcess Info for [%s]:",argv[1]);

  41. }

  42. else

  43. {

  44. printf("\nUsage:%s <ip><username><pass>",argv[0]);

  45. return 1;

  46. }

  47. if(iRet>0)   

  48. for(i=0,printf("\nProcessName     ProcessID");

  49. i<IRET;>
  50. printf("\n%-20s %d",TaskList[i].ProcessName,TaskList[i].dwProcessID),i++); 

  51.   return 0;

  52. }



  53. DWORD GetProcessInfo(pi *ProList,char *ip,char *user,char *pass)

  54. {

  55.   DWORD rc,dwType,dwSize,i,dwProcessIdTitle,dwProcessIdCounter,dwRet=-1;

  56.   HKEY             hKeyNames;

  57.   LPSTR            buf = NULL,p,p2;

  58.   CHAR             szSubKey[1024],szProcessName[MAX_PATH];

  59.   PPERF_DATA_BLOCK       pPerf;

  60.   PPERF_OBJECT_TYPE      pObj;

  61.   PPERF_INSTANCE_DEFINITION  pInst;

  62.   PPERF_COUNTER_BLOCK     pCounter;

  63.   PPERF_COUNTER_DEFINITION   pCounterDef;

  64.   HKEY      ghPerfKey =NULL, // get perf data from this key

  65. ghMachineKey = NULL; // get title index from this key

  66.   BOOL bRemote=FALSE;



  67.   // Look for the list of counters. Always use the neutral

  68.   // English version, regardless of the local language. We

  69.   // are looking for some particular keys, and we are always

  70.   // going to do our looking in English. We are not going

  71.   // to show the user the counter names, so there is no need

  72.   // to go find the corresponding name in the local language.



  73.     __try

  74.     {

  75.        if((ip)&&(user)&&(pass))

  76.        {

  77.            if(ConnIPC(ip,user,pass)!=0)

  78.            {

  79.               printf("\nConnect to %s failed.",ip);

  80.               __leave;

  81.            }

  82.            else

  83.               bRemote=TRUE;

  84.       }

  85.        //连接本地or远程注册表

  86.        if(RegConnectRegistry(ip,HKEY_PERFORMANCE_DATA,

  87.            &ghPerfKey)!=ERROR_SUCCESS)

  88.        {

  89.            printf("\nRegConnectRegistry() 1 failed:%d",GetLastError());

  90.            __leave;

  91.        }

  92. `   if(RegConnectRegistry(ip,HKEY_LOCAL_MACHINE,&ghMachineKey)!=ERROR_SUCCESS)

  93.        {

  94.            printf("\nRegConnectRegistry() 2 failed:%d",GetLastError());

  95.            __leave;

  96.        }



  97. sprintf( szSubKey, "%s\\%03x", REGKEY_PERF,MAKELANGID( LANG_ENGLISH, SUBLANG_NEUTRAL));



  98. if(RegOpenKeyEx(ghMachineKey,szSubKey,0,KEY_READ,&hKeyNames)!=ERROR_SUCCESS)

  99.            __leave;



  100.        // 从counter names取得需要的缓冲区大小

  101. if(RegQueryValueEx(hKeyNames,REGSUBKEY_COUNTERS,NULL,&dwType,NULL,&dwSize)!= ERROR_SUCCESS)

  102.   __leave;

  103.        //分配内存

  104.        buf = (LPSTR) malloc( dwSize );

  105.        if (buf == NULL)

  106.            __leave;

  107.        memset( buf, 0, dwSize );

  108.        // read the counter names from the registry

  109. if(RegQueryValueEx(ghPerfKey,REGSUBKEY_COUNTERS,NULL,&dwType,(LPBYTE) buf,&dwSize)!= ERROR_SUCCESS)

  110.            __leave;

  111.        // now loop thru the counter names looking for the following counters:

  112.        //   1. "Process"     process name

  113.        //   2. "ID Process"    process id



  114.        // the buffer contains multiple null terminated strings and then

  115.        // finally null terminated at the end. the strings are in pairs of

  116.        // counter number and counter name.



  117.        p = buf;

  118.        while (*p)

  119.        {

  120.            if (p>buf)

  121.              for( p2=p-2; isdigit(*p2); p2--) ;

  122.            if (stricmp(p, PROCESS_COUNTER) == 0)

  123.            {

  124.               // look backwards for the counter number

  125.              for( p2=p-2; isdigit(*p2); p2--) ;

  126.               strcpy( szSubKey, p2+1 );

  127.            }

  128.            else if (stricmp(p, PROCESSID_COUNTER) == 0)

  129.            {

  130.               // look backwards for the counter number

  131.              for( p2=p-2; isdigit(*p2); p2--) ;

  132.               dwProcessIdTitle = atol( p2+1 );

  133.            }

  134.            // next string

  135.            p += (strlen(p) + 1);

  136.        }

  137.        // free the counter names buffer

  138.        free( buf );

  139.        // allocate the initial buffer for the performance data

  140.        dwSize = INITIAL_SIZE;

  141.        buf = (LPSTR) malloc( dwSize );



  142.        while (TRUE)

  143.        {

  144.            if (buf == NULL)

  145.               __leave;

  146.            memset( buf, 0, dwSize );

  147.            rc=RegQueryValueEx(ghPerfKey,szSubKey,NULL,&dwType,(LPBYTE) buf,&dwSize);

  148.            pPerf = (PPERF_DATA_BLOCK) buf;

  149.            // check for success and valid perf data block signature

  150.            if ((rc == ERROR_SUCCESS) &&

  151.                  (dwSize > 0) &&

  152.                  (pPerf)->Signature[0] == (WCHAR)'P' &&

  153.                  (pPerf)->Signature[1] == (WCHAR)'E' &&

  154.                  (pPerf)->Signature[2] == (WCHAR)'R' &&

  155.                  (pPerf)->Signature[3] == (WCHAR)'F' )

  156.               break;

  157.            // if buffer is not big enough, reallocate and try again

  158.            if (rc == ERROR_MORE_DATA)

  159.            {

  160.               dwSize += EXTEND_SIZE;

  161.               buf = (LPSTR) realloc( buf, dwSize );

  162.            }

  163.            else __leave;

  164.        }

  165.        // set the perf_object_type pointer

  166.        pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);

  167.        //loop thru the performance counter definition records looking

  168.        //for the process id counter and then save its offset



  169.    pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);



  170.     for (i=0; i<(DWORD)pObj->NumCounters; i++)

  171.        {

  172.            if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle)

  173.            {

  174.               dwProcessIdCounter = pCounterDef->CounterOffset;

  175.               break;

  176.            }

  177.            pCounterDef++;

  178.        }



  179.     pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);



  180.        // loop thru the performance instance data extracting each process name

  181.        // and process id



  182.        for (i=0; i < (DWORD)pObj->NumInstances-1 && i<MAXPROCESSNUM; i++)>
  183.        {

  184.            // pointer to the process name

  185.            p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);

  186.            // convert it to ascii

  187.            rc = WideCharToMultiByte( CP_ACP,0,(LPCWSTR)p,-1,szProcessName,sizeof(szProcessName),NULL,NULL);



  188.            // if we cant convert the string then use a default value

  189.            if (!rc) strcpy( ProList[i].ProcessName, UNKNOWN_TASK );

  190.            else strncpy(ProList[i].ProcessName, szProcessName,sizeof(ProList[i].ProcessName)-1);



  191.            // get the process id

  192.        pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);

  193.   ProList[i].dwProcessID = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));



  194.            // next process

  195.   pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);

  196.        }

  197.        dwRet=i;

  198.     }//end of try

  199.     __finally

  200.     {

  201.        if (buf) free( buf );

  202.        RegCloseKey( hKeyNames );

  203.        RegCloseKey( HKEY_PERFORMANCE_DATA );

  204.        if(bRemote)

  205.        {

  206.            char tmp[52],tmp2[96];

  207.            strncpy(tmp,ip,sizeof(tmp)-1);

  208.            wsprintf(tmp2,"\\\\%s\\ipc$",tmp);

  209.            WNetCancelConnection2(tmp2,CONNECT_UPDATE_PROFILE,TRUE);

  210.        }

  211.     }

  212.     return dwRet;

  213. }



  214. ////////////////////////////////////////////////////////////////////////////////



  215. int ConnIPC(char *RemoteName,char *User,char *Pass)

  216. {

  217.     NETRESOURCE nr;

  218.     char RN[50]="\\\";



  219.     strncat(RN,RemoteName,sizeof(RN)-11);

  220.     strcat(RN,"\\ipc$");



  221.     nr.dwType=RESOURCETYPE_ANY;

  222.     nr.lpLocalName=NULL;

  223.     nr.lpRemoteName=RN;

  224.     nr.lpProvider=NULL;



  225.     if(WNetAddConnection2(&nr,Pass,User,FALSE)==NO_ERROR)

  226.        return 0;

  227.     else

  228.        return 1;

  229. }
  230. </pass></username></ip></winnetwk.h></windows.h></stdio.h>
复制代码
程序在Windows2000、VC++6.0环境下编译,运行良好。注意哦,远程机器要允许IPC连接和远程操作注册表才可以哦,并且需要Admin权限
回复 支持 反对

使用道具 举报

结帖率:100% (11/11)
 楼主| 发表于 2013-8-3 11:22:51 | 显示全部楼层   河北省衡水市
fml224 发表于 2013-8-3 11:21
表示好长的说,,,

表示全部仔细的弄成代码形式了!
回复 支持 反对

使用道具 举报

结帖率:57% (13/23)
发表于 2013-8-3 11:21:38 | 显示全部楼层   广东省惠州市
表示好长的说,,,
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则 致发广告者

发布主题 收藏帖子 返回列表

sitemap| 易语言源码| 易语言教程| 易语言论坛| 易语言模块| 手机版| 广告投放| 精易论坛
拒绝任何人以任何形式在本论坛发表与中华人民共和国法律相抵触的言论,本站内容均为会员发表,并不代表精易立场!
论坛帖子内容仅用于技术交流学习和研究的目的,严禁用于非法目的,否则造成一切后果自负!如帖子内容侵害到你的权益,请联系我们!
防范网络诈骗,远离网络犯罪 违法和不良信息举报电话0663-3422125,QQ: 793400750,邮箱:wp@125.la
Powered by Discuz! X3.4 揭阳市揭东区精易科技有限公司 ( 粤ICP备12094385号-1) 粤公网安备 44522102000125 增值电信业务经营许可证 粤B2-20192173

快速回复 返回顶部 返回列表