Malware re-purposing with PowerShell reflection

The code demonstrates how to load and interact with a .NET assembly dynamically.

# define and compile a .NET asembly
Add-Type -TypeDefinition @'
using System;
using System.Diagnostics;

// this is the bening class
namespace TotesNotMalware {
    public class NothingToSeeHere {
        public static void Main(string[] args) {
            Console.WriteLine("Hello, benign world!");
        }
    }

	// this is the malicious class that runs calc.exe
	// when a condition is met
    internal class TotallyMalicious {
        internal static int secretC2Password = 1094795585;

        private string ExecuteCommandAndSendToC2(int password) {
            if ((password ^ secretC2Password) == 1296911693L) {
                Process process = new Process();
                ProcessStartInfo startInfo = new ProcessStartInfo();
                startInfo.FileName = "calc.exe";
                process.StartInfo = startInfo;
                process.Start();

                return "done";
            }

            return null;
        }
    }
}
'@ -OutputAssembly BenignHelloWorldNothingToSeeHere.exe

# convert a base64-encoded .NET assembly back into bytes
# and load the assmebly into memory
$EncodedHelloWorld = '<BASE64_STRING>'
$HelloWorldAssemblyBytes = [Convert]::FromBase64String($EncodedHelloWorld)
$HelloWorldAssembly = [System.Reflection.Assembly]::Load($HelloWorldAssemblyBytes)

# get a reference to the TotallyMalicious class
$TotallyMaliciousClass = $HelloWorldAssembly.GetType('TotesNotMalware.TotallyMalicious')

# create an instance of the `TotallyMalicious` class using `Activator.CreateInstance`
$TotallyMaliciousObject = [System.Activator]::CreateInstance($TotallyMaliciousClass)

# retrieves the value of the internal static field `secretC2Password`
$Password1 = $TotallyMaliciousClass.GetField('secretC2Password', [Reflection.BindingFlags] 'NonPublic, Static').GetValue($null)

# derives a password by XORing the retrieved password with `1296911693`
$DerivedPassword = $Password1 -bxor 1296911693

# gets a reference to the private method `ExecuteCommandAndSendToC2`
$ExecuteCommandAndSendToC2 = $TotallyMaliciousClass.GetMethod('ExecuteCommandAndSendToC2', [Reflection.BindingFlags] 'NonPublic, Instance')

# invokes the private method `ExecuteCommandAndSendToC2` with the derived password, causing it to start `calc.exe`
$ExecuteCommandAndSendToC2.Invoke($TotallyMaliciousObject, [Object[]] @($DerivedPassword))

Resources:

Last updated