aboutsummaryrefslogtreecommitdiff
path: root/cowrieder.py
diff options
context:
space:
mode:
authorAda Isopods <me@bathynomus.xyz>2025-05-15 02:47:23 -0600
committerAda Isopods <me@bathynomus.xyz>2026-10-21 23:04:19 -0600
commit4ea637c34b1619f944338057940cccf8eaa1826a (patch)
treeee4928cde4ab973384b51fcdf22bc823d422b3e1 /cowrieder.py
parent22502a6dc24f546227592a20110b39f3647bca39 (diff)
Multiple verbosity settings. No way to increase verbosity yet
Diffstat (limited to 'cowrieder.py')
-rw-r--r--cowrieder.py113
1 files changed, 82 insertions, 31 deletions
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))