private static Dictionary <string, string> GetEnvironmentVariablesCore(IntPtr hProcess) { IntPtr penv = GetPenv(hProcess); int dataSize; if (!HasReadAccess(hProcess, penv, out dataSize)) { throw new Win32Exception("Unable to read environment block."); } // Limit env size to 10 MB to be defensive const int maxEnvSize = 10 * 1000 * 1000; if (dataSize > maxEnvSize) { dataSize = maxEnvSize; } var envData = new byte[dataSize]; var res_len = IntPtr.Zero; bool b = ProcessNativeMethods.ReadProcessMemory( hProcess, penv, envData, new IntPtr(dataSize), ref res_len); if (!b || (int)res_len != dataSize) { throw new Win32Exception("Unable to read environment block data."); } return(EnvToDictionary(envData)); }
private static string GetCommandLineCore(IntPtr hProcess) { int targetProcessBitness = GetProcessBitness(hProcess); if (targetProcessBitness == 64 && !System.Environment.Is64BitProcess) { throw new Win32Exception( "The current process should run in 64 bit mode to be able to get the environment of another 64 bit process."); } var pPeb = targetProcessBitness == 64 ? GetPeb64(hProcess) : GetPeb32(hProcess); //dt -r ntdll!PEB for offset values of the PEB var offset = targetProcessBitness == 64 ? 0x20 : 0x10; var unicodeStringOffset = targetProcessBitness == 64 ? 0x70 : 0x40; IntPtr ptr; if (!TryReadIntPtr(hProcess, pPeb + offset, out ptr)) { throw new Win32Exception("Unable to read PEB."); } int commandLineLength; IntPtr commandLineBuffer; if ((targetProcessBitness == 64 && System.Environment.Is64BitProcess) || (targetProcessBitness == 32 && !System.Environment.Is64BitProcess)) { //we running same bitness as the target process, use native UNICODE_STRING var unicodeString = new ProcessNativeMethods.UNICODE_STRING(); if (!ProcessNativeMethods.ReadProcessMemory(hProcess, ptr + unicodeStringOffset, ref unicodeString, new IntPtr(Marshal.SizeOf(unicodeString)), IntPtr.Zero)) { throw new Win32Exception(String.Format("Unable to read command line, win32 error {0}", Marshal.GetLastWin32Error())); } commandLineLength = unicodeString.Length; commandLineBuffer = unicodeString.Buffer; } else { //we are running 64 but target process is 32, use UNICODE_STRING_32 var unicodeString = new ProcessNativeMethods.UNICODE_STRING_32(); if (!ProcessNativeMethods.ReadProcessMemory(hProcess, ptr + unicodeStringOffset, ref unicodeString, new IntPtr(Marshal.SizeOf(unicodeString)), IntPtr.Zero)) { throw new Win32Exception(String.Format("Unable to read command line, win32 error {0}", Marshal.GetLastWin32Error())); } commandLineLength = unicodeString.Length; commandLineBuffer = new IntPtr(unicodeString.Buffer); } var bytes = new byte[commandLineLength]; if (!ProcessNativeMethods.ReadProcessMemory(hProcess, commandLineBuffer, bytes, new IntPtr(commandLineLength), IntPtr.Zero)) { throw new Win32Exception(String.Format("Unable to read command line, win32 error {0}", Marshal.GetLastWin32Error())); } return(Encoding.Unicode.GetString(bytes)); }
// should just be ReadIntPtr not TryReadIntPtr, throw when failed private static bool TryReadIntPtr(IntPtr hProcess, IntPtr ptr, out IntPtr readPtr) { var dataSize = new IntPtr(IntPtr.Size); var res_len = IntPtr.Zero; if (!ProcessNativeMethods.ReadProcessMemory( hProcess, ptr, out readPtr, dataSize, ref res_len)) { // automatically GetLastError() and format message throw new Win32Exception(); } // This is more like an assert return(res_len == dataSize); }