NetReconToolkit – Part 04

Series Navigation
<< NetReconToolkit – Part 03          

And the day has finally come (if you’re thinking … free donuts for everyone? Nope, sorry) but something just as good … NRT is on Github!

To be fair, it’s only bare-bones at this point, but logging is working and database initialization is well on it’s way. If you want to git clone the repo (that just sounds cool), head over to Github. You can scan a client by updating the following line near the end of NRT.py:

scan_host("127.0.0.1")  # The IP of the host to scan

127.0.0.1 will scan your local machine (if you didn’t know that already).

I try to comment almost every line, so that someone with little coding experience can get a good idea of what’s going on. Which leads me to an important topic … code formatting (yay …).

Formatting

I know there are lots of opinions about how code should be formatted and how it should flow. The nice thing about Python (and one reason I like it) is that it enforces basic formatting hygiene. I use PyCharm and it has a nifty feature called Reformat Code (Top menu bar > Code > Reformat Code … or just Ctrl+Alt+L), which I use all the time to keep things consistent.

The goal is to make my code easy to read, so I prefer to use long variable names, this way I can describe what’s being stored in the variable. One of my great frustrations is seeing a variable called “s” or “c” (or something like that) and then trying to figure out what it actually does. Remember, computers don’t care how long a variable’s name is, so please use human-readable words to describe its function. (end rant)

I also like to list out exactly how my code flows. So all of my functions will appear under

if __name__ == '__main__':

In the order they’ll be executed (with very few exceptions) that way anyone can look and see what’s happening. No need to spend hours chasing down a bunch of functions as you worm your way through the program.

Lastly, I prefer to write out my logic, even if there’s a way to make the code shorter (or when PyCharm gives me helpful shortcut suggestions). My aim is readability, not code length, so … no lambda expressions. A small example, from W3Schools, about lambdas. This is not very readable …

x = lambda a: a + 10
print(x(5))

This is (even a non-programmer can probably understand what’s going on here) …

def add_ten(x):
    return x + 10

print(add_ten(5))

With that said (and I know there will be people who disagree … and that’s okay) I’m very happy with my coding style. It’s proven itself over time … I can go back to code I haven’t touched in years and remember exactly what it does in a minute or two. Now … let’s move on to the code.

Current NRT Code

I plan to include the full code, at it’s current state, in each subsequent blog post … for those who don’t like Github:

# Install imports using: pip install -r requirements.txt
import inspect
import sqlite3
import nmap
import logging
import logging.handlers

log_filename = "NetReconToolkit.log"  # The filename of the log file. TODO Set log_filename based on settings.txt
log_rotate_handler = logging.handlers.RotatingFileHandler(log_filename, maxBytes=100000, backupCount=5)  # Enable log file rotation if it exceeds maxBytes, keeping 5 total backup files. TODO Set maxBytes and backupCount via settings.txt
logging.basicConfig(format='%(asctime)s >> %(message)s', handlers=[log_rotate_handler], level=logging.DEBUG)  # Instantiate root logger. TODO Set logging level through settings.txt
logging.info('-----##### Starting NRT #####-----')


def database_connection():
    current_function_name = inspect.getframeinfo(inspect.currentframe()).function  # Get the name of the current function for logging purposes
    logging.info('%s - Entering function', current_function_name)

    database_name = "NetReconToolkit.db"
    sqlite3_connection = sqlite3.connect(database_name)  # Create database connection using database_name variable.
    sqlite3_connection.row_factory = sqlite3.Row  # Enable to provide index-based and case-sensitive name-based access to columns (https://docs.python.org/3/library/sqlite3.html#sqlite3.Connection.row_factory).


def scan_host(ip_to_scan):
    current_function_name = inspect.getframeinfo(inspect.currentframe()).function  # Get the name of the current function for logging purposes
    logging.info('%s - Entering function', current_function_name)

    print("Scanning: " + ip_to_scan)  # Display the host we're currently scanning.
    logging.info('%s - Scanning: %s', current_function_name, ip_to_scan)
    nmap_ps = nmap.PortScanner()  # Create our instance of python-nmap.
    nmap_ps.scan(hosts=ip_to_scan,
                 arguments='-sV -Pn -p22-445')  # Set our host to scan and arguments (sV - Service scan, Pn - don't ping, but assume the port is up, p22-445 - only scan ports 22 through 445).

    for host in nmap_ps.all_hosts():  # Iterate through all scanned hosts.
        print(nmap_ps[host].hostname())  # Display the hostname for each host.

        for protocol in nmap_ps[host].all_protocols():  # Iterate through all protocols (TCP, UDP, etc.) for one host.
            protocol_keys = nmap_ps[host][protocol].keys()  # Get a dictionary containing all port numbers (22, 80, 445, etc.) for one protocol.

            for port in protocol_keys:  # Iterate through each port in the protocol_keys dictionary.
                print(port, "-", nmap_ps[host][protocol][port]['state'])  # Display each port and it's associated state.


if __name__ == '__main__':
    current_function_name = inspect.getframeinfo(inspect.currentframe()).function  # Get the name of the current function for logging purposes
    logging.info('%s - Entering function', "Main")

    scan_host("127.0.0.1")  # The IP of the host to scan

    logging.info('-----##### Ending NRT #####-----')

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.