获取所有进程的映像路径以及命令VC源代码
来源:互联网 发布:时时彩开奖视频源码 编辑:程序博客网 时间:2024/05/16 08:00
- 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:\n\t%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 %s\n",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"
0 0
- 获取所有进程的映像路径以及命令VC源代码
- 获取所有进程的映像路径以及命令行参数
- 获取所有进程的映像路径以及命令行参数
- VC获取进程的所有线程
- 如何获取某个进程的主窗口以及创建进程的程序名(进程映像名)
- 获取当前所有进程的完整路径
- (lazarus)显示所有进程的映像名称
- 【VB.NET2010】遍历进程,获取进程映像路径
- 获取本机所有进程的完整路径
- 关于hadoop循环获取路径以及获得分片的源代码
- 获取指定路径下的所有文件名以及读取配置文件
- C/C++win32获取所有进程路径
- Java获取当前进程ID以及所有Java进程的进程ID
- Windows 下 根据进程名获取进程ID 以及该进程下所有窗口的句柄
- 进程的映像
- [Linux] ls和size命令以及程序内存映像、磁盘映像的理解
- [Linux] ls和size命令以及程序内存映像、磁盘映像的理解
- ls和size命令以及程序内存映像、磁盘映像的理解
- fsockopen 模拟 post get 请求
- 求最大值
- linux u-boot 文件配置和编译笔记
- 如何指定国内主流浏览器以何种模式打开网页
- The Fast Pimpl Idiom
- 获取所有进程的映像路径以及命令VC源代码
- 保留DDR内存作为外设访问
- thinkphp 生成缓存 方法
- Ubuntu 12.04 安装 Java 环境
- opwenWrt移植Helloworld测试
- 二分练习
- jquery 学习日记3-几个容易弄混的事件
- android设置默认输入法
- Axis,axis2,Xfire以及cxf对比