概述
-
http://code1.okbase.net/codefile/CommandLine.cpp_201211112590_1.htm
/***************************************************************************************** -
在网上,我们似乎很难找到关于获取其他进程命令行的方案或源代码,呵呵~,反正我找了很久还是找不着~~~。废话就不说了,开始进入正题。
-
我们知道,如果获取本进程命令行的话,可以通过调用 GetCommandLine 获得, GetCommandLine 返回的是LPTSTR类型的数据,该返回值便是本进程命令行的内存首地址。那么,我们可以让远程执行 GetCommandLine 这个函数,然后获取远程进程中这个函数的返回值,再通过 ReadProcessMemory 把远程进程的命令行读出来就得到我们想要的了。
-
具体实现步骤如下:
-
1、通过 GetProcAddress 取得 GetCommandLineA 的地址。
-
2、用 CreateRemoteThread 启动远程线程,使远程进程执行 GetCommandLineA 。
-
3、用 WaitForSingleObject 等待远程线程结束。
-
4、用 GetExitCodeThread 取得远程线程退出代码,其实就是远程进程中 GetCommandLineA 函数的返回值,这是远程进程命令行的首地址。
-
5、通过 GetProcAddress 取得 lstrlenA 的地址。
-
6、用 CreateRemoteThread 启动远程线程,使远程进程执行 lstrlenA 。
-
7、用 WaitForSingleObject 等待远程线程结束。
-
8、用 GetExitCodeThread 取得远程线程退出代码,其实就是远程进程中 lstrlenA 函数的返回值,这是远程进程命令行的文本长度。
-
9、使用 ReadProcessMemory 把远程进程的命令行读取出来。
-
10、收工!
-
·若要转载,请保持该文章的完整性。
-
******************************************************************************************/
-
-
//
-
//功能:获取所有进程的映像路径以及命令行参数
-
//作者:梁增健(lzj85@163.com)
-
//MyQQ:184186651
-
//日期:2007.06.11
-
//
-
#include <windows.h>
-
#include <tlhelp32.h>
-
#include <iostream.h>
-
-
//定义命令行信息结构体
-
typedef struct tagCOMMANDLINEINFO {
-
DWORD dwDestCommand_addr;//目标进程命令行的起始地址
-
DWORD iDestCommandLength;//目标进程命令行的长度
-
} COMMANDLINEINFO;
-
-
//函数声明
-
BOOLUpgradeProcessPrivilege(HANDLE,LPCTSTR);
-
BOOLGetProcessCommandLineInfo(HANDLE,COMMANDLINEINFO*);
-
-
//主函数
-
intmain(int argc,char*argv[ ],char*envp[ ] )
-
{
-
UpgradeProcessPrivilege(GetCurrentProcess(),SE_DEBUG_NAME);//提升本进程的权限
-
-
HANDLE hSnapshot, hProcess;
-
hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);//创建进程快照
-
-
PROCESSENTRY32 pe;
-
ZeroMemory(&pe,sizeof(PROCESSENTRY32));
-
pe.dwSize=sizeof(PROCESSENTRY32);
-
BOOL bFirstProcess=TRUE, bSucceed=FALSE;
-
do
-
{
-
if(bFirstProcess)
-
bFirstProcess = !(bSucceed=Process32First(hSnapshot,&pe));//获取第一个进程的信息
-
else
-
bSucceed = Process32Next(hSnapshot, &pe); //获取下一个进程的信息
-
if(bSucceed)
-
{
-
hProcess = OpenProcess (PROCESS_ALL_ACCESS,FALSE, pe.th32ProcessID);//打开进程
-
if(hProcess!=0)
-
{
-
char*strDestCommand;
-
COMMANDLINEINFO cli;
-
ZeroMemory(&cli,sizeof(COMMANDLINEINFO));
-
if(GetProcessCommandLineInfo(hProcess,&cli))//获取进程的命令行信息
-
{
-
try
-
{
-
strDestCommand = new char[cli.iDestCommandLength+1];
-
ZeroMemory(strDestCommand, cli.iDestCommandLength+1);
-
//读取目标进程的命令行文本
-
ReadProcessMemory ( hProcess,
-
(constvoid*)cli.dwDestCommand_addr,
-
strDestCommand,
-
cli.iDestCommandLength,
-
NULL);
-
cout<<"程序名:"<<pe.szExeFile<<"n命令行:"<<strDestCommand<<"n"<<endl;
-
delete []strDestCommand;
-
}
-
catch(...)
-
{
-
cout<<"发生异常!n"<<endl;
-
}
-
}
-
else
-
{
-
cout<<"程序名:"<<pe.szExeFile<<"n"<<endl;
-
}
-
CloseHandle(hProcess);//关闭进程句柄
-
}
-
}
-
}while(bSucceed);
-
CloseHandle(hSnapshot);//关闭快照句柄
-
-
return0;
-
}
-
-
/****************************************************************************************/
-
/*****************************************子程序*****************************************/
-
/****************************************************************************************/
-
//
-
//名称:UpgradeProcessPrivilege
-
//功能:提升进程权限
-
//作者:梁增健(lzj85@163.com)
-
//MyQQ:184186651
-
//日期:2007.06.11
-
//
-
BOOLUpgradeProcessPrivilege(HANDLE hProcess,
-
LPCTSTR lpPrivilegeName=SE_DEBUG_NAME)
-
{
-
HANDLE hToken=NULL;
-
if(OpenProcessToken(hProcess,TOKEN_ALL_ACCESS,&hToken))
-
{
-
LUIDLuid;
-
if(LookupPrivilegeValue(NULL, lpPrivilegeName, &Luid))
-
{
-
TOKEN_PRIVILEGES tp;
-
tp.PrivilegeCount=1;
-
tp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
-
tp.Privileges[0].Luid=Luid;
-
return(AdjustTokenPrivileges(hToken,FALSE,&tp,0,NULL,NULL) );
-
}
-
}
-
returnFALSE;
-
}
-
-
//
-
//名称:GetProcessCommandLineInfo
-
//功能:获取进程命令行信息
-
//作者:梁增健(lzj85@163.com)
-
//MyQQ:184186651
-
//日期:2007.06.11
-
//
-
BOOLGetProcessCommandLineInfo(HANDLE hProcess,COMMANDLINEINFO*CommandLineInfo)
-
{
-
if(IsBadReadPtr(CommandLineInfo,sizeof(COMMANDLINEINFO)))//判断指针是否有效
-
returnFALSE;
-
-
FARPROCGetCommandLineA_addr, lstrlenA_addr;
-
HANDLE hThread;
-
-
//获取 GetCommandLineA 的地址
-
GetCommandLineA_addr=GetProcAddress(GetModuleHandle("Kernel32.dll"),"GetCommandLineA");
-
if(GetCommandLineA_addr==0)
-
returnFALSE;
-
//启动远程线程,使远程进程执行 GetCommandLineA 函数
-
hThread = CreateRemoteThread(hProcess, NULL, 0,
-
(LPTHREAD_START_ROUTINE)GetCommandLineA_addr,NULL,0,NULL);
-
if(hThread==0)
-
returnFALSE;
-
WaitForSingleObject (hThread,INFINITE);//等待远程线程结束
-
//作者:梁增健 Email:lzj85@163.com MyQQ:184186651
-
//获取远程 GetCommandLineA 的返回值,若正常返回,则该值为远程进程命令行的首地址
-
GetExitCodeThread (hThread,&(CommandLineInfo->dwDestCommand_addr));
-
CloseHandle (hThread);
-
if(CommandLineInfo->dwDestCommand_addr==0)
-
returnFALSE;
-
-
//获取 lstrlenA 的地址
-
lstrlenA_addr = GetProcAddress( GetModuleHandle ("Kernel32.dll"),"lstrlenA");
-
if(GetCommandLineA_addr==0)
-
returnFALSE;
-
//启动远程线程,使远程进程执行 lstrlenA 函数
-
hThread = CreateRemoteThread(hProcess, NULL, 0,(LPTHREAD_START_ROUTINE)lstrlenA_addr,
-
(void*)CommandLineInfo->dwDestCommand_addr,0,NULL);
-
if(hThread==0)
-
returnFALSE;
-
WaitForSingleObject (hThread,INFINITE);
-
//获取远程 lstrlenA 的返回值,若正常返回,则该值为远程进程命令行文本的长度
-
GetExitCodeThread (hThread,&(CommandLineInfo->iDestCommandLength));
-
CloseHandle (hThread);
-
-
returnTRUE;
-
}
-
/*************************************************************************************/
-
/****************************************子程序***************************************/
-
/*************************************************************************************/
开发环境: 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读取相应的数据即可。 示例代码:
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.
}
全文完
- #include "stdafx.h"
- #include <windows.h>
- #include <stdio.h>
- #include <conio.h>
-
- //UNICODE_STRING结构定义
- typedef struct
- {
- USHORT Length;
- USHORT MaximumLength;
- PWSTR Buffer;
- }UNICODE_STRING, *PUNICODE_STRING;
-
-
- //进程参数结构定义,必有和NativeAPI规范相符和
- typedef struct
- {
- ULONG AllocationSize;
- ULONG ActualSize;
- ULONG Flags;
- ULONG Unknown1;
- UNICODE_STRING Unknown2;
- HANDLE InputHandle;
- HANDLE OutputHandle;
- HANDLE ErrorHandle;
- UNICODE_STRING CurrentDirectory;
- HANDLE CurrentDirectoryHandle;
- UNICODE_STRING SearchPaths;
- UNICODE_STRING ApplicationName;
- UNICODE_STRING CommandLine;
- PVOID EnvironmentBlock;
- ULONG Unknown[9];
- UNICODE_STRING Unknown3;
- UNICODE_STRING Unknown4;
- UNICODE_STRING Unknown5;
- UNICODE_STRING Unknown6;
- }PROCESS_PARAMETERS, *PPROCESS_PARAMETERS;
-
- //PEB: Process Environment Block, 进程环境变量块
- typedef struct
- {
- ULONG AllocationSize;
- ULONG Unknown1;
- HINSTANCE ProcessHinstance;
- PVOID ListDlls;
- PPROCESS_PARAMETERS ProcessParameters;
- ULONG Unknown2;
- HANDLE Heap;
- }PEB,*PPEB;
-
- //进程基本信息结构定义
- typedef struct
- {
- DWORD ExitStatus;
- PPEB PebBaseAddress;
- DWORD AffinityMask;
- DWORD BasePriority;
- ULONG UniqueProcessId;
- ULONG InheritedFromUniqueProcessId;
- }PROCESS_BASIC_INFORMATION;
-
- //函数指针定义,类型为WINDOWS Native API, 用于获取NtQueryInformationProcess的地址
- typedef LONG(WINAPI *PROCNTQSIP)(HANDLE,UINT,PVOID,ULONG,PULONG);
-
- //函数指针声明
- PROCNTQSIP NtQueryInformationProcess;
-
- //获取进程的命令行参数
- //dwId:输入参数,进程ID
- //wBuf:输出参数,用于存储命令行参数的缓冲区指针
- //dwBufLen:输入参数,缓冲区的大小
- //返回值:TRUE,成功FALSE,失败
- BOOL GetProcessCmdLine(DWORD dwId,LPWSTR wBuf,DWORD dwBufLen);
-
- //提升权限的函数
- void EnableDebugPriv(void);
-
- //主函数,程序入口
- void main(int argc,char* argv[])
- {
- //命令行参数合法性判断
- if(argc!=2)
- {
- printf("usage:nt%s <PID>n",argv[0]);
- return;
- }
- //提升权限,否则无法读取其它进程信息
- EnableDebugPriv();
- //获取WINDOWS Native API NtQueryInformationProcess的入口地址
- NtQueryInformationProcess=(PROCNTQSIP)GetProcAddress(GetModuleHandle("ntdll"),"NtQueryInformationProcess");
- //获取的函数入口的合法性检查
- if(!NtQueryInformationProcess)
- {
- return;
- }
- //从命令行获取目标进程的PID
- DWORD dwId;
- sscanf(argv[1],"%lu",&dwId);
- //定义缓冲区,用于获得目标进程的命令行参数
- WCHAR wstr[2048];
- //清空缓冲区
- ZeroMemory(wstr,sizeof(wstr));
- //获取目标进程的命令行参数
- if(GetProcessCmdLine(dwId,wstr,sizeof(wstr)))
- {
- //获取成功,打印结果
- wprintf(L"commandline for process %lu is:n %sn",dwId,wstr);
- }
- else
- {
- //获取失败,打印提示信息
- wprintf(L"Could not Get Command Line!");
- }
- }
- //获取进程的命令行参数
- BOOL GetProcessCmdLine(DWORD dwId,LPWSTR wBuf,DWORD dwBufLen)
- {
- LONG status;
- HANDLE hProcess;
- PROCESS_BASIC_INFORMATION pbi;
- PEB Peb;
- PROCESS_PARAMETERS ProcParam;
- DWORD dwDummy;
- DWORD dwSize;
- LPVOID IpAddress;
- BOOL bRet=FALSE;
-
- //打开进程,获取查询和毒虚拟内存的权限
- hProcess=OpenProcess(PROCESS_QUERY_INFORMATION| PROCESS_VM_READ,FALSE,dwId);
- if(!hProcess)
- {
- return FALSE;
- }
-
- //查询进程的基本信息,获取PEB
- status=NtQueryInformationProcess(hProcess,0,(PVOID)&pbi,sizeof(PROCESS_BASIC_INFORMATION),NULL);
- if(status)
- {
- goto EndGet;
- }
- //读取进程的PEB指针
- if(!ReadProcessMemory(hProcess,pbi.PebBaseAddress,&Peb,sizeof(PEB),&dwDummy))
- {
- goto EndGet;
- }
- //获取目标进程空间存储的命令行参数字符串的指针
- if(!ReadProcessMemory(hProcess,Peb.ProcessParameters,&ProcParam,sizeof(PROCESS_PARAMETERS),&dwDummy))
- {
- goto EndGet;
- }
- IpAddress=ProcParam.CommandLine.Buffer;
- dwSize=ProcParam.CommandLine.Length;
- if(dwBufLen<dwSize)
- {
- goto EndGet;
- }
- //读取目标进程的命令行参数到本进程的缓冲区
- if(!ReadProcessMemory(hProcess,IpAddress,wBuf,dwSize,&dwDummy))
- {
- goto EndGet;
- }
- bRet=TRUE;
-
- EndGet:
- //关闭目标进程的句柄
- CloseHandle(hProcess);
- return bRet;
- }
- //提升本进程权限
- void EnableDebugPriv(void)
- {
- HANDLE hToken;
- LUID sedebugnameValue;
- TOKEN_PRIVILEGES tkp;
-
- //打开本进程,获得调整权限的权限
- if(!OpenProcessToken(GetCurrentProcess(),TOKEN_ADJUST_PRIVILEGES|TOKEN_QUERY,&hToken))
- {
- return;
- }
- //查询EBUG权限的值
- if(!LookupPrivilegeValue(NULL,SE_DEBUG_NAME,&sedebugnameValue))
- {
- CloseHandle(hToken);
- return;
- }
- tkp.PrivilegeCount=1;
- tkp.Privileges[0].Luid=sedebugnameValue;
- tkp.Privileges[0].Attributes=SE_PRIVILEGE_ENABLED;
- //调整本进程的权限,使之具有可以高度其它进程的权限
- AdjustTokenPrivileges(hToken,FALSE,&tkp,sizeof tkp,NULL,NULL);
- //关闭本进程句柄
- CloseHandle(hToken);
- }
- #include "stdafx.h"
最后
以上就是美好唇彩为你收集整理的获取所有进程的映像路径以及命令VC源代码的全部内容,希望文章能够帮你解决获取所有进程的映像路径以及命令VC源代码所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复