1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173
|
#include "ProcessHelper.h"
PPEB ProcessHelper::GetPebAddress(HANDLE ProcessHandle){
_NtQueryInformationProcess NtQueryInformationProcess = (_NtQueryInformationProcess)GetProcAddress(GetModuleHandleA("ntdll.dll"), "NtQueryInformationProcess");
PROCESS_BASIC_INFORMATION pbi = { 0 };
NtQueryInformationProcess(ProcessHandle, 0, &pbi, sizeof(pbi), NULL);
return pbi.PebBaseAddress;
}
// Source: https://www.vergiliusproject.com/kernels/x64/Windows%20XP%20%7C%202003/SP2/_RTL_DRIVE_LETTER_CURDIR
//0x18 bytes (sizeof)
struct MY_RTL_DRIVE_LETTER_CURDIR
{
USHORT Flags; //0x0
USHORT Length; //0x2
ULONG TimeStamp; //0x4
struct _STRING DosPath; //0x8
};
// Source: https://www.vergiliusproject.com/kernels/x64/Windows%20XP%20%7C%202003/SP2/_CURDIR
//0x18 bytes (sizeof)
struct MY_CURDIR
{
struct _UNICODE_STRING DosPath; //0x0
VOID* Handle; //0x10
};
bool ProcessHelper::GetProcessCommandLine(DWORD dwProcId, LPWSTR& szCmdLine){
szCmdLine = NULL;
HANDLE processHandle = OpenProcess(PROCESS_QUERY_INFORMATION | /* required for NtQueryInformationProcess */
PROCESS_VM_READ, /* required for ReadProcessMemory */
FALSE, dwProcId);
if (!processHandle){ return false; }
PVOID pebAddress = GetPebAddress(processHandle);
PVOID rtlUserProcParamsAddress;
if (!ReadProcessMemory(processHandle, &(((_PEB*)pebAddress)->ProcessParameters), &rtlUserProcParamsAddress, sizeof(PVOID), NULL)){
CloseHandle(processHandle);
return false;
}
UNICODE_STRING commandLine;
if (!ReadProcessMemory(processHandle, &(((_RTL_USER_PROCESS_PARAMETERS*)rtlUserProcParamsAddress)->CommandLine), &commandLine, sizeof(commandLine), NULL)){
CloseHandle(processHandle);
return false;
}
szCmdLine = new WCHAR[commandLine.MaximumLength];
memset(szCmdLine, 0, commandLine.MaximumLength);
if (!ReadProcessMemory(processHandle, commandLine.Buffer, szCmdLine, commandLine.Length, NULL)){
delete[] szCmdLine;
CloseHandle(processHandle);
return false;
}
CloseHandle(processHandle);
return true;
}
// Source: https://www.vergiliusproject.com/kernels/x64/Windows%20XP%20%7C%202003/SP2/_RTL_USER_PROCESS_PARAMETERS
//0x3f0 bytes (sizeof)
struct MY_RTL_USER_PROCESS_PARAMETERS
{
ULONG MaximumLength; //0x0
ULONG Length; //0x4
ULONG Flags; //0x8
ULONG DebugFlags; //0xc
VOID* ConsoleHandle; //0x10
ULONG ConsoleFlags; //0x18
VOID* StandardInput; //0x20
VOID* StandardOutput; //0x28
VOID* StandardError; //0x30
struct MY_CURDIR CurrentDirectory; //0x38
struct _UNICODE_STRING DllPath; //0x50
struct _UNICODE_STRING ImagePathName; //0x60
struct _UNICODE_STRING CommandLine; //0x70
VOID* Environment; //0x80
ULONG StartingX; //0x88
ULONG StartingY; //0x8c
ULONG CountX; //0x90
ULONG CountY; //0x94
ULONG CountCharsX; //0x98
ULONG CountCharsY; //0x9c
ULONG FillAttribute; //0xa0
ULONG WindowFlags; //0xa4
ULONG ShowWindowFlags; //0xa8
struct _UNICODE_STRING WindowTitle; //0xb0
struct _UNICODE_STRING DesktopInfo; //0xc0
struct _UNICODE_STRING ShellInfo; //0xd0
struct _UNICODE_STRING RuntimeData; //0xe0
struct MY_RTL_DRIVE_LETTER_CURDIR CurrentDirectores[32]; //0xf0
};
int ProcessHelper::GetProcessParameter(DWORD dwProcId, LPWSTR& szParameter, ProcessParameter parameter) {
szParameter = nullptr;
auto rc = 0;
auto hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcId);
if (hProcess) {
auto pPEBAddress = GetPebAddress(hProcess);
if (pPEBAddress) {
MY_RTL_USER_PROCESS_PARAMETERS* pRtlUserProcParamsAddress;
SIZE_T nSizeRead = 0;
SIZE_T dummy = 0;
if (ReadProcessMemory(hProcess, &(pPEBAddress->ProcessParameters),
&pRtlUserProcParamsAddress, sizeof(pRtlUserProcParamsAddress), &nSizeRead) &&
(nSizeRead == sizeof(pRtlUserProcParamsAddress))) {
auto paramPtr = [parameter, pRtlUserProcParamsAddress]() -> PUNICODE_STRING
{
switch (parameter)
{
return &pRtlUserProcParamsAddress->CommandLine;
case ProcessParameter::WorkingDirectory:
return &pRtlUserProcParamsAddress->CurrentDirectory.DosPath;
default:
return nullptr;
}
}();
UNICODE_STRING paramStr;
if (ReadProcessMemory(hProcess, paramPtr,
¶mStr, sizeof(paramStr), &nSizeRead) && (nSizeRead == sizeof(paramStr))) {
szParameter = new WCHAR[paramStr.MaximumLength];
if (szParameter) {
memset(szParameter, 0, paramStr.MaximumLength);
if (ReadProcessMemory(hProcess, paramStr.Buffer,
szParameter, paramStr.Length, &nSizeRead) && (nSizeRead == paramStr.Length)) {
rc = 0;
}
else {
// couldn't read parameter string
delete[] szParameter;
szParameter = nullptr;
rc = -6;
}
}
else {
// couldn't allocate memory
rc = -5;
}
}
else {
// couldn't read parameter
rc = -4;
}
}
else {
// couldn't read process memory
rc = -3;
}
}
else {
// couldn't get PEB address
rc = -2;
}
CloseHandle(hProcess);
}
else {
// couldn't open process
rc = -1;
}
return rc;
}
|