Python Tools for system analysis 
from __future__ import division
import nltk
from prettytable import PrettyTable
from nltk.corpus import gutenberg
from nltk.book import *
from nltk.corpus import wordnet as wn

print((type(text1)))
print(len(text1))
print((len)(set(text1)))
print(text1[:10])
print(text2[:10])
      
table = PrettyTable()
PrettyTable.attributes 

#add columns
table.field_names = ['Description', 'Value']

table.add_row(['Type of text', str(type(text1))])
table.add_row(['Length of text', len(text1)])
table.add_row(['Length of set(text1)', len(set(text1)) ])
table.add_row(['First 10 elements of text1', text1[:10]])
table.add_row(['First 10 elements of Text 2',text2[:10]])
table.add_row(['fileids',gutenberg.fileids()])
table.add_row(['Concordance',text1.concordance('passion')])

hamlet_sentences = gutenberg.sents('shakespeare-hamlet.txt')

print(('length of hamlet senteces:'),len(hamlet_sentences))

print(('the count of the word horse:'), text1.count('horse'))
print(table)

vocab = nltk.FreqDist(text1)
print(('length of vocab:'),len(vocab))
print(('vocab most common:', (vocab.most_common(20))))



# Dictionary 
w = wn.synset("unmitigated.a.01")


print(w.name(), '-', w.definition())
print(w.examples())

#synsets

cat = wn.synset("cat.n.01")
cat.hypernyms()

print(cat)
Functions/NLTKQuery.py
green-dino/forensictools
from flask import Flask, render_template, request, redirect, url_for
import tempfile
from scapy.all import *
from scapy.layers.inet import IP
import networkx as nx
import matplotlib
matplotlib.use('Agg')
import matplotlib.pyplot as plt  # Import Matplotlib
from bokeh.io import output_file, show
from bokeh.models import Plot, Range1d, MultiLine, Circle, HoverTool, BoxZoomTool, ResetTool, LabelSet, ColumnDataSource
from bokeh.plotting import from_networkx
from bokeh.palettes import Spectral4
import webbrowser

app = Flask(__name__)

def setup_logging():
    log_format = '%(asctime)s [%(levelname)s] - %(message)s'
    logging.basicConfig(filename='app.log', level=logging.INFO, format=log_format)

@app.route("/")
def index():
    return render_template("index.html")

@app.route("/upload_pcap", methods=["POST"])
def upload_pcap():
    pcap_file = request.files["pcap_file"]
    if not pcap_file:
        return "No PCAP file uploaded", 400

    with tempfile.NamedTemporaryFile(delete=False) as temp_pcap:
        temp_pcap.write(pcap_file.read())
        pcap_path = temp_pcap.name

    G = generate_network_map(pcap_path)
    output_path = os.path.join(app.root_path, "static", "network.svg")
    plot_network_map(G, output_path)
    
    return redirect(url_for("show_network_map"))

@app.route("/show_network_map")
def show_network_map():
    return render_template("show_network_map.html")

def generate_network_map(pcap_path):
    try:
        pcap = rdpcap(pcap_path)
    except Exception as e:
        print(f"Failed to read PCAP file: {e}")
        return None

    G = nx.DiGraph()

    for packet in pcap:
        if IP in packet:
            src_ip = packet[IP].src
            dst_ip = packet[IP].dst
            G.add_edge(src_ip, dst_ip)

    mapping = {node: i for i, node in enumerate(G.nodes())}
    G_relabeled = nx.relabel_nodes(G, mapping)

    return G_relabeled  # Return the generated graph

def plot_network_map(G, output_path=None):
    pos = nx.spring_layout(G, k=0.15, iterations=20)
    

    if output_path:
        fig, ax = plt.subplots(figsize=(8, 8))  # Create a Matplotlib figure and axis
        nx.draw(G, pos, with_labels=True, node_size=300, node_color='skyblue', font_size=10, font_color='black', font_weight='bold', alpha=0.8, width=0.5, edge_color='gray', ax=ax)
        plt.title("Network Map")
        plt.axis('off')  # Turn off axis
        plt.savefig(output_path, format="svg")  # Save the plot as an SVG file (change format to SVG)
        plt.close(fig)  # Close the Matplotlib figure
        return f"Network map saved to {output_path}"  # Return a status message
    else:
        return "Network map displayed in the browser"  # Return a status message


if __name__ == "__main__":
    app.run(debug=True)

Functions/NetworkAnalysis/app.py
green-dino/forensictools
import os
import csv
import json

class DataStorageManager:
    def __init__(self, storage_file_path="data_storage.json"):
        self.storage_file_path = storage_file_path
        self.data_storage = {}

    def csv_to_dictionary(self, file_path):
        with open(file_path, 'r', newline='', encoding='utf-8') as csvfile:
            reader = csv.DictReader(csvfile)
            sheet_data = [row for row in reader]
        return sheet_data

    def save_data_storage(self):
        with open(self.storage_file_path, 'w') as json_file:
            json.dump(self.data_storage, json_file)

    def load_data_storage(self):
        if os.path.exists(self.storage_file_path):
            with open(self.storage_file_path, 'r') as json_file:
                self.data_storage = json.load(json_file)

    def print_dictionary_keys(self):
        print("Dictionary keys:")
        for key in self.data_storage:
            print("- " + key)

    def process_folder(self, folder_path):
        if os.path.exists(self.storage_file_path):
            self.load_data_storage()
            print("Loaded data storage from file.")
        else:
            self.data_storage = {}

            for filename in os.listdir(folder_path):
                if filename.endswith(".csv"):
                    file_path = os.path.join(folder_path, filename)
                    sheet_name = os.path.splitext(filename)[0]

                    sheet_data = self.csv_to_dictionary(file_path)
                    self.data_storage[sheet_name] = {"data": sheet_data}

            self.save_data_storage()
            print("Saved data storage to file.")

    def list_available_sheets(self):
        print("Available sheet names:")
        for sheet_name in self.data_storage.keys():
            print("- " + sheet_name)

    def access_sheet_data(self, sheet_name):
        if sheet_name in self.data_storage:
            sheet_data = self.data_storage[sheet_name]["data"]
            print(f"Data from sheet '{sheet_name}':")

            for row_data in sheet_data:
                print(row_data)
        else:
            print("Sheet name not found in data storage.")

    def view_components_in_data_storage(self):
        print("\nComponents in data storage:")
        self.print_dictionary_keys()

if __name__ == "__main__":
    manager = DataStorageManager()

    folder_path = input("Enter the path of the folder containing CSV files: ")
    manager.process_folder(folder_path)

    manager.list_available_sheets()

    sheet_name_to_access = input("Enter the sheet name you want to access: ")
    manager.access_sheet_data(sheet_name_to_access)

    manager.view_components_in_data_storage()

Functions/csv_dictionary.py
green-dino/forensictools
import os
import subprocess
import csv

def search_and_write_electron_versions(search_dir, file_pattern, output_file):
    # Define the shell command to execute
    command = (
        f'find {search_dir} -type f -name "{file_pattern}" -exec '
        'sh -c "echo  \\\"{}\\\" && strings \\\"{}\\\" | grep \'Chrome/[0-9.]* Electron/[0-9]\' | head -n1 && echo " \\;'
    )

    # Run the shell command
    result = subprocess.run(command, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True)

    # Split the result into lines
    output_lines = result.stdout.splitlines()

    # Create a CSV file and write the results
    with open(output_file, 'w', newline='') as csv_file:
        csv_writer = csv.writer(csv_file)

        # Write the header row
        csv_writer.writerow(["File Path", "Electron Version"])

        # Write the data rows
        for line in output_lines:
            # Split the line into parts based on space
            parts = line.split(' ', 1)

            # Check if there are at least 2 parts (file path and Electron info)
            if len(parts) >= 2:
                file_path, electron_info = parts
                # Write to CSV
                csv_writer.writerow([file_path.strip(), electron_info.strip()])
            else:
                # Handle the case where there is no Electron version information
                file_path = parts[0]
                # Write to CSV with no Electron version
                csv_writer.writerow([file_path.strip(), "No Electron Version"])

    print(f"Results written to {output_file}")

# Example usage:
search_dir = '/Applications'
file_pattern = '*Electron Framework*'
output_file = 'electron_results.csv'
search_and_write_electron_versions(search_dir, file_pattern, output_file)

Functions/electron.py
green-dino/forensictools
import os
import re
from packaging import version
import csv

safe_versions = [version.parse(ver) for ver in ['22.3.24', '24.8.3', '25.8.1', '26.2.1']]
pattern = re.compile(r'Chrome/[0-9.]+ Electron/([0-9.]+)')

results = []

def check_file(file_path):
    with open(file_path, 'r') as file:
        content = file.read()
        match = pattern.search(content)
        if match:
            electron_version = version.parse(match.group(1))
            safe_versions_sorted = sorted(safe_versions, key=lambda v: v.numify(), reverse=True)
            if electron_version < safe_versions_sorted[0]:
                results.append((file_path, electron_version))

def find_electron_files(directory):
    for root, _, files in os.walk(directory):
        for file in files:
            if file.endswith(".js"):
                file_path = os.path.join(root, file)
                check_file(file_path)

if __name__ == "__main__":
    directory = "/Applications"
    find_electron_files(directory)

    # Write results to a CSV file
    with open('vulnerable_electron.csv', 'w', newline='') as csvfile:
        csv_writer = csv.writer(csvfile)
        csv_writer.writerow(['File Path', 'Vulnerable Electron Version'])
        csv_writer.writerows(results)

Functions/electron_not_shell.py
green-dino/forensictools
'''
Simple File I/O
Read a text file and display the contents

Script requires the file test.txt to be in the
same folder as the script
'''
try:

    with open("test.txt",'r') as book:
        content = book.read()
        print(content)

except Exception as err:
    print("Exception: ", str(err))
    
Functions/file-IO.py
green-dino/forensictools
import os
import hashlib
import time
from prettytable import PrettyTable

class FileHasher:
    def __init__(self):
        self.tbl = PrettyTable(['Path', 'Status', 'FileSize', 'LastModified', 'LastAccess', 'Created', 'SHA-512 HASH', 'Error Info'])

    def hash_file(self, file_path):
        try:
            with open(file_path, 'rb') as target:
                file_contents = target.read()
                sha512_obj = hashlib.sha512()
                sha512_obj.update(file_contents)
                hex_digest = sha512_obj.hexdigest()
                return hex_digest
        except Exception as err:
            return str(err)

    def process_directory(self, directory_path):
        for root, _, files in os.walk(directory_path):
            for file_name in files:
                file_to_hash = os.path.join(root, file_name)
                if os.path.isfile(file_to_hash):
                    print("\nAttempting to hash file:", file_to_hash)
                    file_info = os.stat(file_to_hash)
                    file_size = file_info.st_size
                    last_modified = time.ctime(file_info.st_mtime)
                    last_access = time.ctime(file_info.st_atime)
                    created = time.ctime(file_info.st_ctime)
                    hash_value = self.hash_file(file_to_hash)
                    error_info = ""
                    if isinstance(hash_value, str):
                        error_info = hash_value
                        hash_value = "Error"
                    self.tbl.add_row([file_to_hash, "Success", file_size, last_modified, last_access, created, hash_value, error_info])
                else:
                    self.tbl.add_row([file_to_hash, "Invalid File", "-", "-", "-", "-", "-", ""])

    def print_result_table(self):
        print(self.tbl)

def hash_files_in_directory(directory_path):
    file_hasher = FileHasher()
    if os.path.isdir(directory_path):
        file_hasher.process_directory(directory_path)
        file_hasher.print_result_table()
    else:
        print("\nInvalid Directory")

if __name__ == "__main__":
    while True:
        directory_path = input("\nEnter the directory path to hash files >>> ")
        if os.path.isdir(directory_path):
            break
        else:
            print("\nInvalid Directory... Please Try Again")

    hash_files_in_directory(directory_path)
    print("Script Done")

Functions/filehash.py
green-dino/forensictools
import os
import hashlib
from datetime import datetime
from prettytable import PrettyTable

def analyze_folder_properties(target_folder):
    print("Walking: ", target_folder, "\n")
    
    tbl = PrettyTable(['FilePath', 'FileSize', 'Modified Time', 'Access Time', 'Created Time', 'SHA-256 Hash'])
    
    for current_root, dir_list, file_list in os.walk(target_folder):
        for next_file in file_list:
            full_path = os.path.join(current_root, next_file)
            abs_path = os.path.abspath(full_path)
            file_size = os.path.getsize(abs_path)
            
            # MAC Times (in human-readable form)
            modified_time = os.path.getmtime(abs_path)
            accessed_time = os.path.getatime(abs_path)
            created_time = os.path.getctime(abs_path)
            
            modified_time_str = datetime.fromtimestamp(modified_time).strftime('%Y-%m-%d %H:%M:%S')
            accessed_time_str = datetime.fromtimestamp(accessed_time).strftime('%Y-%m-%d %H:%M:%S')
            created_time_str = datetime.fromtimestamp(created_time).strftime('%Y-%m-%d %H:%M:%S')
            
            # SHA-256 Hash value of the content of each file
            sha256_hash = hashlib.sha256()
            with open(abs_path, "rb") as file:
                while chunk := file.read(8192):
                    sha256_hash.update(chunk)
            sha256_hash_value = sha256_hash.hexdigest()
            
            tbl.add_row([abs_path, file_size, modified_time_str, accessed_time_str, created_time_str, sha256_hash_value])
    
    tbl.align = "l"  # align the columns left justified
    # display the table
    print(tbl.get_string(sortby="FileSize", reversesort=True))
    
    print("\nScript-End\n")

if __name__ == "__main__":
    target_folder = input("Enter Target Folder: ")
    analyze_folder_properties(target_folder)

Functions/folder.py
green-dino/forensictools
''' IMPORT STANDARD LIBRARIES '''
import os       # File System Methods
import sys      # System Methods
import time     # Time Conversion Methods
from datetime import datetime
import hashlib
import csv

''' IMPORT 3RD PARTY LIBRARIES '''
from prettytable import PrettyTable

''' DEFINE PSEUDO CONSTANTS '''

# NONE

''' LOCAL FUNCTIONS '''

class FileInspectionError(Exception):
    pass

'''Define Constants for Block Size and file types
'''

# Define constants for block size and file types
BLOCK_SIZE = 4096
FILE_TYPE_FILE = "File"
FILE_TYPE_DIRECTORY = "Directory"
FILE_TYPE_LINK = "Link"
FILE_TYPE_UNKNOWN = "Unknown"


def GetFileMetaData(fileName):
    ''' 
        obtain filesystem metadata
        from the specified file
        specifically, fileSize and MAC Times
        
        return True, None, fileSize and MacTimeList
    '''
    try:
        metaData = os.stat(fileName)   # Use the stat method to obtain meta data
        fileSize = metaData.st_size    # Extract fileSize and MAC Times
        timeLastAccess = metaData.st_atime
        timeLastModified = metaData.st_mtime
        timeCreated = metaData.st_ctime
        
        macTimeList = [timeLastModified, timeCreated, timeLastAccess]   # Group the MAC Times in a List
        return True, None, fileSize, macTimeList
    
    except Exception as err:
        return False, str(err), None, None

def CalculateSHA256(filePath):
    ''' 
        calculate the SHA-256 hash value
        of the content of the file
    '''
    try:
        sha256_hash = hashlib.sha256()
        with open(filePath, "rb") as f:
            # Read and update hash string value in blocks of 4K
            for byte_block in iter(lambda: f.read(BLOCK_SIZE), b""):
                sha256_hash.update(byte_block)
        return sha256_hash.hexdigest()
    except Exception as err:
        return str(err)

def inspect_directory(directory):
    ''' 
        Recursively inspect the specified directory and its subdirectories
    '''
    try:
        fileList = os.listdir(directory)
        for eachFile in fileList:
            path = os.path.join(directory, eachFile)
            path = os.path.abspath(path)

            success, errInfo, fileSize, macList = GetFileMetaData(path)

            if success:
                modTime = datetime.fromtimestamp(macList[0]).strftime('%Y-%m-%d %H:%M:%S')
                accTime = datetime.fromtimestamp(macList[1]).strftime('%Y-%m-%d %H:%M:%S')
                creTime = datetime.fromtimestamp(macList[2]).strftime('%Y-%m-%d %H:%M:%S')

                if os.path.isfile(path):
                    fileType = "File"
                    sha256_hash = CalculateSHA256(path)
                elif os.path.isdir(path):
                    fileType = "Directory"
                    sha256_hash = "N/A"
                    inspect_directory(path)  # Recursively inspect subdirectories
                elif os.path.islink(path):
                    fileType = "Link"
                    sha256_hash = "N/A"
                else:
                    fileType = "Unknown"
                    sha256_hash = "N/A"

                resultTable.add_row([path, fileSize, modTime, accTime, creTime, sha256_hash])

            else:
                print("Fail:      ", path, "Exception =     ", errInfo)

    except Exception as err:
        print("\n\nScript Aborted     ", "Exception =     ", err)


''' LOCAL CLASSES '''
# NONE

''' MAIN ENTRY POINT '''

def main():
    print("\nWork\n")

    targetDIR = input('Enter a Directory Path i.e. c:/ >>> ')
    print()

    global resultTable
    resultTable = PrettyTable(['AbsPath', 'FileSize', 'LastModified', 'LastAccess', 'CreatedTime', 'SHA-256 HASH'])

    resultList = []

    try:
        inspect_directory(targetDIR)

        resultTable.align = "l"
        print(resultTable.get_string(sortby="FileSize", reversesort=True))

        # Save the PrettyTable as a .csv file
        with open('file_metadata.csv', 'w', newline='') as csvfile:
            csv_writer = csv.writer(csvfile)
            csv_writer.writerow(resultTable.field_names)
            for row in resultTable:
                csv_writer.writerow(row)

        print("File metadata saved as file_metadata.csv")

    except Exception as err:
        print("\n\nScript Aborted     ", "Exception =     ", err)



if __name__ == '__main__':
    main()
    print("Script End")

Functions/meta_data_prettytable.py
green-dino/forensictools
import PyPDF2

def extract_text_and_metadata_from_pdf(pdf_path, save_to_file=False, output_file=None):
    try:
        with open(pdf_path, 'rb') as pdf_file:
            pdf_reader = PyPDF2.PdfFileReader(pdf_file)
            text = ''
            for page_num in range(pdf_reader.numPages):
                text += pdf_reader.getPage(page_num).extractText()
            
            if save_to_file and output_file:
                with open(output_file, 'w', encoding='utf-8') as file:
                    file.write(text)
                print("Extracted text saved to:", output_file)

            pdf_metadata = pdf_reader.getDocumentInfo()
            return text, pdf_metadata

    except Exception as e:
        return None, str(e)

if __name__ == "__main__":
    pdf_path = input("Enter the path to the PDF file: ")
    save_to_file = input("Do you want to save the extracted text to a file? (y/n): ").lower() == 'y'
    output_file = input("Enter the name of the output file (leave empty if not saving to a file): ").strip()
    
    extracted_text, pdf_metadata = extract_text_and_metadata_from_pdf(pdf_path, save_to_file, output_file)
    
    if extracted_text:
        print("Extracted Text:\n")
        print(extracted_text)
        
        if pdf_metadata:
            print("\nPDF Metadata:")
            for key, value in pdf_metadata.items():
                print(f"{key}: {value}")
    else:
        print("Error extracting text from the PDF.")

Functions/readpdf.py
green-dino/forensictools
import re
import sys
import os
from prettytable import PrettyTable

def analyze_large_file_for_urls(file_path, chunk_size):
    print("\nSimple File Search v2\n")

    try:
        # Verify file is real
        if os.path.isfile(file_path):
            urls_found = {}  # Dictionary to store the URLs and their occurrences
            urlPattern = re.compile(b'\w+:\/\/[\w@][\w.:@]+\/?[\w\.?=%&=\-@/$,]*')
            with open(file_path, 'rb') as targetFile:
                while True:
                    fileChunk = targetFile.read(chunk_size)
                    fileChunk = fileChunk.lower()  # broaden search

                    if fileChunk:  # if we still have data
                        # Search this chunk for URLs
                        urls = urlPattern.findall(fileChunk)
                        for url in urls:
                            url = url.decode('utf-8')  # Convert bytes to string
                            if url in urls_found:
                                urls_found[url] += 1
                            else:
                                urls_found[url] = 1
                    else:
                        # File has been processed
                        break
        else:
            print(file_path, "is not a valid file")
            sys.exit("Script Aborted")

        # Create a PrettyTable to display the results
        table = PrettyTable()
        table.field_names = ["URL", "Occurrences"]
        for url, occurrences in urls_found.items():
            table.add_row([url, occurrences])

        print(table)
        # Save the PrettyTable as an HTML file
        with open("urls_table.html", "w") as html_file:
            html_file.write(table.get_html_string())

        print("The PrettyTable has been saved as 'urls_table.html.'")

    except Exception as err:
        sys.exit("\nException: " + str(err) + " Script Aborted")

    print("\nFile Processed ... Script End")

if __name__ == "__main__":
    file_path = input("Enter the name of a large File: ")
    chunk_size = int(input("What size chunks?  "))
    analyze_large_file_for_urls(file_path, chunk_size)

Functions/summarize.py
green-dino/forensictools
import os
import hashlib
from prettytable import PrettyTable

def list_files_in_directory(directory):
    print("Walking: ", directory, "\n")

    tbl = PrettyTable(['FileName', 'FileSize'])

    for currentRoot, dirList, fileList in os.walk(directory):
        for nextFile in fileList:
            fullPath = os.path.join(currentRoot, nextFile)
            absPath = os.path.abspath(fullPath)

            print("=" * 40)
            print("FilePath: ", absPath)  # Display absolute File Path

            stats = os.stat(absPath)
            fileSize = stats.st_size

            tbl.add_row([absPath, fileSize])

    tbl.align = "l"  # align the columns left justified

    # display the table
    print(tbl.get_string(sortby="FileSize", reversesort=True))

    print("\nScript-End\n")

if __name__ == "__main__":
    dir_path = input("Enter Directory Path: ")
    list_files_in_directory(dir_path)

Functions/walk_file_system.py
green-dino/forensictools
import os
import re
from prettytable import PrettyTable

print("Current working directory:", os.getcwd())

from pathlib import Path

file_path = Path('dialog.txt')
if file_path.is_file():
    with file_path.open('r') as file:
        fileContents = file.read()
else:
    print("File not found or path is incorrect.")

# Convert the variable fileContents into all lowercase
fileContents = fileContents.lower()
# Remove all punctiuation and whatnot to focus only on words
cleanContent = re.sub(r'[^A-Za-z0-9 ]+', '', fileContents)

# Read in the contents of the stopWords.txt file into the variable: STOP_WORDS
file_path = Path('stop_Words.txt')
if file_path.is_file():
    with file_path.open('r') as file:
        STOP_WORDS = file.read().split()
        
sampleSentence = input("Enter a sample sentence: ")

# Split the sample sentence into a list of words
wordList = cleanContent.split()

# Create a dictionary named wordDict
wordDict = {}

for eachWord in wordList:
    # Skip words found in the STOP_WORDS list or words that are less than 4 or greater than 12 characters
    if eachWord in STOP_WORDS or len(eachWord) < 4 or len(eachWord) > 12:
        continue
    
    # If the word is not in the dictionary, add it with a count of 1
    if eachWord not in wordDict:
        wordDict[eachWord] = 1
    else:
        # If the word is already in the dictionary, increment its count
        wordDict[eachWord] += 1

# Create a pretty table named wordTable
wordTable = PrettyTable()
wordTable.field_names = ["WORD", "OCCURS"]

wordSort = sorted(wordDict.items(), key=lambda x:x[1])

wordSort.reverse()

# Add entries from wordDict to the table
for word, count in wordSort:
    wordTable.add_row([word, count])

print("Word Frequency Table:")

print(wordTable)



# Output the contents of the wordTable to a file
output_filename = "Output_file.txt"
with open(output_filename, 'w') as output_file:
    output_file.write(str(wordTable))
    
print(f"Word Frequency Table saved to '{output_filename}'.")
Functions/wordFrequency.py
green-dino/forensictools
import os
import stat
import time
import hashlib
import argparse
import csv
import logging

# Parse Command Line Arguments
# The script takes various command-line arguments for configuring its behavior, including specifying the hashing algorithm (MD5, SHA256, or SHA512), root path for hashing, and report path.

# WalkPath Function
# This function traverses the directory specified by the root path and calculates file hashes using the selected hashing algorithm. It also generates a CSV report containing file details and hash values.

# Validation Functions
# The script includes functions for validating directories (whether they exist, are readable, or writeable).

# HashFile Function
# This function calculates file hashes and collects file metadata such as size, timestamps, owner, and group. It supports MD5, SHA256, and SHA512 hashing algorithms.

# DisplayMessage Function
# A simple function to display messages (replace with your preferred logging method).

# _CSVWriter Class
# A class for writing data to a CSV file. It initializes the CSV file, writes rows of data, and closes the file.


log = logging.getLogger('main._pfish')

# Parse Command Line >>>

def ParseCommandLine():
    global gl_args
    global gl_hashtype

    parser = argparse.ArgumentParser('Python File sytem hashing p-fish')
    parser.add_argument('-v', '-verbose', help= 'progress messages', action='store_true')

    # group selection is mutually exclusive and required
    group = parser.add_mutually_exclusive_group(required=True)
    group.add_argument('--md5', help='Specifies MD5 ', action='store_true')
    group.add_argument('--sha256', help='Specifies SHA256', action='store_true')
    group.add_argument('--sha512', help='Specifices SHA 512 ', action='store_true')
    
    # path settings
    #parser.add_argument('-d', '--rootPath', type= ValidateDirectory, required=True, help="specify the root path for hashing")
    #parser.add_argument('-r', '--reportPath', type= ValidateDirectoryWriteable, required=True, help= "Specify the path for reports")

    parser.add_argument('-d', '--rootPath', type=str, required=True, help="specify the root path for hashing")
    parser.add_argument('-r', '--reportPath', type=str, required=True, help="Specify the path for reports")

    gl_args = parser.parse_args()


    if gl_args.md5:
        gl_hashtype ='MD5'
    elif gl_args.sha256:
        gl_hashtype='SHA256'
    elif gl_args.sha512:
        gl_hashtype='SHA512'
    else:
        gl_hashtype = 'Unknown'
    
   # logging.error('Unknown Hashtype')
   
    
# Parse Command Line <<<
def WalkPath():
    processCount = 0
    errorCount = 0

    log.info('Root Path:' + gl_args.rootPath)

    oCVS = _CSVWriter(gl_args.reportPath + 'fileSystemReport.csv', gl_hashtype)
    

    for root, dirs, files in os.walk(gl_args.rootPath):
        for file in files:
            fname = os.path.join(root,file)
            result = HashFile (fname, file, oCVS)

        #if successful increment count 
            if result is True:
                processCount +=1
        #if not successfull increament the errorcount   
        else:
            errorCount +=1


    oCVS.writerClose()
    return(processCount)

# Directory Validation >>>

def ValidateDirectory(theDir):
    #ensure path is a directory
    if not os.path.isdir(theDir):
        raise argparse.ArgumentTypeError('Directory does not exist')
    
    # Validate path is readable
    if os.access(theDir, os.R_OK):
        return theDir
    else:
        raise argparse.ArgumentTypeError('The Directory is not readable')
    

# Directory Validation <<<

#Directory Writable >>>

def ValidateDirectoryWriteable(theDir):
        #validate path is writable
    if os.access(theDir, os.W_OK):
        return theDir
    else:
        raise argparse.ArgumentTypeError('Directory not writeable')

#directory writeable <<<

#HashFile Function

def HashFile(theFile, simpleName, o_result):
    # Verify that the path is valid
    if not os.path.exists(theFile):
        raise FileNotFoundError('File does not exist: ' + theFile)

    # Verify that the path is not a symbolic link
    if os.path.islink(theFile):
        raise IsADirectoryError('Path is a symbolic link: ' + theFile)

    # Verify that the file is real
    if not os.path.isfile(theFile):
        raise IsADirectoryError('Not a regular file: ' + theFile)

    try:
        # Attempt to open the file
        with open(theFile, 'rb') as f:
            rd = f.read()
    except IOError:
        # If open fails, report the error
        raise IOError('Open Failed: ' + theFile)

    # Success, the file is open and we can read from it
    # File stats
    theFileStats = os.stat(theFile)
    (mode, ino, dev, nlink, uid, gid, size, atime, mtime, ctime) = os.stat(theFile)

    # Print the simple file name
    DisplayMessage("Processing File: " + theFile)

    # Print the size of the file in Bytes
    fileSize = str(size)

    # Print MAC Times
    modifiedTime = time.ctime(mtime)
    accessTime = time.ctime(atime)
    createdTime = time.ctime(ctime)
    ownerID = str(uid)
    groupID = str(gid)
    fileMode = bin(mode)

    # Process the file hashes
    if gl_args.md5:
        # Calculate and Print the MD5 hash
        hash = hashlib.md5()
        hash.update(rd)
        hexMD5 = hash.hexdigest()
        hashValue = hexMD5.upper()
    elif gl_args.sha256:
        # Calculate and Print the SHA256 hash
        hash = hashlib.sha256()
        hash.update(rd)
        hexSHA256 = hash.hexdigest()
        hashValue = hexSHA256.upper()
    elif gl_args.sha12:
        # Calculate and Print the SHA512 hash
        hash = hashlib.sha512()
        hash.update(rd)
        hexSHA512 = hash.hexdigest()
        hashValue = hexSHA512.upper()
    else:
        raise ValueError('Hash not Selected')

    # Write data to CSV
    o_result.writeRow([simpleName, theFile, fileSize])


# Function to display messages (replace with your preferred logging method)
def DisplayMessage(message):
    print(message)

class _CSVWriter:
    def __init__(self, fileName, hashType):
        try:
            # Construct the full path to the CSV file
            fullFilePath = os.path.join(gl_args.reportPath, fileName)
            self.csvFile = open(fullFilePath, 'w', newline='')
            # Additional initialization code here
            self.writer = csv.writer(self.csvFile)
            # delimiter =(',', quoting=csv.QUOTE_ALL)
            self.writer.writerow(('File', 'Path', 'Size'))
        except IOError:
            log.warning('Failed to open CSV file: ' + fullFilePath)

    def writeRow(self, rowData):
        try:
            self.writer.writerow(rowData)
        except IOError:
            log.warning('Failed to write to CSV File:' + self.csvFile.name)

    def writerClose(self):
        try:
            self.csvFile.close()
        except IOError:
            log.warning('Failed to close CSV file: ' + self.csvFile.name)



Modules/_pFish.py
green-dino/forensictools
# psearch support functions 
# CommandLine interface
#python your_script.py -k path_to_keyword_file.txt -t path_to_target_file.txt -m path_to_matrix_file.txt

#The script accepts command-line arguments to specify the keyword file, target file, and weight matrix file. 
#It then performs keyword searches within the target file, highlighting matches and providing offset information.
import argparse
import os
import logging
import sys

log = logging.getLogger('main._psearch')


#constants
MIN_WORD = 5 # min word size in bytes
MAX_WORD = 15 # max word size in bytes
PREDECESSOR_SIZE = 32 # values to print before match found
WINDOW_SIZE = 128  # values to dump when match 


# parse command function, uses argparse 

def ParseCommandLine():
    parser = argparse.ArgumentParser('Python Search')

    parser.add_argument('-v', '--verbose', help='enables the printing of additional program messages', action='store_true')
    parser.add_argument('-k', '--keyWords', type=ValidateFileRead,
                        required=True,help='Specify the file containing search words')
    parser.add_argument('-t','--srchTarget', type=ValidateFileRead,
                        required=True, help="specifiy the target file to search")
    parser.add_argument('-m','--theMatrix', type=ValidateFileRead,
                        required=True, help='Specify the weight matrix file')
    
    global gl_args
    gl_args = parser.parse_args()

    DisplayMessage('Command line processed: Successfully')

    return


#validate read function

def ValidateFileRead(theFile):
    #os path valid
    if not os.path.exists(theFile):
        raise argparse.ArgumentTypeError('File does not exist')
    
    #readable path
    if os.access(theFile, os.R_OK):
        return theFile
    else:
        raise argparse.ArgumentTypeError('File is not readable')

def DisplayMessage(msg):
    if gl_args.verbose:
        print(msg)
    return

# Search Words, use command line arguments, searches target for keywords



def SearchWords():
    #empty set of search words
    searchWords=set()
    try:
        fileWords = open (gl_args.keyWords)
        for line in fileWords:
            searchWords(line.strip())
    except:
        log.error('Keyword file failure:'+gl_args.keyWords)
        sys.exit()
    finally:
        fileWords.close()
    # log entry words to search for
    log.info('Search Words')
    log.info('Input File:'+gl_args.keyWords)
    log.info(searchWords)
       # Calculate the size of the target file
    sizeOfTarget = len(baTarget)

    baTargetCopy = class_Matrix

    # open and read the target file, load bytearray

    try:
        targetFile = open (gl_args.srchTarget, 'rb')
        baTarget = bytearray(targetFile.read())
    except:
        log.error('Target File Failure:'+ gl_args.srchTarget)
        sys.exit()
    finally:
        targetFile.close()
    # post to log

    log.info('Target of Search:'+gl_args.srchTarget)
    log.info('File Size:'+ str(sizeOfTarget))

    baTargetCopy = class_Matrix()

    #search loop
    #replace non characters with zero

    for i in range(0, sizeOfTarget):
        character = chr(baTarget[i])
        if not character.isalpha():
            baTarget[i] = 0
    
    # extract possible words from bytearray, inspect searchword list, 
    #create empty list of probable not found items

    indexOfWords = []
    cnt = 0
    for i in range(0, sizeOfTarget):
        character = chr(baTarget[i])
        if character.isalpha():
            cnt+=1
        else:
            if (cnt >=MIN_WORD and cnt <= MAX_WORD):
                newWord = ""
                for z in range(i-cnt,i):
                    newWord = newWord + chr(baTarget[z])
                newWord = newWord.lower()
                if (newWord in searchWords):
                        PrintBuffer(newWord, i-cnt, baTargetCopy, i- PREDECESSOR_SIZE, WINDOW_SIZE) 
                        indexOfWords.append([newWord, i-cnt])
                        cnt = 0
                        print
                else:
                    cnt = 0
    PrintAllWordsFound(indexOfWords)
    return
# hexidecimal / ASCII Page 

def  PrintHeading():
    print("offset 00 01 02 03 04 05 06 070 80 09 0A 0B 0C 0D 0E 0F ASCII")
    print("--------------------------------------------------------------")
    return

def PrintBuffer(word, direcOffset, buff, offset, hexSize):
    print("%08X  " % (direcOffset))
    PrintHeading()
    for i in range(0, 16):
        if i == 0:
            print("%08x" % i, end=' ')
        else:
            byteValue = buff[i + offset]
            print("%02x" % byteValue, end=' ')
    print("")
    for j in range (0,16):
        byteValue = buff[i+j]
        if (byteValue >=0x20 and byteValue <=0x7f):
            print("%c"%byteValue, end='')
        else:
            print('.', end=''),
    print('')
    return


def PrintAllWordsFound(wordList):
    print ("Index of all words")
    print("----------------------------")

    wordList.sort()

    for entry in wordList:
        print (entry)
    print ('---------------')
    print

    return

class class_Matrix:

    weightedMatrix = set()

    def __init__(self):
        try:
            fileTheMatrix = open(gl_args.theMatrix, 'rb')
            for line in fileTheMatrix:  # Added ':' to the for loop
                value = line.strip()
                self.weightedMatrix.add(int(value, 16))
        except:
            log.error('Matrix File Error' + gl_args.theMatrix)
            sys.exit()
        finally:
            fileTheMatrix.close()
Modules/_pSearch.py
green-dino/forensictools
import sys
import string

def load_search_words(file_path):
    search_words = set()
    try:
        with open(file_path) as fileWords:
            for line in fileWords:
                search_words.add(line.strip())
    except FileNotFoundError:
        print(f'The file {file_path} does not exist. Please create the file or add words to it.')
    except Exception as e:
        print('File Handling Error:', str(e))
    return search_words

# Word Frequency Analysis

def word_frequency_analysis(search_words):
    word_count = {}
    for word in search_words:
        # Remove punctuation and convert to lowercase for consistency
        cleaned_word = word.translate(str.maketrans('', '', string.punctuation)).lower()
        if cleaned_word in word_count:
            word_count[cleaned_word] += 1
        else:
            word_count[cleaned_word] = 1
    return word_count

while True:
    file_path = input('Enter the file path and name you want to search through: ')
    searchWords = load_search_words(file_path)

    if not searchWords:
        continue

    print(searchWords)

    search_type = input('Choose search type (exact/partial): ')
    word_to_search = input('Enter a word to search: ')

    if search_type == 'exact':
        if word_to_search.lower() in (word.lower() for word in searchWords):
            print('Found Word')
        else:
            print('Not found')
    elif search_type == 'partial':
        matching_words = [word for word in searchWords if word_to_search.lower() in word.lower()]
        if matching_words:
            print('Found Words:')
            for word in matching_words:
                print(word)
        else:
            print('No matches found')

    # Perform Word Frequency Analysis
    word_count = word_frequency_analysis(searchWords)
    print('Word Frequency Analysis:')
    for word, count in word_count.items():
        print(f'{word}: {count}')

    again = input('Do you want to search again? (yes/no): ')
    if again.lower() != 'yes':
        break

Modules/_searchWords.py
green-dino/forensictools
import os

# Define the directory tree structure this get_started sets the framework for a Flask App for quick locally hosted locally processed data 
directory_tree = {
    'my_project': {
        'app': {
            'templates': {
                'index.html': '',
                'about.html': '',
                'contact.html': '',
            },
            'static': {
                'css': {
                    'style.css': '',
                    'responsive.css': '',
                },
                'js': {
                    'script.js': '',
                    'jquery.js': '',
                },
                'img': {
                    'logo.png': '',
                    'banner.jpg': '',
                    'icon.png': '',
                },
            },
            'app.py': '',
            'config.py': '',
            'models.py': '',
        },
        'data': {
            'data.csv': '',
            'logs.txt': '',
        },
        'docs': {
            'readme.md': '',
            'documentation.pdf': '',
        },
        'tests': {
            'test_utils.py': '',
            'test_models.py': '',
            'test_views.py': '',
        },
        'requirements.txt': '',
        'README.md': '',
        'LICENSE': '',
    }
}
# Function to create the directory tree
def create_directory_tree(base_path, tree):
    for name, contents in tree.items():
        path = os.path.join(base_path, name)
        if isinstance(contents, dict):
            if not os.path.exists(path):
                os.makedirs(path)
            create_directory_tree(path, contents)
        elif contents:
            with open(path, 'w') as file:
                file.write(contents)

# Prompt the user for the base directory
base_directory = input("Enter the base directory where you want to create the directory tree: ")

# Check if the specified directory exists
if not os.path.exists(base_directory):
    print(f"Error: The specified directory '{base_directory}' does not exist.")
else:
    # Create the directory tree
    create_directory_tree(base_directory, directory_tree)
    print(f"Directory tree created at {base_directory}")
Modules/get_started.py
green-dino/forensictools
# Python word searcher 

import logging 
import time
import _pSearch

if __name__ == '_main_':
    Version = '1.0'
    logging.basicConfig(filename='pSearchLog.log', level=logging.DEBUG, format='%(asctime)s%(messages)s')

# proccess command line args
_pSearch.ParseCommandLine()

log = logging.getLogger('main._psearch')
log.info("p-search started")

# record start time
startTime = time.time()

# perform keyword search
_pSearch.SearchWords()

# record Ending time

endTime = time.time()
duration = endTime - startTime

logging.info('Elapsed Time: '+ str(duration)+ 'seconds')
logging.info('')
logging.info('Program Terminated Normally')



Modules/pSearch.py
green-dino/forensictools
#pfish- python File System Hash program 

import logging
import time
import sys
import _pFish # support function module 

if __name__=='__main__':
    PFISH_Version='1.0'
    #turn on logging

logging.basicConfig(filename='pFishLog.log',level=logging.DEBUG, format='%(asctime)s%(message)s')   

# Post Start scan message to log 
logging.info('Welcome to p-fish v 1.0 ... New Scan Started')

# Record System Information
logging.info('System:'+sys.platform)
logging.info('Version: '+sys.version)


# Process Command Line Args 
_pFish.ParseCommandLine()

# Record Start time 
startTime = time.time()


# Traverse file systems and Hash files
filesProcessed = _pFish.WalkPath()

# Duration 
endTime = time.time()
duration = endTime - startTime

logging.info('Files Processed:' + str(filesProcessed))
logging.info('Elapsed Time: ' + str(duration)+'seconds')
logging.info('Program Termingated Normally')

Modules/pfish.py
green-dino/forensictools
#understanding conditional loops

while True:
    x = float(input('value for x:'))
    y = float(input('value for y:'))
    z = float(input('value for z:'))

    if x == y:
        print('x is equal to y')
    elif x == z:
        print ('x equals z')
    else:
        print('try again')
    
    play_again = input('play again? (y/n):')
    if play_again.lower() != 'y':
        break
examples.py
green-dino/forensictools