Add a new tool scanner class


As a first step to integrate a new scanner, answer the below questions:

  • Which module will this scanner be a part of?
    • Amass is used for subdomain discovery and hence will be part of the disovery module
  • Is this scanner a command line tool or API?
    • Amass is a command line tool
  • What will the tool output?
    • Amass will output a list of subdomains
  • What is the report output format we are expecting to parse?
    • Though Amass supports a number of output formats, lets go with .txt
  • What is the command that you need to execute?
    • amass enum -passive -d {input_domain} -o {output_file_path}
  • What is the input that the tool takes, meaning, TLDs, subdomains, IPs etc.?
    • Amass takes TLDs as an input

Now that we have a clear understanding of the expected input and output from the tool, let's begin the process of creating the scanner class. As previously indicated here, we are required to implement three functions:

  • base_get_commands() or get_commands()
  • parse_report()
  • db_operations()

Creating the Tool Class

Please Note - The name of the tool class should be the same as defined in the config file

Create a new file under /mantis/mantis/modules/discovery/ and name it Amass.py

Implementing get_commands()

This function needs to return a list of tool commands for every asset.

def get_commands(self, assets):
    self.org = args.org
    self.base_command = 'amass enum -passive -d {input_domain} -o {output_file_path}'
    self.outfile_extension = ".txt"
    self.assets = await get_assets_grouped_by_type(args, ASSET_TYPE_TLD)
    return super().base_get_commands(self.assets)
  • self.base_command represents the command to be executed
  • self.outfile_extension indicates the output file extension
  • self.assets exclusively extract TLDs from the database, which are then supplied as input to Amass

InfoπŸ’‘- As mentioned here, Mantis incorporates a range of pre-existing utility functions to facilitate the seamless integration of new tools

Implementing parse_report()

This function is required to parse what the scanner outputs and insert it into the database. In this context, a list of subdomains need to be extrated and inserted into the database.

InfoπŸ’‘- To understand the DB schema, click here

def parse_report(self, outfile):
        output_dict_list = []
        amass_output = open(outfile).readlines()
        for domain in amass_output:
            domain_dict = {}
            domain_dict['asset'] = domain.rstrip('\n')
            domain_dict['asset_type'] = ASSET_TYPE_SUBDOMAIN
            domain_dict['org'] = self.org
            output_dict_list.append(domain_dict)

        return output_dict_list

You dont have to worry about where the output file is stored etc. The outfile parameter is the path to the output file generated by the tool

  • domain contains the subdomain
  • asset_type is a parameter required for Mantis, the type of Asset, if its a TLD, subdomain or IP
  • org is the organisation to which the asset belongs to, fetched from args

Implementing db_operations()

The final step is to insert the data into mongoDB

async def db_operations(self, tool_output_dict, asset=None):
        await CrudUtils.insert_assets(tool_output_dict)

This is straight forward, call the corresponding util function to insert the data into mongoDB.

InfoπŸ’‘- Depending on whether you are inserting an asset, or updating an asset for recon information, or adding a new finding, you can use the corresponding util functions as described here

⏭️ In a similar fashion let's try to add a new API scanner.