From e01dbdbb5dfe52dcedf1d168b484df9852bd17c7 Mon Sep 17 00:00:00 2001 From: Spencer McIntyre Date: Thu, 2 Mar 2023 15:54:37 -0500 Subject: [PATCH] Add fix up tracking the process handle This allows the process handle to be closed when the process was not started by the Meterpreter instance. --- python/meterpreter/ext_server_stdapi.py | 2 + python/meterpreter/meterpreter.py | 52 +++++++++++++------------ 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/python/meterpreter/ext_server_stdapi.py b/python/meterpreter/ext_server_stdapi.py index fc622be4..aefe36d9 100644 --- a/python/meterpreter/ext_server_stdapi.py +++ b/python/meterpreter/ext_server_stdapi.py @@ -1353,6 +1353,8 @@ def stdapi_sys_process_attach(request, response): handle = OpenProcess(permissions, inherit, pid) if not handle: return error_result_windows(), response + meterpreter.processes[handle] = None + debug_print('[*] added process id: ' + str(pid) + ', handle: ' + str(handle)) response += tlv_pack(TLV_TYPE_HANDLE, handle) return ERROR_SUCCESS, response diff --git a/python/meterpreter/meterpreter.py b/python/meterpreter/meterpreter.py index c46eb028..d6919c57 100644 --- a/python/meterpreter/meterpreter.py +++ b/python/meterpreter/meterpreter.py @@ -1259,6 +1259,21 @@ class PythonMeterpreter(object): self.next_channel_id += 1 return idx + def close_channel(self, channel_id): + if channel_id not in self.channels: + return False + channel = self.channels[channel_id] + try: + channel.close() + except Exception: + debug_traceback('[-] failed to close channel id: ' + str(channel_id)) + return False + del self.channels[channel_id] + if channel_id in self.interact_channels: + self.interact_channels.remove(channel_id) + debug_print('[*] closed and removed channel id: ' + str(channel_id)) + return True + def add_process(self, process): if has_windll: PROCESS_ALL_ACCESS = 0x1fffff @@ -1274,37 +1289,24 @@ class PythonMeterpreter(object): return handle def close_process(self, proc_h_id): - proc_h = self.processes.pop(proc_h_id, None) - if not proc_h: + if proc_h_id not in self.processes: return False - for channel_id, channel in self.channels.items(): - if not isinstance(channel, MeterpreterProcess): - continue - if not channel.proc_h is proc_h: - continue - self.close_channel(channel_id) - break + proc_h = self.processes.pop(proc_h_id) + if proc_h: + # proc_h is only set when we started the process via execute and not when we attached to it + for channel_id, channel in self.channels.items(): + if not isinstance(channel, MeterpreterProcess): + continue + if not channel.proc_h is proc_h: + continue + self.close_channel(channel_id) + break if has_windll: CloseHandle = ctypes.windll.kernel32.CloseHandle CloseHandle.argtypes = [ctypes.c_void_p] CloseHandle.restype = ctypes.c_long CloseHandle(proc_h_id) - debug_print('[*] closed and removed process id: ' + str(proc_h.pid) + ', handle: ' + str(proc_h_id)) - return True - - def close_channel(self, channel_id): - if channel_id not in self.channels: - return False - channel = self.channels[channel_id] - try: - channel.close() - except Exception: - debug_traceback('[-] failed to close channel id: ' + str(channel_id)) - return False - del self.channels[channel_id] - if channel_id in self.interact_channels: - self.interact_channels.remove(channel_id) - debug_print('[*] closed and removed channel id: ' + str(channel_id)) + debug_print('[*] closed and removed process handle: ' + str(proc_h_id)) return True def get_packet(self):