From 4ea637c34b1619f944338057940cccf8eaa1826a Mon Sep 17 00:00:00 2001 From: Ada Isopods Date: Thu, 15 May 2025 02:47:23 -0600 Subject: Multiple verbosity settings. No way to increase verbosity yet --- cowrieder.py | 113 +++++++++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 82 insertions(+), 31 deletions(-) (limited to 'cowrieder.py') diff --git a/cowrieder.py b/cowrieder.py index 0518df6..267d97e 100644 --- a/cowrieder.py +++ b/cowrieder.py @@ -3,52 +3,103 @@ import sys import random import os -if not 0 <= 1 < len(sys.argv): +def ccgen(seed=""): # Color code generator + if(not os.isatty(1)): # Do not output color code at all if output is not a TTY that can accept them + return "" + if(seed and seed != "reset" and seed != "RESET"): # If seed is provided, use it to generate a color. Return color reset code otherwise or if seed is the word "reset" + random.seed(seed) + return "\x1b[38;2;{r};{g};{b}m".format(r=random.randrange(50, 256), g=random.randrange(50, 256), b=random.randrange(50, 256)) + return "\x1b[0m" + +if not 0 <= 1 < len(sys.argv): # TODO: integrate argparse print("Provide a path to a Cowrie JSON log file") exit() filepath = sys.argv[1] + +verbosity = 0 entries = [] -sessions = [] +sessions = {} session_ips = {} +session_timestamps = {} +session_durations = {} +session_ran_command = {} +session_successful_login = {} with open(filepath, "r") as logfile: for line in logfile: entry = json.loads(line) entries.append(entry) - session = entry['session'] - if(session not in sessions): - sessions.append(session) - session_ips.update({session: entry['src_ip']}) + session_id = entry['session'] + + if(session_id not in sessions): + sessions.update({session_id: [entry]}) + session_ips.update({session_id: entry['src_ip']}) + else: + sessions[session_id].append(entry) + + if(entry["eventid"] == "cowrie.session.connect" and session_id not in session_timestamps): # Save the timestamp of the session's initial connection + session_timestamps.update({session_id: entry['timestamp']}) + + if(entry["eventid"] == "cowrie.session.closed" and session_id not in session_durations): # Save the session's duration + session_durations.update({session_id: entry['duration']}) + + if(entry["eventid"] == "cowrie.command.input" and session_id not in session_ran_command): # Save whether any commands were run during the session + session_ran_command.update({session_id: True}) + + if(entry["eventid"] == "cowrie.login.success" and session_id not in session_successful_login): # Save if login was a success + session_successful_login.update({session_id: True}) + + if(entry["eventid"] == "cowrie.login.failed" and session_id not in session_successful_login): # Save if login failed + session_successful_login.update({session_id: False}) + + if(entry["eventid"] == "cowrie.login.success" and session_id in session_successful_login): # Save if login succeeded after failing + session_successful_login[session_id] = True filter_ip = "" if 0 <= 2 < len(sys.argv): filter_ip = sys.argv[2] -cc_session = "" -cc_ip = "" -cc_reset = "" -outpipe = os.isatty(1) - -for session in sessions: - ip = session_ips[session] - if(ip == filter_ip or not filter_ip): - if(outpipe): - random.seed(session) - sr = random.randrange(50, 256) - sg = random.randrange(50, 256) - sb = random.randrange(50, 256) - random.seed(ip) - ir = random.randrange(50, 256) - ig = random.randrange(50, 256) - ib = random.randrange(50, 256) - cc_reset = "\x1b[0m" - cc_session = "\x1b[38;2;{r};{g};{b}m".format(r=sr, g=sg, b=sb) - cc_ip = "\x1b[38;2;{r};{g};{b}m".format(r=ir, g=ig, b=ib) - - print("\n--- Session " + cc_session + session + cc_reset + " from " + cc_ip + session_ips[session] + cc_reset +" ---") - for entry in entries: - if(entry['session'] == session): + +if(verbosity == 1): # Verbose mode: print timestamp, event type and message (if applicable) for every event. I could probably do better but I'm lazy + for session_id in sessions: + ip = session_ips[session] + if(ip == filter_ip or not filter_ip): + print("\n--- Session " + ccgen(session_id) + session_id + ccgen() + " from " + ccgen(ip) + session_ips[session_id] + ccgen() +" ---") + for entry in sessions[session_id]: if(entry['message']): eventid = entry['eventid'] print(entry["timestamp"] + " > " + eventid + (" " * (29 - len(eventid))) + ": " + entry['message']) else: - print(entry["timestamp"] + " > " + entry['eventid']) \ No newline at end of file + print(entry["timestamp"] + " > " + entry['eventid']) + +elif(verbosity == 2): # Maximum verbosity: basically just pretty print the now-sorted-by-session logs + print(json.dumps(sessions, indent=4)) + +else: # Default verbosity: just the good stuff + for session_id in sessions: + ip = session_ips[session_id] + timestamp = session_timestamps[session_id][:22].replace("T", " ") + if(session_id not in session_successful_login): + print(timestamp + " > Ping from " + ccgen(ip) + ip + ccgen() + " lasting " + session_durations[session_id] + "s") + elif(not session_successful_login[session_id]): + cred_combos = [] + for entry in sessions[session_id]: + if(entry["eventid"] == "cowrie.login.failed"): + cred_combos.append((entry["username"], entry["password"])) + print(timestamp + " > Failed login attempt from " + ccgen(ip) + ip + ccgen() + " with credentials " + str(cred_combos)) + elif(session_id in session_ran_command): + print(timestamp + " > Session from " + ccgen(ip) + ip + ccgen() + ":") + for entry in sessions[session_id]: + match(entry["eventid"]): + case "cowrie.login.failed": + print(" | Failed login attempt: " + entry["username"] + "/" + entry["password"]) + case "cowrie.login.success": + print(" | Successful login: " + entry["username"] + "/" + entry["password"]) + case "cowrie.command.input": + print(" | CMD: " + entry["input"]) + print(" \ Disconnected after " + session_durations[session_id] + "s") + else: + cred_combos = [] + for entry in sessions[session_id]: + if(entry["eventid"] == "cowrie.login.failed" or entry["eventid"] == "cowrie.login.success"): + cred_combos.append((entry["username"], entry["password"])) + print(timestamp + " > Successful login from " + ccgen(ip) + ip + ccgen() + " with credentials " + str(cred_combos)) -- cgit v1.2.3