From 069ad805c19488d5c727fb431cb7253df2d3348f Mon Sep 17 00:00:00 2001 From: adfoster-r7 Date: Fri, 5 May 2023 13:50:38 +0100 Subject: [PATCH] Fix ruby 3.1 crashes when garbage collecting meterpreter resources --- lib/msf/core/framework.rb | 6 ++++++ lib/rex/post/meterpreter/channel.rb | 13 +++++++++---- .../extensions/stdapi/sys/event_log.rb | 13 +++++++++---- .../meterpreter/extensions/stdapi/sys/process.rb | 15 ++++++++++----- .../stdapi/sys/registry_subsystem/registry_key.rb | 13 +++++++++---- .../sys/registry_subsystem/remote_registry_key.rb | 14 ++++++++++---- .../meterpreter/extensions/stdapi/sys/thread.rb | 13 +++++++++---- 7 files changed, 62 insertions(+), 25 deletions(-) diff --git a/lib/msf/core/framework.rb b/lib/msf/core/framework.rb index 1fc8b9390d..682369b2b6 100644 --- a/lib/msf/core/framework.rb +++ b/lib/msf/core/framework.rb @@ -199,6 +199,8 @@ class Framework # # @return [Metasploit::Framework::DataService::DataProxy] def db + return @db if @db + synchronize { @db ||= get_db } @@ -209,6 +211,8 @@ class Framework # # @return [Msf::SessionManager] def sessions + return @sessions if @sessions + synchronize { @sessions ||= Msf::SessionManager.new(self) } @@ -219,6 +223,8 @@ class Framework # # @return [Msf::ThreadManager] def threads + return @threads if @threads + synchronize { @threads ||= Msf::ThreadManager.new(self) } diff --git a/lib/rex/post/meterpreter/channel.rb b/lib/rex/post/meterpreter/channel.rb index 4b65022608..52ebd27d5e 100644 --- a/lib/rex/post/meterpreter/channel.rb +++ b/lib/rex/post/meterpreter/channel.rb @@ -153,11 +153,16 @@ class Channel def self.finalize(client, cid) proc { unless cid.nil? - begin - self._close(client, cid) - rescue => e - elog("finalize method for Channel failed", error: e) + deferred_close_proc = proc do + begin + self._close(client, cid) + rescue => e + elog("finalize method for Channel failed", error: e) + end end + + # Schedule the finalizing logic out-of-band; as this logic might be called in the context of a Signal.trap, which can't synchronize mutexes + client.framework.sessions.schedule(deferred_close_proc) end } end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb index 07410d6be9..4c1bf51d63 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb @@ -67,11 +67,16 @@ class EventLog def self.finalize(client,handle) proc do - begin - self.close(client,handle) - rescue => e - elog("finalize method for EventLog failed", error: e) + deferred_close_proc = proc do + begin + self.close(client,handle) + rescue => e + elog("finalize method for EventLog failed", error: e) + end end + + # Schedule the finalizing logic out-of-band; as this logic might be called in the context of a Signal.trap, which can't synchronize mutexes + client.framework.sessions.schedule(deferred_close_proc) end end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb index a146189406..6099101c80 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb @@ -337,11 +337,16 @@ class Process < Rex::Post::Process def self.finalize(client, handle) proc do - begin - self.close(client, handle) - rescue => e - elog("finalize method for Process failed", error: e) + deferred_close_proc = proc do + begin + self.close(client, handle) + rescue => e + elog("finalize method for Process failed", error: e) + end end + + # Schedule the finalizing logic out-of-band; as this logic might be called in the context of a Signal.trap, which can't synchronize mutexes + client.framework.sessions.schedule(deferred_close_proc) end end @@ -366,7 +371,7 @@ class Process < Rex::Post::Process request = Packet.create_request(COMMAND_ID_STDAPI_SYS_PROCESS_CLOSE) request.add_tlv(TLV_TYPE_HANDLE, handle) client.send_request(request, nil) - handle = nil; + handle = nil return true end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb index 8daefe8a3a..d66acf9b52 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb @@ -36,11 +36,16 @@ class RegistryKey def self.finalize(client,hkey) proc do - begin - self.close(client,hkey) - rescue => e - elog("finalize method for RegistryKey failed", error: e) + deferred_close_proc = proc do + begin + self.close(client,hkey) + rescue => e + elog("finalize method for RegistryKey failed", error: e) + end end + + # Schedule the finalizing logic out-of-band; as this logic might be called in the context of a Signal.trap, which can't synchronize mutexes + client.framework.sessions.schedule(deferred_close_proc) end end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb index aa5320c894..79a6a2daf3 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/remote_registry_key.rb @@ -35,11 +35,17 @@ class RemoteRegistryKey def self.finalize(client, hkey) proc do - begin - self.close(client, hkey) - rescue => e - elog("finalize method for RemoteRegistryKey failed", error: e) + # Schedule the finalizing logic out-of-band; as this logic might be called in the context of a Signal.trap, which can't synchronize mutexes + client.framework.sessions.schedule do + begin + self.close(client, hkey) + rescue => e + elog("finalize method for RemoteRegistryKey failed", error: e) + end end + + # Schedule the finalizing logic out-of-band; as this logic might be called in the context of a Signal.trap, which can't synchronize mutexes + client.framework.sessions.schedule(deferred_close_proc) end end diff --git a/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb b/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb index cd5a1dafc4..294a0e91f0 100644 --- a/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +++ b/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb @@ -41,11 +41,16 @@ class Thread < Rex::Post::Thread def self.finalize(client,handle) proc do - begin - self.close(client, handle) - rescue => e - elog("finalize method for thread failed", error: e) + deferred_close_proc = proc do + begin + self.close(client, handle) + rescue => e + elog("finalize method for thread failed", error: e) + end end + + # Schedule the finalizing logic out-of-band; as this logic might be called in the context of a Signal.trap, which can't synchronize mutexes + client.framework.sessions.schedule(deferred_close_proc) end end