c2servers/scripts/exportcsdata.py (143 lines of code) (raw):

#!/usr/bin/python3 # -*- coding: utf-8 -*- # # Part of RedELK # Script to parse Cobalt Strike data in .bin files # # Author: Outflank B.V. / Marc Smeets # Shameless copy-paste-modify from original script "export_TSv.py" from Alyssa @ramen0x3f (https://github.com/ramen0x3f/AggressorScripts/blob/master/export_TSv.py) # from argparse import ArgumentParser, RawTextHelpFormatter from javaobj import loads from os import path from sys import argv from pprint import pprint def print_tsv(data_type, data, prefix): with open(prefix + "_" + data_type + ".tsv", "w") as output_file: ## Cred-it where it's due if data_type == "credentials": print("[+] Parsing credentials") print( "#User\tPassword/Hash\tExtracted from\tExtracted via", file=output_file ) for d in data: print( "{}\\{}\t{}\t{}\t{}".format( d["realm"], d["user"], d["password"], d["host"], d["source"] ), file=output_file, ) print("[+] Completed parsing credentials") ## Listen here, pal elif data_type == "listeners": print("[+] Parsing listeners") print( "#Listener name\tHost\tPort\tBeacons\tListener type\tPort bind\tC2 Profile\tProxy", file=output_file, ) for d in data: name = d["name"] if "name" in d else "" host = d["host"] if "host" in d else "" port = d["port"] if "port" in d else "" beacons = d["beacons"] if "beacons" in d else "" payload = d["payload"] if "payload" in d else "" bindto = d["bindto"] if "bindto" in d else "" profile = d["profile"] if "profile" in d else "" proxy = d["proxy"] if "proxy" in d else "" print( "{}\t{}\t{}\t{}\t{}\t{}\t{}\t{}".format( name, host, port, beacons, payload, bindto, profile, proxy ), file=output_file, ) print("[+] Completed parsing listeners") ## (ob)Session. By Calvin Klein. elif data_type == "sessions": print("[+] Parsing sessions") print( "#Hostname\tInternal IP\tExternal IP\tUser (beacon running as)\tDate/Time session created\tOS Version\tNote", file=output_file, ) for d in data: print( "{}\t{}\t{}\t{}\t{}\t{} {}\t{}".format( d["computer"], d["host"], d["external"], d["user"], d["opened"], d["os"], d["ver"], d["note"], ), file=output_file, ) print("[+] Completed parsing sessions") ## Better than Walmart elif data_type == "targets": print("[+] Parsing targets") print("#Hostname\tIP Address\tOS Version", file=output_file) for d in data: print( "{}\t{}\t{} {}".format( d["name"], d["address"], d["os"], d["version"] ), file=output_file, ) print("[+] Completed parsing targets") ## Don't loose control elif data_type == "c2info": print("[+] Parsing c2info") print("#Beacon ID\tDomains\tPort\tProtocol", file=output_file) for d in data: bid = d["bid"] if "bid" in d else "" domains = d["domains"] if "domains" in d else "" port = d["port"] if "port" in d else "" proto = d["proto"] if "proto" in d else "" print( "{}\t{}\t{}\t{}".format(bid, domains, port, proto), file=output_file ) print("[+] Completed parsing c2info") ## If you fail this badly, I'm impressed. else: print("[!] Invalid data type chosen") if __name__ == "__main__": parser = ArgumentParser( description="Export TSVs of data from Teamserver data/*.bins" ) ## For arguments sake parser.add_argument( "--credentials", type=str, help="Provide a credentials.bin file" ) parser.add_argument("--listeners", type=str, help="Provide a listeners.bin file") parser.add_argument("--sessions", type=str, help="Provide a sessions.bin file") parser.add_argument("--targets", type=str, help="Provide a targets.bin file") parser.add_argument("--c2info", type=str, help="Provide a c2info.bin file") parser.add_argument( "--prefix", type=str, help='Prefix for TSV files. Default is "export".' ) ## This script is like life. You get out of it what you put into it. if len(argv) == 1: parser.print_help() exit() ## Lazy people get lazy filenames args = parser.parse_args() prefix = args.prefix if args.prefix else "export" ## BINgo was his name-o try: print("[+] Export time!") if args.credentials and path.exists(args.credentials): print_tsv( "credentials", [d for k, d in loads(open(args.credentials, "rb").read()).items()], prefix, ) if args.listeners and path.exists(args.listeners): print_tsv( "listeners", [d for k, d in loads(open(args.listeners, "rb").read()).items()], prefix, ) if args.sessions and path.exists(args.sessions): print_tsv( "sessions", [d for k, d in loads(open(args.sessions, "rb").read()).items()], prefix, ) if args.targets and path.exists(args.targets): print_tsv( "targets", [d for k, d in loads(open(args.targets, "rb").read()).items()], prefix, ) if args.c2info and path.exists(args.c2info): print_tsv( "c2info", [d for k, d in loads(open(args.c2info, "rb").read()).items()], prefix, ) except: print( "[!] Something went wrong, but I'm too lazy to put in more validation. Check your input files or whatever." )