From 0399846c6de104054957b4f0f3087b8cec267581 Mon Sep 17 00:00:00 2001 From: Egor Kalinichev Date: Thu, 21 Mar 2024 14:28:27 +0100 Subject: [PATCH] Avoid code duplication between `interactive_shell_write` and `meterpreter_write` methods --- lib/msf/core/rpc/v10/rpc_session.rb | 53 ++++++++++++++--------------- 1 file changed, 25 insertions(+), 28 deletions(-) diff --git a/lib/msf/core/rpc/v10/rpc_session.rb b/lib/msf/core/rpc/v10/rpc_session.rb index 40d0727d774de..809d0467fd4bb 100644 --- a/lib/msf/core/rpc/v10/rpc_session.rb +++ b/lib/msf/core/rpc/v10/rpc_session.rb @@ -181,16 +181,7 @@ def rpc_interactive_shell_write(sid, data) # and we don't know exact type of the session, so we just pass empty string session = _valid_session(sid, '') - unless session.user_output.respond_to?(:dump_buffer) - session.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new) - end - - if session.interacting - session.user_input.put(data + "\n") - else - framework.threads.spawn('InteractiveRunSingle', false, session) { |s| s.console.run_single(data) } - end - { 'result' => 'success' } + _interactive_write(session) end # Reads the output from interactive session (such as a command output). @@ -308,7 +299,6 @@ def rpc_ring_clear(sid) { "result" => "success" } end - # Sends an input to a meterpreter prompt. # You may want to use #rpc_meterpreter_read to retrieve the output. # @@ -325,26 +315,12 @@ def rpc_ring_clear(sid) # @see #rpc_meterpreter_run_single # @example Here's how you would use this from the client: # rpc.call('session.meterpreter_write', 2, "sysinfo") - def rpc_meterpreter_write( sid, data) - s = _valid_session(sid,"meterpreter") - - if not s.user_output.respond_to? :dump_buffer - s.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new) - end + def rpc_meterpreter_write(sid, data) + session = _valid_session(sid, 'meterpreter') - interacting = false - s.channels.each_value do |ch| - interacting ||= ch.respond_to?('interacting') && ch.interacting - end - if interacting - s.user_input.put(data + "\n") - else - self.framework.threads.spawn("MeterpreterRunSingle", false, s) { |sess| sess.console.run_single(data) } - end - { "result" => "success" } + _interactive_write(session) end - # Detaches from a meterpreter session. Serves the same purpose as [CTRL]+[Z]. # # @param [Integer] sid Session ID. @@ -559,6 +535,27 @@ def _interactive_read(session) { 'data' => data } end + def _interactive_write(session) + unless session.user_output.respond_to? :dump_buffer + session.init_ui(Rex::Ui::Text::Input::Buffer.new, Rex::Ui::Text::Output::Buffer.new) + end + + interacting = false + if session.respond_to? :channels + session.channels.each_value do |ch| + interacting ||= ch.respond_to?('interacting') && ch.interacting + end + end + + if interacting + session.user_input.put(data + "\n") + else + framework.threads.spawn('InteractiveRunSingle', false, session) { |s| s.console.run_single(data) } + end + + { 'result' => 'success' } + end + end end end