Skip to content

Commit

Permalink
Add setg option to log TLV packets to console or file
Browse files Browse the repository at this point in the history
  • Loading branch information
sjanusz-r7 committed Mar 1, 2022
1 parent 96e1e3b commit 869f073
Show file tree
Hide file tree
Showing 6 changed files with 117 additions and 5 deletions.
9 changes: 9 additions & 0 deletions lib/msf/ui/console/command_dispatcher/core.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1914,6 +1914,15 @@ def cmd_set(*args)
print_warning("Changing the SSL option's value may require changing RPORT!")
end

# Correctly set the file output if user provides a directory for SessionTlvLogging
if name.casecmp?('SessionTlvLogging')
pathname = ::Pathname.new(datastore[name].split('file:').last)

if ::File.directory?(pathname) && datastore[name].start_with?('file:')
datastore[name] = ::File.join(datastore[name], 'sessiontlvlogging.txt')
end
end

print_line("#{name} => #{datastore[name]}")
end

Expand Down
1 change: 1 addition & 0 deletions lib/msf/ui/console/command_dispatcher/modules.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1439,6 +1439,7 @@ def show_global_options
[ 'LogLevel', framework.datastore['LogLevel'] || "0", 'Verbosity of logs (default 0, max 3)' ],
[ 'MinimumRank', framework.datastore['MinimumRank'] || "0", 'The minimum rank of exploits that will run without explicit confirmation' ],
[ 'SessionLogging', framework.datastore['SessionLogging'] || "false", 'Log all input and output for sessions' ],
[ 'SessionTlvLogging', framework.datastore['SessionTlvLogging'] || "false", 'Log all incoming and outgoing TLV packets' ],
[ 'TimestampOutput', framework.datastore['TimestampOutput'] || "false", 'Prefix all console output with a timestamp' ],
[ 'Prompt', framework.datastore['Prompt'] || Msf::Ui::Console::Driver::DefaultPrompt.to_s.gsub(/%.../,"") , "The prompt string" ],
[ 'PromptChar', framework.datastore['PromptChar'] || Msf::Ui::Console::Driver::DefaultPromptChar.to_s.gsub(/%.../,""), "The prompt character" ],
Expand Down
51 changes: 51 additions & 0 deletions lib/msf/ui/console/driver.rb
Original file line number Diff line number Diff line change
Expand Up @@ -393,6 +393,8 @@ def on_variable_set(glob, var, val)
case var.downcase
when 'sessionlogging'
handle_session_logging(val) if glob
when 'sessiontlvlogging'
handle_session_tlv_logging(val) if glob
when 'consolelogging'
handle_console_logging(val) if glob
when 'loglevel'
Expand All @@ -412,6 +414,8 @@ def on_variable_unset(glob, var)
case var.downcase
when 'sessionlogging'
handle_session_logging('0') if glob
when 'sessiontlvlogging'
handle_session_tlv_logging('false') if glob
when 'consolelogging'
handle_console_logging('0') if glob
when 'loglevel'
Expand Down Expand Up @@ -601,6 +605,53 @@ def handle_ssh_ident(val)
$VERBOSE = verbose
end

def handle_session_tlv_logging(val)
if val
if val.casecmp?('console') || val.casecmp?('true') || val.casecmp?('false')
return true
elsif val.start_with?('file:') && !val.split('file:').empty?
pathname = ::Pathname.new(val.split('file:').last)

# Check if we want to write the log to file
if ::File.file?(pathname)
if ::File.writable?(pathname)
return true
else
print_status "No write permissions for log output file: #{pathname}"
return false
end
# Check if we want to write the log file to a directory
elsif ::File.directory?(pathname)
if ::File.writable?(pathname)
return true
else
print_status "No write permissions for log output directory: #{pathname}"
return false
end
# Check if the subdirectory exists
elsif ::File.directory?(pathname.dirname)
if ::File.writable?(pathname.dirname)
return true
else
print_status "No write permissions for log output directory: #{pathname.dirname}"
return false
end
else
# Else the directory doesn't exist. Check if we can create it.
begin
::FileUtils.mkdir_p(pathname.dirname)
return true
rescue ::StandardError => e
print_status "Error when trying to create directory #{pathname.dirname}: #{e.message}"
return false
end
end
end
end

false
end

# Require the appropriate readline library based on the user's preference.
#
# @return [void]
Expand Down
5 changes: 5 additions & 0 deletions lib/msf/ui/console/module_option_tab_completion.rb
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@ def tab_complete_option_names(mod, str, words)
PromptChar
PromptTimeFormat
MeterpreterPrompt
SessionTlvLogging
]
if !mod
return res
Expand Down Expand Up @@ -122,6 +123,10 @@ def tab_complete_option_names(mod, str, words)
# Provide tab completion for option values
#
def tab_complete_option_values(mod, str, words, opt:)
if words.last.casecmp?('SessionTlvLogging')
return %w[console true false file:<file>]
end

res = []
# With no module, we have nothing to complete
if !mod
Expand Down
3 changes: 2 additions & 1 deletion lib/rex/post/meterpreter/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,8 @@ def init_meterpreter(sock,opts={})
self.url = opts[:url]
self.ssl = opts[:ssl]

self.tlv_logging_enabled = true

self.pivot_session = opts[:pivot_session]
if self.pivot_session
self.expiration = self.pivot_session.expiration
Expand Down Expand Up @@ -502,4 +504,3 @@ def unicode_filter_decode(str)
end

end; end; end

53 changes: 49 additions & 4 deletions lib/rex/post/meterpreter/packet_dispatcher.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
require 'rex/post/meterpreter/command_mapper'
require 'rex/post/meterpreter/packet_response_waiter'
require 'rex/exceptions'
require 'pathname'

module Rex
module Post
Expand Down Expand Up @@ -88,6 +89,9 @@ def shutdown_passive_dispatcher
self.send_queue = []
self.recv_queue = []
self.waiters = []

self.tlv_log_file.close unless self.tlv_log_file.nil?
self.tlv_log_file = nil
end

def on_passive_request(cli, req)
Expand Down Expand Up @@ -130,8 +134,7 @@ def send_packet(packet, opts={})
tlv_enc_key = opts[:tlv_enc_key]
end

# Uncomment this line if you want to see outbound packets in the console.
# STDERR.puts("\n\e[1;31mSEND\e[0m: #{packet.inspect}\n")
log_packet(packet, :send) if self.tlv_logging_enabled

bytes = 0
raw = packet.to_r(session_guid, tlv_enc_key)
Expand Down Expand Up @@ -579,8 +582,7 @@ def decrypt_inbound_packet(packet)
def dispatch_inbound_packet(packet)
handled = false

# Uncomment this line if you want to see inbound packets in the console
# STDERR.puts("\n\e[1;32mRECV\e[0m: #{packet.inspect}\n")
log_packet(packet, :recv) if self.tlv_logging_enabled

# Update our last reply time
self.last_checkin = ::Time.now
Expand Down Expand Up @@ -639,6 +641,49 @@ def deregister_inbound_handler(handler)
attr_accessor :receiver_thread # :nodoc:
attr_accessor :dispatcher_thread # :nodoc:
attr_accessor :waiters # :nodoc:
attr_accessor :tlv_log_file # :nodoc:
attr_accessor :tlv_logging_enabled # :nodoc:

def log_packet(packet, packet_type)
option = framework.datastore['SessionTlvLogging']
return if option.nil? || option.casecmp?('false')

if option.casecmp?('console') || option.casecmp?('true')
log_packet_to_console(packet, packet_type)
elsif option.start_with?('file:')
log_packet_to_file(packet, packet_type)
end
end

def log_packet_to_console(packet, packet_type)
if packet_type == :recv
print "\n%bluRECV%clr: #{packet.inspect}\n"
elsif packet_type == :send
print "\n%redSEND%clr: #{packet.inspect}\n"
end
end

def log_packet_to_file(packet, packet_type)
path = framework.datastore['SessionTlvLogging'].split('file:').last
pathname = ::Pathname.new(path)

begin
self.tlv_log_file ||= ::File.open(pathname, 'a+')

if packet_type == :recv
self.tlv_log_file.puts("\nRECV: #{packet.inspect}\n")
elsif packet_type == :send
self.tlv_log_file.puts("\nSEND: #{packet.inspect}\n")
end
rescue ::StandardError => e
self.tlv_logging_enabled = false
print_error "Failed writing to TLV Log File: #{pathname} with error: #{e.message}. Turning off logging for this session: #{self.inspect}..."
elog(e)
self.tlv_log_file.close unless self.tlv_log_file.nil?
self.tlv_log_file = nil
return
end
end
end

module HttpPacketDispatcher
Expand Down

0 comments on commit 869f073

Please sign in to comment.