HOWTO: Get the command line of a process(转)
How would you get the command line of a process? Some people have suggested that you use remote thread injection, call GetCommandLine(), then IPC the result back. This might work most of the time on Windows XP, but on Windows Vista it doesn’t work on system and service processes. This is because CreateRemoteThread only works on processes in the same session ID as the caller – in Windows Vista, services and other system processes run in session 0 while user programs run in higher sessions. The best and safest way is to read a structure present in every Windows process.
The Process Environment Block (PEB) is usually stored in the high regions of process memory, above 0x7ff00000. These regions also contain Thread Environment Blocks (TEBs). The PEB address is different for almost every process, so you can’t simply use a hardcoded constant. There’s only one way (in user mode) to get the PEB address:NtQueryInformationProcess. Its (simplified) function definition is:
NtQueryInformationProcess(
IN HANDLE ProcessHandle,
IN PROCESS_INFORMATION_CLASS ProcessInformationClass,
OUT PVOID ProcessInformation,
IN ULONG ProcessInformationLength,
OUT PULONG ReturnLength
);
The ProcessInformationClass we want to use is the first one, ProcessBasicInformation (with a value of 0). The structure for this is named PROCESS_BASIC_INFORMATION:
typedef struct _PROCESS_BASIC_INFORMATION
{
NTSTATUS ExitStatus;
PVOID PebBaseAddress; /* contains the PEB address! */
ULONG_PTR AffinityMask;
DWORD BasePriority;
HANDLE UniqueProcessId;
HANDLE InheritedFromUniqueProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION;
The problem with calling NtQueryInformationProcess is that you’ll have to find the address of it yourself. Here’s some code that finds the PEB address of any process:
typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
HANDLE ProcessHandle,
DWORD ProcessInformationClass, /* can't be bothered defining the whole enum */
PVOID ProcessInformation,
DWORD ProcessInformationLength,
PDWORD ReturnLength
); typedef struct _PROCESS_BASIC_INFORMATION
{
...
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; PVOID GetPebAddress(int pid)
{
_NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)
GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
PROCESS_BASIC_INFORMATION pbi;
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid); NtQueryInformationProcess(processHandle, , &pbi, sizeof(pbi), NULL);
CloseHandle(processHandle); return pbi.PebBaseAddress;
}
Once you get the address of the PEB, you’ll have to read its contents. This can easily be done using ReadProcessMemory. Inside the PEB, there’s a pointer to a second structure,RTL_USER_PROCESS_PARAMETERS. Here’s some stuff from the the PEB struct definition:
typedef struct _PEB
{
/* +0x0 */ BOOLEAN InheritedAddressSpace; /* BOOLEANs are one byte each */
/* +0x1 */ BOOLEAN ReadImageFileExecOptions;
/* +0x2 */ BOOLEAN BeingDebugged;
/* +0x3 */ BOOLEAN Spare;
/* +0x4 */ HANDLE Mutant;
/* +0x8 */ PVOID ImageBaseAddress;
/* +0xc */ PPEB_LDR_DATA LoaderData;
/* +0x10 */ PRTL_USER_PROCESS_PARAMETERS ProcessParameters;
...
Those comments on the left hand side are offsets from the beginning of the PEB; if we want to get the address of ProcessParameters, we simply read 4 bytes from PEB address + 0x10. For example:
PVOID pebAddress = ...; /* get the PEB address */
PVOID rtlUserProcParamsAddress; ReadProcessMemory(processHandle, /* open the process first... */
(PCHAR)pebAddress + 0x10,
&rtlUserProcParamsAddress, /* we'll just read directly into our variable */
sizeof(PVOID),
NULL
);
So, now we have the address of ProcessParameters. Let’s look inside it:
typedef struct _RTL_USER_PROCESS_PARAMETERS
{
ULONG MaximumLength;
ULONG Length;
ULONG Flags;
ULONG DebugFlags;
PVOID ConsoleHandle;
ULONG ConsoleFlags;
HANDLE StdInputHandle;
HANDLE StdOutputHandle;
HANDLE StdErrorHandle;
/* +0x24 */ UNICODE_STRING CurrentDirectoryPath;
HANDLE CurrentDirectoryHandle;
/* +0x30 */ UNICODE_STRING DllPath;
/* +0x38 */ UNICODE_STRING ImagePathName;
/* +0x40 */ UNICODE_STRING CommandLine;
... /* more stuff you probably won't care about */
A UNICODE_STRING is simply a counted Unicode string:
typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;
It’s pretty obvious what you have to do from here on. You have to read the desired UNICODE_STRING structure and then read the contents of Buffer (Length is in bytes, not characters). (Now that you’ve seen the definition of RTL_USER_PROCESS_PARAMETERS, you’ll probably want other strings as well!) A complete sample program is below. Note that the code does not work on x64 due to the hard-coded offsets; you may want to include the structure definitions for the PEB and process parameters and use FIELD_OFFSET to get the correct offsets.
#include <windows.h>
#include <stdio.h> typedef NTSTATUS (NTAPI *_NtQueryInformationProcess)(
HANDLE ProcessHandle,
DWORD ProcessInformationClass,
PVOID ProcessInformation,
DWORD ProcessInformationLength,
PDWORD ReturnLength
); typedef struct _UNICODE_STRING
{
USHORT Length;
USHORT MaximumLength;
PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING; typedef struct _PROCESS_BASIC_INFORMATION
{
LONG ExitStatus;
PVOID PebBaseAddress;
ULONG_PTR AffinityMask;
LONG BasePriority;
ULONG_PTR UniqueProcessId;
ULONG_PTR ParentProcessId;
} PROCESS_BASIC_INFORMATION, *PPROCESS_BASIC_INFORMATION; PVOID GetPebAddress(HANDLE ProcessHandle)
{
_NtQueryInformationProcess NtQueryInformationProcess =
(_NtQueryInformationProcess)GetProcAddress(
GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
PROCESS_BASIC_INFORMATION pbi; NtQueryInformationProcess(ProcessHandle, , &pbi, sizeof(pbi), NULL); return pbi.PebBaseAddress;
} int wmain(int argc, WCHAR *argv[])
{
int pid;
HANDLE processHandle;
PVOID pebAddress;
PVOID rtlUserProcParamsAddress;
UNICODE_STRING commandLine;
WCHAR *commandLineContents; if (argc < )
{
printf("Usage: getprocesscommandline [pid]\n");
return ;
} pid = _wtoi(argv[]); if ((processHandle = OpenProcess(
PROCESS_QUERY_INFORMATION | /* required for NtQueryInformationProcess */
PROCESS_VM_READ, /* required for ReadProcessMemory */
FALSE, pid)) == )
{
printf("Could not open process!\n");
return GetLastError();
} pebAddress = GetPebAddress(processHandle); /* get the address of ProcessParameters */
if (!ReadProcessMemory(processHandle, (PCHAR)pebAddress + 0x10,
&rtlUserProcParamsAddress, sizeof(PVOID), NULL))
{
printf("Could not read the address of ProcessParameters!\n");
return GetLastError();
} /* read the CommandLine UNICODE_STRING structure */
if (!ReadProcessMemory(processHandle, (PCHAR)rtlUserProcParamsAddress + 0x40,
&commandLine, sizeof(commandLine), NULL))
{
printf("Could not read CommandLine!\n");
return GetLastError();
} /* allocate memory to hold the command line */
commandLineContents = (WCHAR *)malloc(commandLine.Length); /* read the command line */
if (!ReadProcessMemory(processHandle, commandLine.Buffer,
commandLineContents, commandLine.Length, NULL))
{
printf("Could not read the command line string!\n");
return GetLastError();
} /* print it */
/* the length specifier is in characters, but commandLine.Length is in bytes */
/* a WCHAR is 2 bytes */
printf("%.*S\n", commandLine.Length / , commandLineContents);
CloseHandle(processHandle);
free(commandLineContents); return ;
}
HOWTO: Get the command line of a process(转)的更多相关文章
- could not launch process: debugserver or lldb-server not found: install XCode's command line tools or lldb-server
0x00 事件 VS 调试 go 的时候,发生了这个错误,导致无法调试: could not launch process: debugserver or lldb-server not found: ...
- How to build .apk file from command line(转)
How to build .apk file from command line Created on Wednesday, 29 June 2011 14:32 If you don’t want ...
- ubuntu16.04安装virtualbox5.1失败 gcc:error:unrecognized command line option ‘-fstack-protector-strong’
系统:ubuntu16.04.1 软件:Virtualbox-5.1 编译器:GCC 4.7.4 在如上环境下安装Vbx5.1提示我在终端执行/sbin/vboxconfig命令 照做 出现如下err ...
- python click module for command line interface
Click Module(一) ----xiaojikuaipao The following mat ...
- atprogram.exe : Atmel Studio Command Line Interface
C:\Program Files\Atmel\Atmel Studio 6.1\atbackend\atprogram.exe No command specified.Atmel Studio Co ...
- 10 Interesting Linux Command Line Tricks and Tips Worth Knowing
I passionately enjoy working with commands as they offer more control over a Linux system than GUIs( ...
- Building Xcode iOS projects and creating *.ipa file from the command line
For our development process of iOS applications, we are using Jenkins set up on the Mac Mini Server, ...
- [笔记]The Linux command line
Notes on The Linux Command Line (by W. E. Shotts Jr.) edited by Gopher 感觉博客园是不是搞了什么CSS在里头--在博客园显示效果挺 ...
- Linux Command Line(II): Intermediate
Prerequisite: Linux Command Line(I): Beginner ================================ File I/O $ cat > a ...
随机推荐
- python网络编程-多进程multiprocessing
一:mutilprocess简介 多线程类似于同时执行多个不同程序,多线程运行有如下优点: 使用线程可以把占据长时间的程序中的任务放到后台去处理. 用户界面可以更加吸引人,这样比如用户点击了一个按钮去 ...
- Nginx - 压缩模块
1. 前言 在 Nginx 中与网页压缩相关的模块有两个:一个是 HttpGzipModule,另一个是 HttpGzipStaticModule.前者用于启用在文件传输过程中使用 gzip 压缩,而 ...
- 如何查看页面是否开启了gzip压缩
1.谷歌浏览器 F12 2.在表头单击鼠标右键 3.如果开启了gzip则显示gzip,没有则是空
- 添加自签发的 SSL 证书为受信任的根证书
原文:http://cnzhx.net/blog/self-signed-certificate-as-trusted-root-ca-in-windows/ 添加自签发的 SSL 证书为受信任的根证 ...
- thinkphp辅助方法,数据库操作
- java 多线程总结篇1之——基本概念
1.什么是线程 进程:每个进程都有独立的代码和数据空间(进程上下文),进程间的切换会有较大的开销,一个进程包含1--n个线程.(进程是资源分配的最小单位) 线程:同一类线程共享代码和数据空间,每个线程 ...
- Jdk 和 Tomcat的 安装。
1.再分发服务器上下载JDK,然后利用xftp上传到聚石塔等 2. 解压: tar -zxvf jdk-8u121-linux-x64.tar.gz 3.配置环境变量: export JAVA_HOM ...
- Java 容器的基本概念
java容器类类库的用途时"保存对象",并将其划分为两个不同的概念: 1)Collection(采集).一个独立元素的序列,这些元素都服从一条或多条规则,List必须按照插入的顺序 ...
- kafka基本版与kafka acl版性能对比(单机版)
一.场景 线上已经有kafka集群,服务运行稳定.但是因为产品升级,需要对kakfa做安全测试,也就是权限验证. 但是增加权限验证,会不会对性能有影响呢?影响大吗?不知道呀! 因此,本文就此来做一下对 ...
- Oracle学习笔记:实现select top N的方法
由于Oracle不支持select top N语句,所以在Oracle中需要利用order by和rownum的组合来实现select top N的查询. rownum是记录表中数据编号的一个隐藏字段 ...