• <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>
  • 枚舉本地-遠程NT系統進程

    發表于:2007-07-14來源:作者:點擊數: 標簽:
    作者:eyas 以下所說的都不是新技術,也不是新方法,偶只是收集,總結。好久以前寫的,一直沒好意思貼出來。讓各位見笑了。 ------------------------------------------------------------------------------------------------------- 首先說明本文并沒有什
    作者:eyas

    以下所說的都不是新技術,也不是新方法,偶只是收集,總結。好久以前寫的,一直沒好意思貼出來。讓各位見笑了。
    -------------------------------------------------------------------------------------------------------
     

    首先說明本文并沒有什么新的技術,只是做一些歸納總結吧。在這過程中參考了部分書籍和網上的一些資料,加上自己的一些理解,列舉枚舉本地/遠程NT系統進程的的幾種方法,希望對大家有些幫助。


       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


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


    #include <windows.h>


    #include <stdio.h>


    #include "psapi.h"


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





    void PrintProcessNameAndID( DWORD processID )


    {


      char szProcessName[MAX_PATH] = "unknown";


      //取得進程的句柄


      HANDLE hProcess = OpenProcess( PROCESS_QUERY_INFORMATION |


                      PROCESS_VM_READ,


                       FALSE, processID );


      //取得進程名稱


      if ( hProcess )


      {


        HMODULE hMod;


        DWORD cbNeeded;


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


           GetModuleBaseName( hProcess, hMod, szProcessName, sizeof(szProcessName) );


      }


      //回顯進程名稱和ID


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


      CloseHandle( hProcess );


    }





    void main( )


    {


      DWORD aProcesses[1024], cbNeeded, cProcesses;


      unsigned int i;


      //枚舉系統進程ID列表


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


        return;


      // Calculate how many process identifiers were returned.


      //計算進程數量


      cProcesses = cbNeeded / sizeof(DWORD);


      // 輸出每個進程的名稱和ID


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


         PrintProcessNameAndID( aProcesses[i] );


      return;


    }


    基于PSAPI,shotgun寫了個比較完整的命令行下內存進程/模塊查看器,可以顯示內存中所有的進程及進程調用的所有模塊文件(DLL),可以用來協助程序、DLL的調試,也可以用來查找DLL木馬和后門。有興趣的讀者可以從http://www.patching.net/shotgun/ps.zip下載,壓縮包包含C++源代碼。





    <<第二部分:調用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


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


    #include <windows.h>


    #include <tlhelp32.h>


    #include <stdio.h>


    int main()


    {


       HANDLE     hProcessSnap = NULL;


      PROCESSENTRY32 pe32   = {0};


      hProcessSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);


      if (hProcessSnap == (HANDLE)-1)


      {


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


        return 1;


      }


      pe32.dwSize = sizeof(PROCESSENTRY32);


       printf("\nProcessName     ProcessID");


      if (Process32First(hProcessSnap, &pe32))


      {


        do


        {


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


        }


        while (Process32Next(hProcessSnap, &pe32));


      }


      else


      {


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


      }


      CloseHandle (hProcessSnap);


      return 0;


    }





    <<第三部分:調用NTDLL.DLL中未公開API枚舉本地系統進程>>


       第一部分和第二部分說的是調用MS公開的API來枚舉系統進程,在NTDLL.DLL中其實有一個未公開API,也可以用來枚舉系統進程。此方法是從別處看來的,我可沒這本事自己發現哦,出處記不清楚了,好像是pwdump2 中的源代碼中的一部分吧。


        OK!那個未公開API就是NtQuerySystemInformation,使用方法如下,以下代碼是從pwdump2中修改了一點點而來的:


    ////////////////////////////////////////////////////////////////////////////////////////////////


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


    }





    <<第四部分:從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 suclearcase/" target="_blank" >ccess 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;


    }


    ///////////////////////////////////////////////////////////////////////////////////////


    void banner()


    {


        printf("\nPsList ==>Local and Remote process list"


                "\nPower by ey4s<ey4s@21cn.com>"


                "\nhttp://www.ey4s.org"


                "\n2001/6/22\n");


    }


    /////////////////////////////////////////////////////////////////////////////////////


       程序在Windows2000、VC++6.0環境下編譯,運行良好。注意哦,遠程機器要允許IPC連接和遠程操作注冊表才可以哦,并且需要Admin權限,編譯好的程序在我的主頁http://www.ey4s.org有下載。

    原文轉自:http://www.kjueaiud.com

    老湿亚洲永久精品ww47香蕉图片_日韩欧美中文字幕北美法律_国产AV永久无码天堂影院_久久婷婷综合色丁香五月

  • <ruby id="5koa6"></ruby>
    <ruby id="5koa6"><option id="5koa6"><thead id="5koa6"></thead></option></ruby>

    <progress id="5koa6"></progress>

  • <strong id="5koa6"></strong>