//public static string GetCommandLine(int processId) //{ // return null;// GetProcessParametersString(processId, Is64BitOperatingSystem ? 0x70 : 0x40); //} //public static string GetCommandLine(this Process process) //{ // if (process == null) // throw new ArgumentNullException("process"); // return GetCommandLine(process.Id); //} #endregion private static string GetProcessParametersString(int processId, PEB_OFFSET Offset) { IntPtr handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId); if (handle == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error()); } bool IsWow64Process = Is64BitChecker.InternalCheckIsWow64(); bool IsTargetWow64Process = Is64BitChecker.GetProcessIsWow64(handle); bool IsTarget64BitProcess = Is64BitOperatingSystem && !IsTargetWow64Process; long offset = 0; long processParametersOffset = IsTarget64BitProcess ? 0x20 : 0x10; switch (Offset) { case PEB_OFFSET.CurrentDirectory: offset = IsTarget64BitProcess ? 0x38 : 0x24; break; case PEB_OFFSET.CommandLine: default: return(null); } try { long pebAddress = 0; if (IsTargetWow64Process) // OS : 64Bit, Cur : 32 or 64, Tar: 32bit { IntPtr peb32 = new IntPtr(); int hr = NtQueryInformationProcess(handle, (int)PROCESSINFOCLASS.ProcessWow64Information, ref peb32, IntPtr.Size, IntPtr.Zero); if (hr != 0) { throw new Win32Exception(hr); } pebAddress = peb32.ToInt64(); IntPtr pp = new IntPtr(); if (!ReadProcessMemory(handle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } UNICODE_STRING_32 us = new UNICODE_STRING_32(); if (!ReadProcessMemory(handle, new IntPtr(pp.ToInt64() + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if ((us.Buffer == 0) || (us.Length == 0)) { return(null); } string s = new string('\0', us.Length / 2); if (!ReadProcessMemory(handle, new IntPtr(us.Buffer), s, new IntPtr(us.Length), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(s); } else if (IsWow64Process)//Os : 64Bit, Cur 32, Tar 64 { PROCESS_BASIC_INFORMATION_WOW64 pbi = new PROCESS_BASIC_INFORMATION_WOW64(); int hr = NtWow64QueryInformationProcess64(handle, (int)PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); if (hr != 0) { throw new Win32Exception(hr); } pebAddress = pbi.PebBaseAddress; long pp = 0; hr = NtWow64ReadVirtualMemory64(handle, pebAddress + processParametersOffset, ref pp, Marshal.SizeOf(pp), IntPtr.Zero); if (hr != 0) { throw new Win32Exception(hr); } UNICODE_STRING_WOW64 us = new UNICODE_STRING_WOW64(); hr = NtWow64ReadVirtualMemory64(handle, pp + offset, ref us, Marshal.SizeOf(us), IntPtr.Zero); if (hr != 0) { throw new Win32Exception(hr); } if ((us.Buffer == 0) || (us.Length == 0)) { return(null); } string s = new string('\0', us.Length / 2); hr = NtWow64ReadVirtualMemory64(handle, us.Buffer, s, us.Length, IntPtr.Zero); if (hr != 0) { throw new Win32Exception(hr); } return(s); } else// Os,Cur,Tar : 64 or 32 { PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION(); int hr = NtQueryInformationProcess(handle, (int)PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); if (hr != 0) { throw new Win32Exception(hr); } pebAddress = pbi.PebBaseAddress.ToInt64(); IntPtr pp = new IntPtr(); if (!ReadProcessMemory(handle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } UNICODE_STRING us = new UNICODE_STRING(); if (!ReadProcessMemory(handle, new IntPtr((long)pp + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if ((us.Buffer == IntPtr.Zero) || (us.Length == 0)) { return(null); } string s = new string('\0', us.Length / 2); if (!ReadProcessMemory(handle, us.Buffer, s, new IntPtr(us.Length), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(s); } } finally { CloseHandle(handle); } }
private static extern bool ReadProcessMemory(IntPtr hProcess, IntPtr lpBaseAddress, ref UNICODE_STRING_32 lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead);
public static extern bool ReadProcessMemory( IntPtr hProcess, IntPtr lpBaseAddress, ref UNICODE_STRING_32 lpBuffer, IntPtr dwSize, IntPtr lpNumberOfBytesRead);
private static string GetProcessParametersString(int processId, PebProcessParametersMember offsetType) { IntPtr handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId); if (handle == IntPtr.Zero) throw new Win32Exception(Marshal.GetLastWin32Error()); try { bool isTargetWow64Process = Is64BitChecker.IsWow64Process(handle); bool isTarget64BitProcess = Environment.Is64BitOperatingSystem && !isTargetWow64Process; long processParametersOffset = GetProcessParametersOffset(isTarget64BitProcess); long offset = GetProcessParametersMemberOffset(offsetType, isTarget64BitProcess); if (isTargetWow64Process) { IntPtr peb32 = new IntPtr(); int hr = NtQueryInformationProcess(handle, (int)PROCESSINFOCLASS.ProcessWow64Information, ref peb32, IntPtr.Size, IntPtr.Zero); if (hr != 0) throw new Win32Exception(hr); long pebAddress = peb32.ToInt64(); IntPtr pp = new IntPtr(); if (!ReadProcessMemory(handle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); UNICODE_STRING_32 us = new UNICODE_STRING_32(); if (!ReadProcessMemory(handle, new IntPtr(pp.ToInt64() + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); if ((us.Buffer == 0) || (us.Length == 0)) return null; string s = new string('\0', us.Length / 2); if (!ReadProcessMemory(handle, new IntPtr(us.Buffer), s, new IntPtr(us.Length), IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); return s; } else { PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION(); int hr = NtQueryInformationProcess(handle, (int)PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); if (hr != 0) throw new Win32Exception(hr); long pebAddress = pbi.PebBaseAddress.ToInt64(); IntPtr pp = new IntPtr(); if (!ReadProcessMemory(handle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); UNICODE_STRING us = new UNICODE_STRING(); if (!ReadProcessMemory(handle, new IntPtr((long)pp + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); if ((us.Buffer == IntPtr.Zero) || (us.Length == 0)) return null; string s = new string('\0', us.Length / 2); if (!ReadProcessMemory(handle, us.Buffer, s, new IntPtr(us.Length), IntPtr.Zero)) throw new Win32Exception(Marshal.GetLastWin32Error()); return s; } } finally { CloseHandle(handle); } }
private static string GetProcessParametersString(IntPtr processHandle, PebProcessParametersMember offsetType) { if (processHandle == IntPtr.Zero) { throw new Win32Exception(Marshal.GetLastWin32Error()); } try { bool isTargetWow64Process = NativeMethods.Is64BitChecker.IsWow64Process(processHandle); bool isTarget64BitProcess = Environment.Is64BitOperatingSystem && !isTargetWow64Process; long processParametersOffset = GetProcessParametersOffset(isTarget64BitProcess); long offset = GetProcessParametersMemberOffset(offsetType, isTarget64BitProcess); if (isTargetWow64Process) { IntPtr peb32 = new IntPtr(); int hr = NtQueryInformationProcess(processHandle, (int)PROCESSINFOCLASS.ProcessWow64Information, ref peb32, IntPtr.Size, IntPtr.Zero); if (hr != 0) { throw new Win32Exception(hr); } long pebAddress = peb32.ToInt64(); IntPtr pp = new IntPtr(); if (!ReadProcessMemory(processHandle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } UNICODE_STRING_32 us = new UNICODE_STRING_32(); if (!ReadProcessMemory(processHandle, new IntPtr(pp.ToInt64() + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (us.Buffer == 0 || us.Length == 0) { return(null); } string s = new string('\0', us.Length / 2); if (!ReadProcessMemory(processHandle, new IntPtr(us.Buffer), s, new IntPtr(us.Length), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(s); } else { PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION(); int hr = NtQueryInformationProcess(processHandle, (int)PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); if (hr != 0) { throw new Win32Exception(hr); } long pebAddress = pbi.PebBaseAddress.ToInt64(); IntPtr pp = new IntPtr(); if (!ReadProcessMemory(processHandle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } UNICODE_STRING us = new UNICODE_STRING(); if (!ReadProcessMemory(processHandle, new IntPtr((long)pp + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } if (us.Buffer == IntPtr.Zero || us.Length == 0) { return(null); } string s = new string('\0', us.Length / 2); if (!ReadProcessMemory(processHandle, us.Buffer, s, new IntPtr(us.Length), IntPtr.Zero)) { throw new Win32Exception(Marshal.GetLastWin32Error()); } return(s); } } catch (Win32Exception) { return(String.Empty); } }
private static string GetProcessParametersString(int processId, PEB_OFFSET Offset, RunningProcess pre) { IntPtr handle = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, false, processId); if (handle == IntPtr.Zero) { return(null); } ///////////////////// Get the username associated with the process /////////////////// string username = LookupAccountName.GetProcessUser(handle, pre); if (username != null) { pre.UserName = username; } ///////////////////////////////////////////////////////////////////////////////////// /////////////////// Get Working Set Counters /////////////////////////////////////// PROCESS_MEMORY_COUNTERS memoryCounters; memoryCounters.cb = (uint)Marshal.SizeOf(typeof(PROCESS_MEMORY_COUNTERS)); if (GetProcessMemoryInfo(handle, out memoryCounters, memoryCounters.cb)) { pre.WorkingSet = (int)memoryCounters.WorkingSetSize; //pre.workingsetstr = pre.workingset.ToString("#,##0") + " " + "Bytes"; } //////////////////////////////////////////////////////////////////////////////////// FILETIME lpCreationTime = new FILETIME(); FILETIME lpUserTime = new FILETIME(); FILETIME lpKernelTime = new FILETIME(); FILETIME lpExitTime = new FILETIME(); bool retval = GetProcessTimes(handle, out lpCreationTime, out lpExitTime, out lpKernelTime, out lpUserTime); if (retval == true) { string sc = ConvertTimeToString(lpCreationTime.DateTimeHigh, lpCreationTime.DateTimeLow, true); pre.StartTime = DateTime.Parse(sc); string kr = ConvertTimeToString(lpKernelTime.DateTimeHigh, lpKernelTime.DateTimeLow, false); pre.KernalTime = kr; string ut = ConvertTimeToString(lpUserTime.DateTimeHigh, lpUserTime.DateTimeLow, false); pre.UserTime = ut; } bool IsWow64Process = PlatformCheck.InternalCheckIsWow64(); bool IsTargetWow64Process = PlatformCheck.GetProcessIsWow64(handle); bool IsTarget64BitProcess = Is64BitOperatingSystem && !IsTargetWow64Process; pre.IsWow64 = IsTargetWow64Process; long offset = 0; long processParametersOffset = IsTarget64BitProcess ? 0x20 : 0x10; long offsetldr = 0x0c; switch (Offset) { case PEB_OFFSET.CurrentDirectory: offset = IsTarget64BitProcess ? 0x38 : 0x24; break; case PEB_OFFSET.CommandLine: offset = Is64BitOperatingSystem ? 0x70 : 0x40; if (offset == 0x70 && IsTargetWow64Process) { offset = 0x40; } break; default: return(null); } try { long pebAddress = 0; if (IsTargetWow64Process) // OS : 64Bit, Cur : 32 or 64, Tar: 32bit { IntPtr peb32 = new IntPtr(); int hr = NtQueryInformationProcess(handle, (int)PROCESSINFOCLASS.ProcessWow64Information, ref peb32, IntPtr.Size, IntPtr.Zero); if (hr != 0) { return(null); } pebAddress = peb32.ToInt64(); IntPtr pp = new IntPtr(); if (!ReadProcessMemory(handle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) { return(null); } UNICODE_STRING_32 us = new UNICODE_STRING_32(); if (!ReadProcessMemory(handle, new IntPtr(pp.ToInt64() + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) { return(null); } if ((us.Buffer == 0) || (us.Length == 0)) { return(null); } string s = new string('\0', us.Length / 2); if (!ReadProcessMemory(handle, new IntPtr(us.Buffer), s, new IntPtr(us.Length), IntPtr.Zero)) { return(null); } UNICODE_STRING_32 us2 = new UNICODE_STRING_32(); if (!ReadProcessMemory(handle, new IntPtr(pp.ToInt64() + offset - 8), ref us2, new IntPtr(Marshal.SizeOf(us2)), IntPtr.Zero)) { return(null); } if ((us2.Buffer == 0) || (us2.Length == 0)) { return(null); } string s2 = new string('\0', us2.Length / 2); if (!ReadProcessMemory(handle, new IntPtr(us2.Buffer), s2, new IntPtr(us2.Length), IntPtr.Zero)) { return(null); } pre.Arguments = s; pre.Path = s2; //////////// Read Loader //////// PEB_LDR_DATA ldr1 = new PEB_LDR_DATA(); IntPtr ldrp = StructToPtr(ldr1); if (!ReadProcessMemory(handle, new IntPtr(pebAddress + 0x0c), ref ldrp, new IntPtr(Marshal.SizeOf(ldr1)), IntPtr.Zero)) { return(null); } /// We have long ldraddress = ldrp.ToInt64(); IntPtr le1 = new IntPtr(ldraddress + 0x0c); if (!ReadProcessMemory(handle, new IntPtr(ldraddress + 0xc), ref le1, new IntPtr(Marshal.SizeOf(le1)), IntPtr.Zero)) { return(null); } while (le1 != null) { UNICODE_STRING_32 us3 = new UNICODE_STRING_32(); if (!ReadProcessMemory(handle, new IntPtr(le1.ToInt64() + 0x24), ref us3, new IntPtr(Marshal.SizeOf(us3)), IntPtr.Zero)) { return(null); } if ((us3.Buffer == 0) || (us3.Length == 0)) { return(null); } string s3 = new string('\0', us3.Length / 2); if (!ReadProcessMemory(handle, new IntPtr(us3.Buffer), s3, new IntPtr(us3.Length), IntPtr.Zero)) { return(null); } long nextlist = le1.ToInt64(); IntPtr nextlistp = new IntPtr(nextlist); if (!ReadProcessMemory(handle, nextlistp, ref le1, new IntPtr(Marshal.SizeOf(le1)), IntPtr.Zero)) { return(null); } LoadedModule pme = new LoadedModule(); pme.ModulePath = s3; pre.ListProcessModule.Add(pme); } return(s); } else if (IsWow64Process)//Os : 64Bit, Cur 32, Tar 64 { PROCESS_BASIC_INFORMATION_WOW64 pbi = new PROCESS_BASIC_INFORMATION_WOW64(); int hr = NtWow64QueryInformationProcess64(handle, (int)PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); if (hr != 0) { return(null); } pebAddress = pbi.PebBaseAddress; long pp = 0; hr = NtWow64ReadVirtualMemory64(handle, pebAddress + processParametersOffset, ref pp, Marshal.SizeOf(pp), IntPtr.Zero); if (hr != 0) { return(null); } UNICODE_STRING_WOW64 us = new UNICODE_STRING_WOW64(); hr = NtWow64ReadVirtualMemory64(handle, pp + offset, ref us, Marshal.SizeOf(us), IntPtr.Zero); if (hr != 0) { return(null); } if ((us.Buffer == 0) || (us.Length == 0)) { return(null); } string s = new string('\0', us.Length / 2); hr = NtWow64ReadVirtualMemory64(handle, us.Buffer, s, us.Length, IntPtr.Zero); if (hr != 0) { return(null); } if (pre != null) { pre.Arguments = s; } UNICODE_STRING_WOW64 us2 = new UNICODE_STRING_WOW64(); hr = NtWow64ReadVirtualMemory64(handle, pp + offset - Marshal.SizeOf(us2), ref us2, Marshal.SizeOf(us2), IntPtr.Zero); if (hr != 0) { return(null); } if ((us2.Buffer == 0) || (us2.Length == 0)) { return(null); } string s2 = new string('\0', us2.Length / 2); hr = NtWow64ReadVirtualMemory64(handle, us2.Buffer, s2, us2.Length, IntPtr.Zero); if (hr != 0) { return(null); } // Console.WriteLine("IM : " + s2); pre.Path = s2; /////////////////////For Testing if (s2 != null && ((s2.ToLower().Contains("taskmgr.exe") == false))) { //return s2; } //////////// Read Loader //////// long ldrp = 0; if (NtWow64ReadVirtualMemory64(handle, pebAddress + 0x18, ref ldrp, sizeof(long), IntPtr.Zero) != 0) { return(null); } /// We have long ldraddress = ldrp + 0x10; long le1 = 0; if (NtWow64ReadVirtualMemory64(handle, ldraddress, ref le1, sizeof(long), IntPtr.Zero) != 0) { return(null); } while (le1 != 0) { UNICODE_STRING_WOW64 us3 = new UNICODE_STRING_WOW64(); hr = NtWow64ReadVirtualMemory64(handle, le1 + 0x48, ref us3, Marshal.SizeOf(us3), IntPtr.Zero); if (hr != 0) { return(null); } if ((us3.Buffer == 0) || (us3.Length == 0)) { return(null); } string s3 = new string('\0', us3.Length / 2); hr = NtWow64ReadVirtualMemory64(handle, us3.Buffer, s3, us3.Length, IntPtr.Zero); if (hr != 0) { return(null); } long nextlist = le1; hr = NtWow64ReadVirtualMemory64(handle, nextlist, ref le1, sizeof(long), IntPtr.Zero); if (hr != 0) { return(null); } LoadedModule pme = new LoadedModule(); pme.ModulePath = s3; pre.ListProcessModule.Add(pme); } return(s); } else// Os,Cur,Tar : 64 or 32 { PROCESS_BASIC_INFORMATION pbi = new PROCESS_BASIC_INFORMATION(); int hr = NtQueryInformationProcess(handle, (int)PROCESSINFOCLASS.ProcessBasicInformation, ref pbi, Marshal.SizeOf(pbi), IntPtr.Zero); if (hr != 0) { return(null); } pebAddress = pbi.PebBaseAddress.ToInt64(); IntPtr pp = new IntPtr(); if (!ReadProcessMemory(handle, new IntPtr(pebAddress + processParametersOffset), ref pp, new IntPtr(Marshal.SizeOf(pp)), IntPtr.Zero)) { return(null); } UNICODE_STRING us = new UNICODE_STRING(); if (!ReadProcessMemory(handle, new IntPtr((long)pp + offset), ref us, new IntPtr(Marshal.SizeOf(us)), IntPtr.Zero)) { return(null); } if ((us.Buffer == IntPtr.Zero) || (us.Length == 0)) { return(null); } string s = new string('\0', us.Length / 2); if (!ReadProcessMemory(handle, us.Buffer, s, new IntPtr(us.Length), IntPtr.Zero)) { return(null); } UNICODE_STRING us2 = new UNICODE_STRING(); if (!ReadProcessMemory(handle, new IntPtr((long)pp + offset - Marshal.SizeOf(us2)), ref us2, new IntPtr(Marshal.SizeOf(us2)), IntPtr.Zero)) { return(null); } if ((us2.Buffer == IntPtr.Zero) || (us2.Length == 0)) { return(null); } string s2 = new string('\0', us2.Length / 2); if (!ReadProcessMemory(handle, us2.Buffer, s2, new IntPtr(us2.Length), IntPtr.Zero)) { return(null); } pre.Path = s2; pre.Arguments = s; //////////// Read Loader //////// PEB_LDR_DATA ldr1 = new PEB_LDR_DATA(); IntPtr ldrp = StructToPtr(ldr1); if (!ReadProcessMemory(handle, new IntPtr(pebAddress + 0x0c), ref ldrp, new IntPtr(Marshal.SizeOf(ldr1)), IntPtr.Zero)) { return(null); } /// We have long ldraddress = ldrp.ToInt64(); IntPtr le1 = new IntPtr(ldraddress + 0x0c); if (!ReadProcessMemory(handle, new IntPtr(ldraddress + 0xc), ref le1, new IntPtr(Marshal.SizeOf(le1)), IntPtr.Zero)) { return(null); } while (le1 != null) { UNICODE_STRING_32 us3 = new UNICODE_STRING_32(); if (!ReadProcessMemory(handle, new IntPtr(le1.ToInt64() + 0x24), ref us3, new IntPtr(Marshal.SizeOf(us3)), IntPtr.Zero)) { return(null); } if ((us3.Buffer == 0) || (us3.Length == 0)) { return(null); } string s3 = new string('\0', us3.Length / 2); if (!ReadProcessMemory(handle, new IntPtr(us3.Buffer), s3, new IntPtr(us3.Length), IntPtr.Zero)) { return(null); } long nextlist = le1.ToInt64(); IntPtr nextlistp = new IntPtr(nextlist); if (!ReadProcessMemory(handle, nextlistp, ref le1, new IntPtr(Marshal.SizeOf(le1)), IntPtr.Zero)) { return(null); } LoadedModule pme = new LoadedModule(); pme.ModulePath = s3; pre.ListProcessModule.Add(pme); } return(s); } } finally { CloseHandle(handle); } }