我是靠谱客的博主 美好唇彩,最近开发中收集的这篇文章主要介绍获取所有进程的映像路径以及命令VC源代码,觉得挺不错的,现在分享给大家,希望可以做个参考。

概述

  1. http://code1.okbase.net/codefile/CommandLine.cpp_201211112590_1.htm
    /*****************************************************************************************
  2. 在网上,我们似乎很难找到关于获取其他进程命令行的方案或源代码,呵呵~,反正我找了很久还是找不着~~~。废话就不说了,开始进入正题。
  3. 我们知道,如果获取本进程命令行的话,可以通过调用 GetCommandLine 获得, GetCommandLine 返回的是LPTSTR类型的数据,该返回值便是本进程命令行的内存首地址。那么,我们可以让远程执行 GetCommandLine 这个函数,然后获取远程进程中这个函数的返回值,再通过 ReadProcessMemory 把远程进程的命令行读出来就得到我们想要的了。
  4. 具体实现步骤如下:
  5. 1、通过 GetProcAddress 取得 GetCommandLineA 的地址。
  6. 2、用 CreateRemoteThread 启动远程线程,使远程进程执行 GetCommandLineA 。
  7. 3、用 WaitForSingleObject 等待远程线程结束。
  8. 4、用 GetExitCodeThread 取得远程线程退出代码,其实就是远程进程中 GetCommandLineA 函数的返回值,这是远程进程命令行的首地址。
  9. 5、通过 GetProcAddress 取得 lstrlenA 的地址。
  10. 6、用 CreateRemoteThread 启动远程线程,使远程进程执行 lstrlenA 。
  11. 7、用 WaitForSingleObject 等待远程线程结束。
  12. 8、用 GetExitCodeThread 取得远程线程退出代码,其实就是远程进程中 lstrlenA 函数的返回值,这是远程进程命令行的文本长度。
  13. 9、使用 ReadProcessMemory 把远程进程的命令行读取出来。
  14. 10、收工!
  15. ·若要转载,请保持该文章的完整性。
  16. ******************************************************************************************/
  17. //
  18. //功能:获取所有进程的映像路径以及命令行参数
  19. //作者:梁增健(lzj85@163.com)
  20. //MyQQ:184186651
  21. //日期:2007.06.11
  22. //
  23. #include <windows.h>
  24. #include <tlhelp32.h>
  25. #include <iostream.h>
  26. //定义命令行信息结构体
  27. typedef struct tagCOMMANDLINEINFO {
  28. DWORD dwDestCommand_addr;//目标进程命令行的起始地址
  29. DWORD iDestCommandLength;//目标进程命令行的长度
  30. } COMMANDLINEINFO;
  31. //函数声明
  32. BOOLUpgradeProcessPrivilege(HANDLE,LPCTSTR);
  33. BOOLGetProcessCommandLineInfo(HANDLE,COMMANDLINEINFO*);
  34. //主函数
  35. intmain(int argc,char*argv[ ],char*envp[ ] )
  36. {
  37. UpgradeProcessPrivilege(GetCurrentProcess(),SE_DEBUG_NAME);//提升本进程的权限
  38. HANDLE hSnapshot, hProcess;
  39. hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);//创建进程快照
  40. PROCESSENTRY32 pe;
  41. ZeroMemory(&pe,sizeof(PROCESSENTRY32));
  42. pe.dwSize=sizeof(PROCESSENTRY32);
  43. BOOL bFirstProcess=TRUE, bSucceed=FALSE;
  44. do
  45. {
  46. if(bFirstProcess)
  47. bFirstProcess = !(bSucceed=Process32First(hSnapshot,&pe));//获取第一个进程的信息
  48. else
  49. bSucceed = Process32Next(hSnapshot, &pe); //获取下一个进程的信息
  50. if(bSucceed)
  51. {
  52. hProcess = OpenProcess (PROCESS_ALL_ACCESS,FALSE, pe.th32ProcessID);//打开进程
  53. if(hProcess!=0)
  54. {
  55. char*strDestCommand;
  56. COMMANDLINEINFO cli;
  57. ZeroMemory(&cli,sizeof(COMMANDLINEINFO));
  58. if(GetProcessCommandLineInfo(hProcess,&cli))//获取进程的命令行信息
  59. {
  60. try
  61. {
  62. strDestCommand = new char[cli.iDestCommandLength+1];
  63. ZeroMemory(strDestCommand, cli.iDestCommandLength+1);
  64. //读取目标进程的命令行文本
  65. ReadProcessMemory ( hProcess,
  66. (constvoid*)cli.dwDestCommand_addr,
  67. strDestCommand,
  68. cli.iDestCommandLength,
  69. NULL);
  70. cout<<"程序名:"<<pe.szExeFile<<"n命令行:"<<strDestCommand<<"n"<<endl;
  71. delete []strDestCommand;
  72. }
  73. catch(...)
  74. {
  75. cout<<"发生异常!n"<<endl;
  76. }
  77. }
  78. else
  79. {
  80. cout<<"程序名:"<<pe.szExeFile<<"n"<<endl;
  81. }
  82. CloseHandle(hProcess);//关闭进程句柄
  83. }
  84. }
  85. }while(bSucceed);
  86. CloseHandle(hSnapshot);//关闭快照句柄
  87. return0;
  88. }
  89. /****************************************************************************************/
  90. /*****************************************子程序*****************************************/
  91. /****************************************************************************************/
  92. //
  93. //名称:UpgradeProcessPrivilege
  94. //功能:提升进程权限
  95. //作者:梁增健(lzj85@163.com)
  96. //MyQQ:184186651
  97. //日期:2007.06.11
  98. //
  99. BOOLUpgradeProcessPrivilege(HANDLE hProcess,
  100. LPCTSTR lpPrivilegeName=SE_DEBUG_NAME)
  101. {
  102. HANDLE hToken=NULL;
  103. if(OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken))
  104. {
  105. LUIDLuid;
  106. if(LookupPrivilegeValue(NULL, lpPrivilegeName, &Luid))
  107. {
  108. TOKEN_PRIVILEGES tp;
  109. tp.PrivilegeCount=1;
  110. tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
  111. tp.Privileges[0].Luid=Luid;
  112. return(AdjustTokenPrivileges(hToken,FALSE,&tp,0,NULL,NULL) );
  113. }
  114. }
  115. returnFALSE;
  116. }
  117. //
  118. //名称:GetProcessCommandLineInfo
  119. //功能:获取进程命令行信息
  120. //作者:梁增健(lzj85@163.com)
  121. //MyQQ:184186651
  122. //日期:2007.06.11
  123. //
  124. BOOLGetProcessCommandLineInfo(HANDLE hProcess,COMMANDLINEINFO*CommandLineInfo)
  125. {
  126. if(IsBadReadPtr(CommandLineInfo,sizeof(COMMANDLINEINFO)))//判断指针是否有效
  127. returnFALSE;
  128. FARPROCGetCommandLineA_addr, lstrlenA_addr;
  129. HANDLE hThread;
  130. //获取 GetCommandLineA 的地址
  131. GetCommandLineA_addr=GetProcAddress(GetModuleHandle("Kernel32.dll"),"GetCommandLineA");
  132. if(GetCommandLineA_addr==0)
  133. returnFALSE;
  134. //启动远程线程,使远程进程执行 GetCommandLineA 函数
  135. hThread = CreateRemoteThread(hProcess, NULL, 0,
  136. (LPTHREAD_START_ROUTINE)GetCommandLineA_addr,NULL,0,NULL);
  137. if(hThread==0)
  138. returnFALSE;
  139. WaitForSingleObject (hThread,INFINITE);//等待远程线程结束
  140. //作者:梁增健 Email:lzj85@163.com MyQQ:184186651
  141. //获取远程 GetCommandLineA 的返回值,若正常返回,则该值为远程进程命令行的首地址
  142. GetExitCodeThread (hThread,&(CommandLineInfo->dwDestCommand_addr));
  143. CloseHandle (hThread);
  144. if(CommandLineInfo->dwDestCommand_addr==0)
  145. returnFALSE;
  146. //获取 lstrlenA 的地址
  147. lstrlenA_addr = GetProcAddress( GetModuleHandle ("Kernel32.dll"),"lstrlenA");
  148. if(GetCommandLineA_addr==0)
  149. returnFALSE;
  150. //启动远程线程,使远程进程执行 lstrlenA 函数
  151. hThread = CreateRemoteThread(hProcess, NULL, 0,(LPTHREAD_START_ROUTINE)lstrlenA_addr,
  152. (void*)CommandLineInfo->dwDestCommand_addr,0,NULL);
  153. if(hThread==0)
  154. returnFALSE;
  155. WaitForSingleObject (hThread,INFINITE);
  156. //获取远程 lstrlenA 的返回值,若正常返回,则该值为远程进程命令行文本的长度
  157. GetExitCodeThread (hThread,&(CommandLineInfo->iDestCommandLength));
  158. CloseHandle (hThread);
  159. returnTRUE;
  160. }
  161. /*************************************************************************************/
  162. /****************************************子程序***************************************/
  163. /*************************************************************************************/

    开发环境: VC6 Windows XP

    测试环境: WindowsXP

    我们都知道,在程序里获取命令行参数很简单,WinMain函数会以参数的形式传递给我们,或者可以调用API GetCommandLine 获取。但是GetCommandLine函数不接受参数,获取的只是自己程序的命令行参数。那么如果我们想获取别的应用程序的命令行参数应该怎么办呢?
    有的同学说,既然GetCommandLine只能获取本程序的命令行参数,我们可以在其它进程里插入一个Dll,在那个进程的地址空间调用GetCommandLine函数,然后传回来就可以了。这样好像有点儿不太友好。让我们想想还有没有别的办法。

    我们想,自己的命令行参数既然随时都可以获取到,那么在该进程里一定有一个地方存放它。那么在哪儿呢?看一下GetCommandLine函数的反汇编代码,我们发现,原来世界是如此的美好!

    以下是WinXP系统的GetCommandLine函数反汇编代码:

    1. .text:7C812C8D GetCommandLineA proc near
    2. .text:7C812C8D mov eax, dword_7C8835F4     //dword_7C8835F4 就是命令行参数字符串的地址
    3. //该指令机器码为 A1 F4 35 88 7C,从第2个字节开始的4个字节就是我们要的地址
    4. .text:7C812C92 retn
    5. .text:7C812C92 GetCommandLineA endp

    既然知道了放在哪儿了,我们自己去拿就可以了。因为GetCommandLine函数的地址在各个进程内都是一样的,所以可以直接用我们进程里的地址。 win2000/xp系统很简单,98下稍微麻烦一点儿,需要进行一些简单的计算。 以下是GetCommandLine函数在win98下的汇编代码:

    01. .text:BFF8C907 GetCommandLineA proc near
    02. .text:BFF8C907 mov eax, dword_BFFCADE4
    03. .text:BFF8C90C mov ecx, [eax]
    04. .text:BFF8C90E mov eax, [ecx+0C0h]
    05. .text:BFF8C914 test eax, eax
    06. .text:BFF8C916 jnz short locret_BFF8C91E
    07. .text:BFF8C918 mov eax, [ecx+40h]
    08. .text:BFF8C91B mov eax, [eax+8] //算到这儿,才是我们想要的地址
    09. .text:BFF8C91E
    10. .text:BFF8C91E locret_BFF8C91E: ; CODE XREF: GetCommandLineA+F.
    11. .text:BFF8C91E retn

    这样,我们就可以调用OpenProcess函数打开其它进程,然后用ReadProcessMemory读取相应的数据即可。 示例代码:

    view source
    print ?
    01. DWORD g_GetCmdLine(DWORD dwPID,TCHAR* pCmdLine,DWORD dwBufLen)
    02. {
    03. #define BUFFER_LEN    512        //reading buffer for the commandline
    04.  
    05. HANDLE hProc = OpenProcess(PROCESS_VM_READ,FALSE,dwPID);
    06. if(hProc == NULL)
    07. {
    08. return GetLastError();
    09. }
    10.  
    11. DWORD dwRet = -1;
    12. DWORD dwAddr = *(DWORD*)((DWORD)GetCommandLine + 1);//第2个字节开始才是我们要读的地址
    13. TCHAR tcBuf[BUFFER_LEN] = {0};
    14. DWORD dwRead = 0;
    15.  
    16. //判断平台
    17. DWORD dwVer = GetVersion();
    18. try
    19. {
    20. if(dwVer < 0x80000000)        // Windows NT/2000/XP
    21. {
    22. if(ReadProcessMemory(hProc,(LPVOID)dwAddr,&dwAddr,4,&dwRead))
    23. {
    24. if(ReadProcessMemory(hProc,(LPVOID)dwAddr,tcBuf,BUFFER_LEN,&dwRead))
    25. {
    26. _tcsncpy(pCmdLine,tcBuf,dwBufLen);    //最好检查一下dwRead和dwBufLen的大小,使用较小的那个
    27. dwRet = 0;
    28. }
    29. }        
    30. }
    31. else                        // Windows 95/98/Me    and Win32s
    32. {
    33. while(true)                //使用while是为了出错时方便跳出循环
    34. {
    35. if(!ReadProcessMemory(hProc,(LPVOID)dwAddr,&dwAddr,4,&dwRead))break;
    36. if(!ReadProcessMemory(hProc,(LPVOID)dwAddr,&dwAddr,4,&dwRead))break;
    37.  
    38. if(!ReadProcessMemory(hProc,(LPVOID)(dwAddr + 0xC0),tcBuf,BUFFER_LEN,&dwRead)) break;
    39. if(*tcBuf == 0)
    40. {
    41. if(!ReadProcessMemory(hProc,(LPVOID)(dwAddr + 0x40),&dwAddr,4,&dwRead)) break;
    42. if(!ReadProcessMemory(hProc,(LPVOID)(dwAddr + 0x8),&dwAddr,4,&dwRead)) break;
    43. if(!ReadProcessMemory(hProc,(LPVOID)dwAddr,tcBuf,BUFFER_LEN,&dwRead)) break;
    44. }
    45.  
    46. _tcsncpy(pCmdLine,tcBuf,dwBufLen);    //最好检查一下dwRead和dwBufLen的大小,使用较小的那个
    47. dwRet = 0;
    48. break;
    49. }
    50. }
    51. }
    52. catch(...)
    53. {
    54. dwRet = ERROR_INVALID_ACCESS;    //exception
    55. }
    56. CloseHandle(hProc);
    57.  
    58. return dwRet;
    59. }

    全文完


    1. #include "stdafx.h"
    2. #include <windows.h>
    3. #include <stdio.h>
    4. #include <conio.h>

    5. //UNICODE_STRING结构定义
    6. typedef struct
    7. {
    8.         USHORT Length;
    9.         USHORT MaximumLength;
    10.         PWSTR Buffer;
    11. }UNICODE_STRING, *PUNICODE_STRING;


    12. //进程参数结构定义,必有和NativeAPI规范相符和
    13. typedef struct
    14. {
    15.         ULONG AllocationSize;
    16.         ULONG ActualSize;
    17.         ULONG Flags;
    18.         ULONG Unknown1;
    19.         UNICODE_STRING Unknown2;
    20.         HANDLE InputHandle;
    21.         HANDLE OutputHandle;
    22.         HANDLE ErrorHandle;
    23.         UNICODE_STRING CurrentDirectory;
    24.         HANDLE CurrentDirectoryHandle;
    25.         UNICODE_STRING SearchPaths;
    26.         UNICODE_STRING ApplicationName;
    27.         UNICODE_STRING CommandLine;
    28.         PVOID EnvironmentBlock;
    29.         ULONG Unknown[9];
    30.         UNICODE_STRING Unknown3;
    31.         UNICODE_STRING Unknown4;
    32.         UNICODE_STRING Unknown5;
    33.         UNICODE_STRING Unknown6;
    34. }PROCESS_PARAMETERS, *PPROCESS_PARAMETERS;

    35. //PEB: Process Environment Block, 进程环境变量块
    36. typedef struct
    37. {
    38.         ULONG AllocationSize;
    39.         ULONG Unknown1;
    40.         HINSTANCE ProcessHinstance;
    41.         PVOID ListDlls;
    42.         PPROCESS_PARAMETERS ProcessParameters;
    43.         ULONG Unknown2;
    44.         HANDLE Heap;
    45. }PEB,*PPEB;

    46. //进程基本信息结构定义
    47. typedef struct
    48. {
    49.         DWORD ExitStatus;
    50.         PPEB PebBaseAddress;
    51.         DWORD AffinityMask;
    52.         DWORD BasePriority;
    53.         ULONG UniqueProcessId;
    54.         ULONG InheritedFromUniqueProcessId;
    55. }PROCESS_BASIC_INFORMATION;

    56. //函数指针定义,类型为WINDOWS Native API, 用于获取NtQueryInformationProcess的地址
    57. typedef LONG(WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG);

    58. //函数指针声明
    59. PROCNTQSIP NtQueryInformationProcess;

    60. //获取进程的命令行参数
    61. //dwId:输入参数,进程ID
    62. //wBuf:输出参数,用于存储命令行参数的缓冲区指针
    63. //dwBufLen:输入参数,缓冲区的大小
    64. //返回值:TRUE,成功FALSE,失败
    65. BOOL GetProcessCmdLine(DWORD dwId,LPWSTR wBuf,DWORD dwBufLen);

    66. //提升权限的函数
    67. void EnableDebugPriv(void);

    68. //主函数,程序入口
    69. void main(int argc,char* argv[])
    70. {
    71.         //命令行参数合法性判断
    72.         if(argc!=2)
    73.         {
    74.                 printf("usage:nt%s <PID>n",argv[0]);
    75.                 return;
    76.         }
    77.         //提升权限,否则无法读取其它进程信息
    78.         EnableDebugPriv();
    79.         //获取WINDOWS Native API NtQueryInformationProcess的入口地址
    80.         NtQueryInformationProcess=(PROCNTQSIP)GetProcAddress(GetModuleHandle("ntdll"),"NtQueryInformationProcess");
    81.         //获取的函数入口的合法性检查
    82.         if(!NtQueryInformationProcess)
    83.         {
    84.                 return;
    85.         }
    86.         //从命令行获取目标进程的PID
    87.         DWORD dwId;
    88.         sscanf(argv[1],"%lu",&dwId);
    89.         //定义缓冲区,用于获得目标进程的命令行参数
    90.         WCHAR wstr[2048];
    91.         //清空缓冲区
    92.         ZeroMemory(wstr,sizeof(wstr));
    93.         //获取目标进程的命令行参数
    94.         if(GetProcessCmdLine(dwId,wstr,sizeof(wstr)))
    95.         {
    96.                 //获取成功,打印结果
    97.                 wprintf(L"commandline for process %lu is:n %sn",dwId,wstr);
    98.         }
    99.         else
    100.         {
    101.                 //获取失败,打印提示信息
    102.                 wprintf(L"Could not Get Command Line!");
    103.         }
    104. }
    105. //获取进程的命令行参数
    106. BOOL GetProcessCmdLine(DWORD dwId,LPWSTR wBuf,DWORD dwBufLen)
    107. {
    108.         LONG status;
    109.         HANDLE hProcess;
    110.         PROCESS_BASIC_INFORMATION pbi;
    111.         PEB Peb;
    112.         PROCESS_PARAMETERS ProcParam;
    113.         DWORD dwDummy;
    114.         DWORD dwSize;
    115.         LPVOID IpAddress;
    116.         BOOL bRet=FALSE;

    117.         //打开进程,获取查询和毒虚拟内存的权限
    118.         hProcess=OpenProcess(PROCESS_QUERY_INFORMATION| PROCESS_VM_READ,FALSE,dwId);
    119.         if(!hProcess)
    120.         {
    121.                 return FALSE;
    122.         }

    123.         //查询进程的基本信息,获取PEB
    124.         status=NtQueryInformationProcess(hProcess,0,(PVOID)&pbi,sizeof(PROCESS_BASIC_INFORMATION),NULL);
    125.         if(status)
    126.         {
    127.                 goto EndGet;
    128.         }
    129.         //读取进程的PEB指针
    130.         if(!ReadProcessMemory(hProcess,pbi.PebBaseAddress,&Peb,sizeof(PEB),&dwDummy))
    131.         {
    132.                 goto EndGet;
    133.         }
    134.         //获取目标进程空间存储的命令行参数字符串的指针
    135.         if(!ReadProcessMemory(hProcess,Peb.ProcessParameters,&ProcParam,sizeof(PROCESS_PARAMETERS),&dwDummy))
    136.         {
    137.                 goto EndGet;
    138.         }
    139.         IpAddress=ProcParam.CommandLine.Buffer;
    140.         dwSize=ProcParam.CommandLine.Length;
    141.         if(dwBufLen<dwSize)
    142.         {
    143.                 goto EndGet;
    144.         }
    145.         //读取目标进程的命令行参数到本进程的缓冲区
    146.         if(!ReadProcessMemory(hProcess,IpAddress,wBuf,dwSize,&dwDummy))
    147.         {
    148.                 goto EndGet;
    149.         }
    150.         bRet=TRUE;

    151. EndGet:
    152.         //关闭目标进程的句柄
    153.         CloseHandle(hProcess);
    154.         return bRet;
    155. }
    156. //提升本进程权限
    157. void EnableDebugPriv(void)
    158. {
    159.         HANDLE hToken;
    160.         LUID sedebugnameValue;
    161.         TOKEN_PRIVILEGES tkp;

    162.         //打开本进程,获得调整权限的权限
    163.         if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
    164.         {
    165.         return;
    166.         }
    167.         //查询EBUG权限的值
    168.         if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&sedebugnameValue))
    169.         {
    170.         CloseHandle(hToken);
    171.         return;
    172.         }
    173.         tkp.PrivilegeCount=1;
    174.         tkp.Privileges[0].Luid=sedebugnameValue;
    175.         tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
    176.         //调整本进程的权限,使之具有可以高度其它进程的权限
    177.         AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof tkp,NULL,NULL);
    178.         //关闭本进程句柄 
    179.         CloseHandle(hToken);
    180. }


最后

以上就是美好唇彩为你收集整理的获取所有进程的映像路径以及命令VC源代码的全部内容,希望文章能够帮你解决获取所有进程的映像路径以及命令VC源代码所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(32)

评论列表共有 0 条评论

立即
投稿
返回
顶部