Files
benpturner f094da4c35 Fixed fpc
2024-11-24 10:40:57 +00:00

105 lines
3.6 KiB
Python

#!/usr/bin/env python3
import argparse
import sqlite3 # For SQLite raw connection
import sys
from sqlalchemy import create_engine, text
import pandas as pd
class Colours:
BLUE = '\033[94m'
GREEN = '\033[92m'
RED = '\033[91m'
END = '\033[0m'
YELLOW = '\033[93m'
def create_arg_parser():
parser = argparse.ArgumentParser(description='Find Posh Command - Search for a PoshC2 Command Output')
parser.add_argument("-p", "--project", help="The PoshC2 project directory", default="/opt/PoshC2_Project")
parser.add_argument("-d", "--database_type", help="The database type (SQLite/PostgreSQL)", default="SQLite")
parser.add_argument("-pg", "--postgres_string", help="The PostgreSQL connection string (if using PostgreSQL)", default="")
parser.add_argument("-c", "--command", help="The command to search for", default="%")
parser.add_argument("-u", "--user", help="The user to filter on", default="%")
parser.add_argument("-o", "--output", help="The output to search for", default="%")
parser.add_argument("-t", "--taskid", help="The task ID to search for", default="%")
return parser
def get_database_connection(args):
"""
Returns a raw DBAPI connection depending on the database type.
"""
if args.database_type.lower() == "postgresql":
try:
import psycopg2
connection = psycopg2.connect(args.postgres_string)
return connection
except Exception as e:
print(f"{Colours.RED}[-] Failed to connect to PostgreSQL: {e}{Colours.END}")
sys.exit(1)
else:
try:
db_path = f"{args.project}/PoshC2.SQLite"
connection = sqlite3.connect(db_path)
return connection
except Exception as e:
print(f"{Colours.RED}[-] Failed to connect to SQLite: {e}{Colours.END}")
sys.exit(1)
def main():
args = create_arg_parser().parse_args()
# Check for minimum search criteria
if args.command == '%' and args.output == '%' and args.taskid == '%':
print(f"{Colours.RED}[-] A minimum of a --command, --taskid, or --output search term must be specified.{Colours.END}")
sys.exit(1)
# Get a raw database connection
connection = get_database_connection(args)
# Define the SQL query with parameterization
sql_query = """
SELECT sent_time, completed_time, user, command, output, id
FROM tasks
WHERE user LIKE ?
AND command LIKE ?
AND output LIKE ?
AND CAST(id as text) LIKE ?;
"""
# Define query parameters
params = (
f"%{args.user}%",
f"%{args.command}%",
f"%{args.output}%",
f"%{args.taskid}%"
)
# Execute the query
try:
with pd.option_context('display.max_rows', None, 'display.max_columns', None, 'display.max_colwidth', None):
output = pd.read_sql_query(sql_query, con=connection, params=params)
except Exception as e:
print(f"{Colours.RED}[-] Failed to execute query: {e}{Colours.END}")
sys.exit(1)
finally:
connection.close()
# Display the results
if output.empty:
print(f"{Colours.YELLOW}[!] No results found for the given criteria.{Colours.END}")
else:
for entry in output.itertuples(index=False):
print(f"\n{Colours.GREEN}[*][*][*] Task {entry.id:05d} Command (Issued: {entry.sent_time} by {entry.user}):{Colours.END}")
print(entry.command)
print(f"\n{Colours.BLUE}[*][*][*] Task {entry.id:05d} Output (Completed: {entry.completed_time}):{Colours.END}")
print(entry.output)
print()
if __name__ == '__main__':
main()