|
楼主 |
发表于 2013-8-3 11:16:19
|
显示全部楼层
河北省衡水市
本帖最后由 小白兔° 于 2013-8-3 11:18 编辑
<<第三部分:调用NTDLL.DLL中未公开API枚举本地系统进程>>
第一部分和第二部分说的是调用MS公开的API来枚举系统进程,在NTDLL.DLL中其实有一个未公开API,也可以用来枚举系统进程。此方法是从别处看来的,我可没这本事自己发现哦,出处记不清楚了,好像是pwdump2 中的源代码中的一部分吧。
OK!那个未公开API就是NtQuerySystemInformation,使用方法如下:
////////////////////////////////////////////////////////////////////////////////- #include <windows.h>
- #include <stdio.h>
- #include <stdlib.h>
- typedef unsigned long NTSTATUS;
- typedef unsigned short USHORT;
- typedef unsigned long ULONG;
- typedef unsigned long DWORD;
- typedef long LONG;
- typedef __int64 LONGLONG;
- typedef struct {
- USHORT Length;
- USHORT MaxLen;
- USHORT *Buffer;
- } UNICODE_STRING;
- struct process_info {
- ULONG NextEntryDelta;
- ULONG ThreadCount;
- ULONG Reserved1[6];
- LARGE_INTEGER CreateTime;
- LARGE_INTEGER UserTime;
- LARGE_INTEGER KernelTime;
- UNICODE_STRING ProcessName;
- ULONG BasePriority;
- ULONG ProcessId;
- };
- typedef NTSTATUS (__stdcall *NtQuerySystemInformation1)(
- IN ULONG SysInfoClass,
- IN OUT PVOID SystemInformation,
- IN ULONG SystemInformationLength,
- OUT PULONG RetLen
- );
- int main()
- {
- HINSTANCE hNtDll;
- NtQuerySystemInformation1 NtQuerySystemInformation;
- NTSTATUS rc;
- ULONG ulNeed = 0;
- void *buf = NULL;
- size_t len = 0;
- struct process_info *p ;
- int done;
- hNtDll = LoadLibrary ("NTDLL");
- if (!hNtDll)
- return 0;
- NtQuerySystemInformation = (NtQuerySystemInformation1)GetProcAddress (hNtDll,
- "NtQuerySystemInformation");
- if (!NtQuerySystemInformation)
- return 0;
- do {
- len += 0x1000;
- buf = realloc (buf, len);
- if (!buf)
- return 0;
- rc = NtQuerySystemInformation (5, buf, len, &ulNeed);
- } while (rc == 0xc0000004); // STATUS_INFO_LEN_MISMATCH
- if (rc <0) {
- free (buf);
- return 0;
- }
- printf("\nProcessName ProcessID");
- p = (struct process_info *)buf;
- done = 0;
- while (!done) {
- if ((p->ProcessName.Buffer != 0))
- {
- printf("\n%-20S%d",p->ProcessName.Buffer,p->ProcessId);
- }
- done = p->NextEntryDelta == 0;
- p = (struct process_info *)(((char *)p) + p->NextEntryDelta);
- }
- free (buf);
- FreeLibrary (hNtDll);
- return 0;
- }
- </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。
程序代码如下:
/**************************************************************************- Module:ps.c
- Author:mikeblas@nwlink.com
- Modify:ey4s<EY4S@21CN.COM>
- Http://www.ey4s.org
- Date:2001/6/23
- **************************************************************************/
- #include <stdio.h>
- #include <windows.h>
- #include <winnetwk.h>
- #define INITIAL_SIZE 51200
- #define EXTEND_SIZE 12800
- #define REGKEY_PERF "software\\microsoft\\windows nt\\currentversion\\perflib"
- #define REGSUBKEY_COUNTERS "Counters"
- #define PROCESS_COUNTER "process"
- #define PROCESSID_COUNTER "id process"
- #define UNKNOWN_TASK "unknown"
- #define MaxProcessNum 52//最大进程数量
- #pragma comment(lib,"mpr.lib")
- typedef struct ProcessInfo
- {
- char ProcessName[128];
- DWORD dwProcessID;
- }pi;
- void banner();
- int ConnIPC(char *,char *,char *);
- DWORD GetProcessInfo(pi *,char *,char *,char *);
- int main(int argc,char **argv)
- {
- int i,iRet;
- pi TaskList[MaxProcessNum];
- banner();
- if(argc==1)
- {
- iRet=GetProcessInfo(TaskList,NULL,NULL,NULL);
- printf("\nProcess Info for [LOCAL]:");
- }
- else if(argc==4)
- {
- iRet=GetProcessInfo(TaskList,argv[1],argv[2],argv[3]);
- printf("\nProcess Info for [%s]:",argv[1]);
- }
- else
- {
- printf("\nUsage:%s <ip><username><pass>",argv[0]);
- return 1;
- }
- if(iRet>0)
- for(i=0,printf("\nProcessName ProcessID");
- i<IRET;>
- printf("\n%-20s %d",TaskList[i].ProcessName,TaskList[i].dwProcessID),i++);
- return 0;
- }
- DWORD GetProcessInfo(pi *ProList,char *ip,char *user,char *pass)
- {
- DWORD rc,dwType,dwSize,i,dwProcessIdTitle,dwProcessIdCounter,dwRet=-1;
- HKEY hKeyNames;
- LPSTR buf = NULL,p,p2;
- CHAR szSubKey[1024],szProcessName[MAX_PATH];
- PPERF_DATA_BLOCK pPerf;
- PPERF_OBJECT_TYPE pObj;
- PPERF_INSTANCE_DEFINITION pInst;
- PPERF_COUNTER_BLOCK pCounter;
- PPERF_COUNTER_DEFINITION pCounterDef;
- HKEY ghPerfKey =NULL, // get perf data from this key
- ghMachineKey = NULL; // get title index from this key
- BOOL bRemote=FALSE;
- // Look for the list of counters. Always use the neutral
- // English version, regardless of the local language. We
- // are looking for some particular keys, and we are always
- // going to do our looking in English. We are not going
- // to show the user the counter names, so there is no need
- // to go find the corresponding name in the local language.
- __try
- {
- if((ip)&&(user)&&(pass))
- {
- if(ConnIPC(ip,user,pass)!=0)
- {
- printf("\nConnect to %s failed.",ip);
- __leave;
- }
- else
- bRemote=TRUE;
- }
- //连接本地or远程注册表
- if(RegConnectRegistry(ip,HKEY_PERFORMANCE_DATA,
- &ghPerfKey)!=ERROR_SUCCESS)
- {
- printf("\nRegConnectRegistry() 1 failed:%d",GetLastError());
- __leave;
- }
- ` if(RegConnectRegistry(ip,HKEY_LOCAL_MACHINE,&ghMachineKey)!=ERROR_SUCCESS)
- {
- printf("\nRegConnectRegistry() 2 failed:%d",GetLastError());
- __leave;
- }
- sprintf( szSubKey, "%s\\%03x", REGKEY_PERF,MAKELANGID( LANG_ENGLISH, SUBLANG_NEUTRAL));
- if(RegOpenKeyEx(ghMachineKey,szSubKey,0,KEY_READ,&hKeyNames)!=ERROR_SUCCESS)
- __leave;
- // 从counter names取得需要的缓冲区大小
- if(RegQueryValueEx(hKeyNames,REGSUBKEY_COUNTERS,NULL,&dwType,NULL,&dwSize)!= ERROR_SUCCESS)
- __leave;
- //分配内存
- buf = (LPSTR) malloc( dwSize );
- if (buf == NULL)
- __leave;
- memset( buf, 0, dwSize );
- // read the counter names from the registry
- if(RegQueryValueEx(ghPerfKey,REGSUBKEY_COUNTERS,NULL,&dwType,(LPBYTE) buf,&dwSize)!= ERROR_SUCCESS)
- __leave;
- // now loop thru the counter names looking for the following counters:
- // 1. "Process" process name
- // 2. "ID Process" process id
- // the buffer contains multiple null terminated strings and then
- // finally null terminated at the end. the strings are in pairs of
- // counter number and counter name.
- p = buf;
- while (*p)
- {
- if (p>buf)
- for( p2=p-2; isdigit(*p2); p2--) ;
- if (stricmp(p, PROCESS_COUNTER) == 0)
- {
- // look backwards for the counter number
- for( p2=p-2; isdigit(*p2); p2--) ;
- strcpy( szSubKey, p2+1 );
- }
- else if (stricmp(p, PROCESSID_COUNTER) == 0)
- {
- // look backwards for the counter number
- for( p2=p-2; isdigit(*p2); p2--) ;
- dwProcessIdTitle = atol( p2+1 );
- }
- // next string
- p += (strlen(p) + 1);
- }
- // free the counter names buffer
- free( buf );
- // allocate the initial buffer for the performance data
- dwSize = INITIAL_SIZE;
- buf = (LPSTR) malloc( dwSize );
- while (TRUE)
- {
- if (buf == NULL)
- __leave;
- memset( buf, 0, dwSize );
- rc=RegQueryValueEx(ghPerfKey,szSubKey,NULL,&dwType,(LPBYTE) buf,&dwSize);
- pPerf = (PPERF_DATA_BLOCK) buf;
- // check for success and valid perf data block signature
- if ((rc == ERROR_SUCCESS) &&
- (dwSize > 0) &&
- (pPerf)->Signature[0] == (WCHAR)'P' &&
- (pPerf)->Signature[1] == (WCHAR)'E' &&
- (pPerf)->Signature[2] == (WCHAR)'R' &&
- (pPerf)->Signature[3] == (WCHAR)'F' )
- break;
- // if buffer is not big enough, reallocate and try again
- if (rc == ERROR_MORE_DATA)
- {
- dwSize += EXTEND_SIZE;
- buf = (LPSTR) realloc( buf, dwSize );
- }
- else __leave;
- }
- // set the perf_object_type pointer
- pObj = (PPERF_OBJECT_TYPE) ((DWORD)pPerf + pPerf->HeaderLength);
- //loop thru the performance counter definition records looking
- //for the process id counter and then save its offset
- pCounterDef = (PPERF_COUNTER_DEFINITION) ((DWORD)pObj + pObj->HeaderLength);
- for (i=0; i<(DWORD)pObj->NumCounters; i++)
- {
- if (pCounterDef->CounterNameTitleIndex == dwProcessIdTitle)
- {
- dwProcessIdCounter = pCounterDef->CounterOffset;
- break;
- }
- pCounterDef++;
- }
- pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pObj + pObj->DefinitionLength);
- // loop thru the performance instance data extracting each process name
- // and process id
- for (i=0; i < (DWORD)pObj->NumInstances-1 && i<MAXPROCESSNUM; i++)>
- {
- // pointer to the process name
- p = (LPSTR) ((DWORD)pInst + pInst->NameOffset);
- // convert it to ascii
- rc = WideCharToMultiByte( CP_ACP,0,(LPCWSTR)p,-1,szProcessName,sizeof(szProcessName),NULL,NULL);
- // if we cant convert the string then use a default value
- if (!rc) strcpy( ProList[i].ProcessName, UNKNOWN_TASK );
- else strncpy(ProList[i].ProcessName, szProcessName,sizeof(ProList[i].ProcessName)-1);
- // get the process id
- pCounter = (PPERF_COUNTER_BLOCK) ((DWORD)pInst + pInst->ByteLength);
- ProList[i].dwProcessID = *((LPDWORD) ((DWORD)pCounter + dwProcessIdCounter));
- // next process
- pInst = (PPERF_INSTANCE_DEFINITION) ((DWORD)pCounter + pCounter->ByteLength);
- }
- dwRet=i;
- }//end of try
- __finally
- {
- if (buf) free( buf );
- RegCloseKey( hKeyNames );
- RegCloseKey( HKEY_PERFORMANCE_DATA );
- if(bRemote)
- {
- char tmp[52],tmp2[96];
- strncpy(tmp,ip,sizeof(tmp)-1);
- wsprintf(tmp2,"\\\\%s\\ipc$",tmp);
- WNetCancelConnection2(tmp2,CONNECT_UPDATE_PROFILE,TRUE);
- }
- }
- return dwRet;
- }
- ////////////////////////////////////////////////////////////////////////////////
- int ConnIPC(char *RemoteName,char *User,char *Pass)
- {
- NETRESOURCE nr;
- char RN[50]="\\\";
- strncat(RN,RemoteName,sizeof(RN)-11);
- strcat(RN,"\\ipc$");
- nr.dwType=RESOURCETYPE_ANY;
- nr.lpLocalName=NULL;
- nr.lpRemoteName=RN;
- nr.lpProvider=NULL;
- if(WNetAddConnection2(&nr,Pass,User,FALSE)==NO_ERROR)
- return 0;
- else
- return 1;
- }
- </pass></username></ip></winnetwk.h></windows.h></stdio.h>
复制代码 程序在Windows2000、VC++6.0环境下编译,运行良好。注意哦,远程机器要允许IPC连接和远程操作注册表才可以哦,并且需要Admin权限 |
|