static extern int NtQueryInformationProcess32(IntPtr ProcessHandle, int ProcessInformationClass, [In] ref PROCESS_BASIC_INFORMATION32 ProcessInformation, int ProcessInformationLength, out int ReturnLength);
static string TryGetCommandLineCore(IntPtr hProcess) { int ptrSize = IntPtr.Size; ushort cmdlineLength; IntPtr cmdlineBuffer; bool b; if (ptrSize == 4) { PROCESS_BASIC_INFORMATION32 pbi = default; int hr = NtQueryInformationProcess32(hProcess, ProcessBasicInformation, ref pbi, PROCESS_BASIC_INFORMATION32.SIZE, out int returnLength); if (hr != 0 || pbi.PebBaseAddress == 0) { return(null); } IntPtr userProcessParamsAddr; b = ReadProcessMemory(hProcess, (byte *)pbi.PebBaseAddress + ProcessParametersOffset32, &userProcessParamsAddr, new IntPtr(ptrSize), out var bytesRead); if (!b || bytesRead.ToInt64() != ptrSize) { return(null); } UNICODE_STRING32 unicodeString; b = ReadProcessMemory(hProcess, (byte *)userProcessParamsAddr + CommandLineOffset32, &unicodeString, new IntPtr(UNICODE_STRING32.SIZE), out bytesRead); if (!b || bytesRead.ToInt64() != UNICODE_STRING32.SIZE) { return(null); } cmdlineLength = unicodeString.Length; cmdlineBuffer = IntPtr.Size == 4 ? new IntPtr((int)unicodeString.Buffer) : new IntPtr(unicodeString.Buffer); } else { PROCESS_BASIC_INFORMATION64 pbi = default; int hr = NtQueryInformationProcess64(hProcess, ProcessBasicInformation, ref pbi, PROCESS_BASIC_INFORMATION64.SIZE, out int returnLength); if (hr != 0 || pbi.PebBaseAddress == 0) { return(null); } IntPtr userProcessParamsAddr; b = ReadProcessMemory(hProcess, (byte *)pbi.PebBaseAddress + ProcessParametersOffset64, &userProcessParamsAddr, new IntPtr(ptrSize), out var bytesRead); if (!b || bytesRead.ToInt64() != ptrSize) { return(null); } UNICODE_STRING64 unicodeString; b = ReadProcessMemory(hProcess, (byte *)userProcessParamsAddr + CommandLineOffset64, &unicodeString, new IntPtr(UNICODE_STRING64.SIZE), out bytesRead); if (!b || bytesRead.ToInt64() != UNICODE_STRING64.SIZE) { return(null); } cmdlineLength = unicodeString.Length; cmdlineBuffer = new IntPtr((long)unicodeString.Buffer); } if (cmdlineLength <= 0 || cmdlineBuffer == IntPtr.Zero) { return(string.Empty); } cmdlineLength &= 0xFFFE; var cmdLineChars = new char[cmdlineLength / 2]; fixed(void *p = cmdLineChars) { b = ReadProcessMemory(hProcess, cmdlineBuffer.ToPointer(), p, new IntPtr(cmdlineLength), out var bytesRead); if (!b || bytesRead.ToInt64() != cmdlineLength) { return(null); } } return(new string(cmdLineChars)); }
internal static extern int NtQueryInformationProcess( IntPtr ProcessHandle, PROCESSINFOCLASS ProcessInformationClass, out PROCESS_BASIC_INFORMATION32 ProcessInformation, int ProcessInformationLength, IntPtr ReturnLength = default);
private static extern int NtQueryInformationProcess32(IntPtr processHandle, PROCESSINFOCLASS processInformationClass, ref PROCESS_BASIC_INFORMATION32 processInformation, int processInformationLength, ref int returnLength);
// Reference: https://blogs.msdn.microsoft.com/matt_pietrek/2004/08/25/reading-another-processs-environment/ // Reference: http://blog.gapotchenko.com/eazfuscator.net/reading-environment-variables public static string GetEnvironmentVariable(Process process, IHostContext hostContext, string variable) { var trace = hostContext.GetTrace(nameof(WindowsEnvVarHelper)); Dictionary <string, string> environmentVariables = new Dictionary <string, string>(StringComparer.OrdinalIgnoreCase); IntPtr processHandle = process.SafeHandle.DangerousGetHandle(); IntPtr environmentBlockAddress; if (Environment.Is64BitOperatingSystem) { PROCESS_BASIC_INFORMATION64 pbi = new PROCESS_BASIC_INFORMATION64(); int returnLength = 0; int status = NtQueryInformationProcess64(processHandle, PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), ref returnLength); if (status != 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } bool wow64; if (!IsWow64Process(processHandle, out wow64)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!wow64) { // 64 bits process on 64 bits OS IntPtr UserProcessParameterAddress = ReadIntPtr64(processHandle, new IntPtr(pbi.PebBaseAddress) + 0x20); environmentBlockAddress = ReadIntPtr64(processHandle, UserProcessParameterAddress + 0x80); } else { // 32 bits process on 64 bits OS IntPtr UserProcessParameterAddress = ReadIntPtr32(processHandle, new IntPtr(pbi.PebBaseAddress) + 0x1010); environmentBlockAddress = ReadIntPtr32(processHandle, UserProcessParameterAddress + 0x48); } } else { PROCESS_BASIC_INFORMATION32 pbi = new PROCESS_BASIC_INFORMATION32(); int returnLength = 0; int status = NtQueryInformationProcess32(processHandle, PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), ref returnLength); if (status != 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // 32 bits process on 32 bits OS IntPtr UserProcessParameterAddress = ReadIntPtr32(processHandle, new IntPtr(pbi.PebBaseAddress) + 0x10); environmentBlockAddress = ReadIntPtr32(processHandle, UserProcessParameterAddress + 0x48); } MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION(); if (VirtualQueryEx(processHandle, environmentBlockAddress, ref memInfo, Marshal.SizeOf(memInfo)) == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } Int64 dataSize = memInfo.RegionSize.ToInt64() - (environmentBlockAddress.ToInt64() - memInfo.BaseAddress.ToInt64()); byte[] envData = new byte[dataSize]; IntPtr res_len = IntPtr.Zero; if (!ReadProcessMemory(processHandle, environmentBlockAddress, envData, new IntPtr(dataSize), ref res_len)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (res_len.ToInt64() != dataSize) { throw new ArgumentOutOfRangeException(nameof(ReadProcessMemory)); } string environmentVariableString; Int64 environmentVariableBytesLength = 0; // check env encoding if (envData[0] != 0 && envData[1] == 0) { // Unicode for (Int64 index = 0; index < dataSize; index++) { // Unicode encoded environment variables block ends up with '\0\0\0\0'. if (environmentVariableBytesLength == 0 && envData[index] == 0 && index + 3 < dataSize && envData[index + 1] == 0 && envData[index + 2] == 0 && envData[index + 3] == 0) { environmentVariableBytesLength = index + 3; } else if (environmentVariableBytesLength != 0) { // set it '\0' so we can easily trim it, most array method doesn't take int64 envData[index] = 0; } } if (environmentVariableBytesLength == 0) { throw new ArgumentException(nameof(environmentVariableBytesLength)); } environmentVariableString = Encoding.Unicode.GetString(envData); } else if (envData[0] != 0 && envData[1] != 0) { // ANSI for (Int64 index = 0; index < dataSize; index++) { // Unicode encoded environment variables block ends up with '\0\0'. if (environmentVariableBytesLength == 0 && envData[index] == 0 && index + 1 < dataSize && envData[index + 1] == 0) { environmentVariableBytesLength = index + 1; } else if (environmentVariableBytesLength != 0) { // set it '\0' so we can easily trim it, most array method doesn't take int64 envData[index] = 0; } } if (environmentVariableBytesLength == 0) { throw new ArgumentException(nameof(environmentVariableBytesLength)); } environmentVariableString = Encoding.Default.GetString(envData); } else { throw new ArgumentException(nameof(envData)); } foreach (var envString in environmentVariableString.Split("\0", StringSplitOptions.RemoveEmptyEntries)) { string[] env = envString.Split("=", 2); if (!string.IsNullOrEmpty(env[0])) { environmentVariables[env[0]] = env[1]; trace.Verbose($"PID:{process.Id} ({env[0]}={env[1]})"); } } if (environmentVariables.TryGetValue(variable, out string envVariable)) { return(envVariable); } else { return(null); } }
// Reference: https://blogs.msdn.microsoft.com/matt_pietrek/2004/08/25/reading-another-processs-environment/ // Reference: http://blog.gapotchenko.com/eazfuscator.net/reading-environment-variables public static string GetEnvironmentVariable(Process process, IHostContext hostContext, string variable) { ArgUtil.NotNull(hostContext, nameof(hostContext)); ArgUtil.NotNull(process, nameof(process)); var trace = hostContext.GetTrace(nameof(WindowsEnvVarHelper)); IntPtr processHandle = process.SafeHandle.DangerousGetHandle(); IntPtr environmentBlockAddress; if (Environment.Is64BitProcess) { PROCESS_BASIC_INFORMATION64 pbi = new PROCESS_BASIC_INFORMATION64(); int returnLength = 0; int status = NtQueryInformationProcess64(processHandle, PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), ref returnLength); if (status != 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } bool wow64; if (!IsWow64Process(processHandle, out wow64)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (!wow64) { // 64 bits process on 64 bits OS IntPtr UserProcessParameterAddress = ReadIntPtr64(processHandle, new IntPtr(pbi.PebBaseAddress) + 0x20); environmentBlockAddress = ReadIntPtr64(processHandle, UserProcessParameterAddress + 0x80); } else { // 32 bits process on 64 bits OS IntPtr UserProcessParameterAddress = ReadIntPtr32(processHandle, new IntPtr(pbi.PebBaseAddress) + 0x1010); environmentBlockAddress = ReadIntPtr32(processHandle, UserProcessParameterAddress + 0x48); } } else { PROCESS_BASIC_INFORMATION32 pbi = new PROCESS_BASIC_INFORMATION32(); int returnLength = 0; int status = NtQueryInformationProcess32(processHandle, PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), ref returnLength); if (status != 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } // 32 bits process on 32 bits OS IntPtr UserProcessParameterAddress = ReadIntPtr32(processHandle, new IntPtr(pbi.PebBaseAddress) + 0x10); environmentBlockAddress = ReadIntPtr32(processHandle, UserProcessParameterAddress + 0x48); } MEMORY_BASIC_INFORMATION memInfo = new MEMORY_BASIC_INFORMATION(); if (VirtualQueryEx(processHandle, environmentBlockAddress, ref memInfo, Marshal.SizeOf(memInfo)) == 0) { throw new Win32Exception(Marshal.GetLastWin32Error()); } Int64 dataSize = memInfo.RegionSize.ToInt64() - (environmentBlockAddress.ToInt64() - memInfo.BaseAddress.ToInt64()); byte[] envData = new byte[dataSize]; IntPtr res_len = IntPtr.Zero; if (!ReadProcessMemory(processHandle, environmentBlockAddress, envData, new IntPtr(dataSize), ref res_len)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (res_len.ToInt64() != dataSize) { throw new ArgumentOutOfRangeException(nameof(ReadProcessMemory)); } var environmentVariables = _EnvToDictionary(envData); if (environmentVariables.TryGetValue(variable, out string envVariable)) { return(envVariable); } else { return(null); } }