博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
HOWTO: Get the command line of a process(转)
阅读量:6358 次
发布时间:2019-06-23

本文共 7821 字,大约阅读时间需要 26 分钟。

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:. 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, 0, &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 :

 

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 
#include
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, 0, &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 < 2) { printf("Usage: getprocesscommandline [pid]\n"); return 1; } pid = _wtoi(argv[1]); if ((processHandle = OpenProcess( PROCESS_QUERY_INFORMATION | /* required for NtQueryInformationProcess */ PROCESS_VM_READ, /* required for ReadProcessMemory */ FALSE, pid)) == 0) { 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 / 2, commandLineContents); CloseHandle(processHandle); free(commandLineContents); return 0;}

 

转载地址:http://wpfma.baihongyu.com/

你可能感兴趣的文章
OTP 22.0 RC3 发布,Erlang 编写的应用服务器
查看>>
D语言/DLang 2.085.1 发布,修复性迭代
查看>>
感觉JVM的默认异常处理不够好,既然不好那我们就自己来处理异常呗!那么如何自己处理异常呢?...
查看>>
Java 基础 之 算数运算符
查看>>
Windows下配置安装Git(二)
查看>>
一个最简单的基于Android SearchView的搜索框
查看>>
铁路开通WiFi“钱景”不明
查看>>
Facebook申请专利 或让好友及陌生人相互拼车
查看>>
电力“十三五”规划:地面光伏与分布式的分水岭
查看>>
美联社再告FBI:要求公开请黑客解锁iPhone花费
查看>>
三星电子出售希捷和夏普等四家公司股份
查看>>
任志远:当云计算遇上混合云
查看>>
思科联手发那科 用物联网技术打造无人工厂
查看>>
智慧城市首要在政府利用大数据的智慧
查看>>
2015年物联网行业:巨头展开专利大战
查看>>
以自动化测试撬动遗留系统
查看>>
网络安全初创公司存活之道
查看>>
《图解CSS3:核心技术与案例实战》——1.2节浏览器对CSS3的支持状况
查看>>
《Android应用开发》——2.4节应用类
查看>>
继 One Step 后,锤子科技 Big Bang 正式开源
查看>>