ronin-rb/ronin

View on GitHub
lib/ronin/cli/commands/typosquat.rb

Summary

Maintainability
A
1 hr
Test Coverage
# frozen_string_literal: true
#
# Copyright (c) 2006-2023 Hal Brodigan (postmodern.mod3 at gmail.com)
#
# Ronin is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ronin is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ronin.  If not, see <https://www.gnu.org/licenses/>.
#

require 'ronin/cli/value_processor_command'
require 'ronin/cli/typo_options'

require 'ronin/support/network/domain'

module Ronin
  class CLI
    module Commands
      #
      # Finds typo squatted domains.
      #
      # ## Usage
      #
      #     ronin typosquat [options] [DOMAIN ...]
      #
      # ## Options
      #
      #     -f, --file FILE                  Optional file to read values from
      #         --omit-chars                 Toggles whether to omit repeated characters
      #         --repeat-chars               Toggles whether to repeat single characters
      #         --swap-chars                 Toggles whether to swap certain common character pairs
      #         --change-suffix              Toggles whether to change the suffix of words
      #         -A, --has-addresses          Print typo squat domains with addresses
      #         -r, --registered             Print typo squat domains that are already registered
      #         -u, --unregistered           Print typo squat domains that can be registered
      #     -h, --help                       Print help information
      #
      # ## Arguments
      #
      #     DOMAIN                           The domain to typo squat
      #
      class Typosquat < ValueProcessorCommand

        include TypoOptions

        usage '[options] [DOMAIN ...]'

        option :has_addresses, desc: 'Print typo squat domains with addresses'

        option :registered, desc: 'Print typo squat domains that are already registered'

        option :unregistered, desc: 'Print typo squat domains that can be registered'

        argument :domain, required: true,
                          desc:     'The domain to typo squat'

        description 'Finds typo squatted domains'

        man_page 'ronin-typosquat.1'

        #
        # Processes each word.
        #
        # @param [String] domain
        #   A word argument to typo.
        #
        def process_value(domain)
          if options[:has_addresses]
            each_typo_squat(domain) do |typo_domain|
              if typo_domain.has_addresses?
                puts typo_domain
              end
            end
          elsif options[:registered]
            each_typo_squat(domain) do |typo_domain|
              if typo_domain.registered?
                puts typo_domain
              end
            end
          elsif options[:unregistered]
            each_typo_squat(domain) do |typo_domain|
              if typo_domain.unregistered?
                puts typo_domain
              end
            end
          else
            each_typo_squat(domain) do |typo_domain|
              puts typo_domain
            end
          end
        end

        #
        # Enumerates over each typosquat of the domain.
        #
        # @param [String] domain
        #   The domain to typo squat.
        #
        # @yield [typo_domain]
        #   The given block will be passed each new typo squated domain.
        #
        # @yieldparam [Ronin::Support::Network::Domain] typo_domain
        #   A typo squated variation on the input domain.
        #
        def each_typo_squat(domain)
          domain = Support::Network::Domain.new(domain)
          suffix = domain.suffix
          name   = domain.name.chomp(suffix)

          typo_generator.each_substitution(name) do |typo|
            yield Support::Network::Domain.new("#{typo}#{suffix}")
          end
        end

      end
    end
  end
end