-
-
Save t94j0/c60662ed322775a515bdda52427a3ee5 to your computer and use it in GitHub Desktop.
cs2satellite.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
## Title: cs2satellite.py | |
## Author: Max Harley | |
## Description: Converts Cobalt Strike profiles to satellite .info file format | |
## Based on a project by: Joe Vest, Andrew Chiles | |
import argparse | |
import sys | |
import re | |
description = ''' | |
Converts Cobalt Strike profiles to satellite .info file format by using the User-Agent and URI Endpoint to create rewrite rules. Make sure the profile passes a c2lint check before running this script. | |
''' | |
parser = argparse.ArgumentParser(description=description) | |
parser.add_argument('-i', dest='inputfile', | |
help='C2 Profile file', required=True) | |
parser.add_argument('-c', dest='c2server', | |
help='C2 Server (http://teamserver)', required=True) | |
parser.add_argument('-r', dest='redirect', | |
help='Redirect to this URL (http://google.com)', required=True) | |
args = parser.parse_args() | |
# Make sure we were provided with vaild URLs | |
# https://stackoverflow.com/questions/7160737/python-how-to-validate-a-url-in-python-malformed-or-not | |
regex = re.compile( | |
r'^(?:http|ftp)s?://' # http:// or https:// | |
# domain... | |
r'(?:(?:[A-Z0-9](?:[A-Z0-9-]{0,61}[A-Z0-9])?\.)+(?:[A-Z]{2,6}\.?|[A-Z0-9-]{2,}\.?)|' | |
r'localhost|' # localhost... | |
r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3})' # ...or ip | |
r'(?::\d+)?' # optional port | |
r'(?:/?|[/?]\S+)$', re.IGNORECASE) | |
if re.match(regex, args.c2server) is None: | |
parser.print_help() | |
print("[!] c2server is malformed. Are you sure {} is a valid URL?".format( | |
args.c2server)) | |
sys.exit(1) | |
if re.match(regex, args.redirect) is None: | |
parser.print_help() | |
print("[!] redirect is malformed. Are you sure {} is a valid URL?".format( | |
args.redirect)) | |
sys.exit(1) | |
profile = open(args.inputfile, "r") | |
contents = profile.read() | |
# Strip all single line comments (#COMMENT\n) from profile before searching so it doens't break our crappy parsing | |
contents = re.sub(re.compile("#.*?\n"), "", contents) | |
# Search Strings | |
ua_string = "set useragent" | |
http_get = "http-get" | |
http_post = "http-post" | |
set_uri = "set uri " | |
http_stager = "http-stager" | |
set_uri_86 = "set uri_x86" | |
set_uri_64 = "set uri_x64" | |
# Errors | |
errorfound = False | |
errors = "\n##########\n[!] ERRORS\n" | |
# Get UserAgent | |
if contents.find(ua_string) == -1: | |
ua = "" | |
errors += "[!] User-Agent Not Found\n" | |
errorfound = True | |
else: | |
ua_start = contents.find(ua_string) + len(ua_string) | |
ua_end = contents.find("\n", ua_start) | |
ua = contents[ua_start:ua_end].strip()[1:-2] | |
# Get HTTP GET URIs | |
http_get_start = contents.find(http_get) | |
if contents.find(set_uri) == -1: | |
get_uri = "" | |
errors += "[!] GET URIs Not Found\n" | |
errorfound = True | |
else: | |
get_uri_start = contents.find(set_uri, http_get_start) + len(set_uri) | |
get_uri_end = contents.find("\n", get_uri_start) | |
get_uri = contents[get_uri_start:get_uri_end].strip()[1:-2] | |
# Get HTTP POST URIs | |
http_post_start = contents.find(http_post) | |
if contents.find(set_uri) == -1: | |
post_uri = "" | |
errors += "[!] POST URIs Not Found\n" | |
errorfound = True | |
else: | |
post_uri_start = contents.find(set_uri, http_post_start) + len(set_uri) | |
post_uri_end = contents.find("\n", post_uri_start) | |
post_uri = contents[post_uri_start:post_uri_end].strip()[1:-2] | |
# Get HTTP Stager URIs x86 | |
http_stager_start = contents.find(http_stager) | |
if contents.find(set_uri_86) == -1: | |
stager_uri_86 = "" | |
errors += "[!] x86 Stager URIs Not Found\n" | |
errorfound = True | |
else: | |
stager_uri_start = contents.find( | |
set_uri_86, http_stager_start) + len(set_uri_86) | |
stager_uri_end = contents.find("\n", stager_uri_start) | |
stager_uri_86 = contents[stager_uri_start:stager_uri_end].strip()[1:-2] | |
# Get HTTP Stager URIs x64 | |
http_stager_start = contents.find(http_stager) | |
if contents.find(set_uri_64) == -1: | |
stager_uri_64 = "" | |
errors += "[!] x64 Stager URIs Not Found\n" | |
errorfound = True | |
else: | |
stager_uri_start = contents.find( | |
set_uri_64, http_stager_start) + len(set_uri_64) | |
stager_uri_end = contents.find("\n", stager_uri_start) | |
stager_uri_64 = contents[stager_uri_start:stager_uri_end].strip()[1:-2] | |
# Create URIs list | |
get_uris = get_uri.split() | |
post_uris = post_uri.split() | |
stager86_uris = stager_uri_86.split() | |
stager64_uris = stager_uri_64.split() | |
# Remove duplicate URIs | |
temp_uris = get_uris + post_uris + stager86_uris + stager64_uris | |
uris = list(set(temp_uris)) | |
# Create URI string in modrewrite syntax. "*" are needed in REGEX to support GET parameters on the URI | |
uris_string = ".*|".join(uris) + ".*" | |
uri_template = ''' | |
- path: {path} | |
authorized_useragents: | |
- {ua} | |
proxy: {c2server} | |
on_failure: | |
redirect: {redirect} | |
''' | |
all_paths = [uri_template.format( | |
path=uri, ua=ua, c2server=args.c2server, redirect=args.redirect) for uri in uris] | |
print('########### .proxy.yml ###########') | |
print('\n'.join(all_paths)) | |
print("#### Save the following as .proxy.yml in the root web directory") | |
# Print Errors Found | |
if errorfound: | |
print(errors) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment