
श्वेतपत्र
TL;DR: यह PoC एक 3‑चरणीय संरचित अपवाद हैंडलिंग (SEH) कैस्केड प्रदर्शित करता है जो जानबूझकर गलत संरेखण (misaligned execution) के कारण कच्चे बाइट ब्लॉब्स में होता है, जिसका पहला वैध निर्देश शून्य भाजक के साथ दोषपूर्ण
div regहै।
प्रत्येक अपवाद चरण अगला SEH हैंडलर स्थापित करता है, एक नया गलत संरेखित शून्य-से-विभाजन ट्रिगर करता है, और एक सौम्य अवलोकनीय पेलोड निष्पादित करता है, इससे पहले कि मूल SEH श्रृंखला को पुनर्स्थापित कर सफाई से समाप्त हो।
MOEW (Misaligned Opcode Exception Waterfall) एक रक्षात्मक अनुसंधान नमूना है जो x86/Wow64 विंडोज़ पर नियंत्रित अपवाद-संचालित बहु-चरणीय निष्पादन प्रदर्शित करता है। यह प्रदर्शित करता है:
fs:[0] के माध्यम से मैन्युअल SEH श्रृंखला हेरफेरblob1, blob2, blob3) में जानबूझकर गलत संरेखणKiUserExceptionDispatcherRtlDispatchExceptionसभी पेलोड सौम्य हैं:
%TEMP% में एक मार्कर फ़ाइल लिखता हैPoC जानबूझकर निष्क्रिय किया गया है। कोई डेटा एन्क्रिप्टेड, संशोधित या नष्ट नहीं किया गया है।
ECX/EDX/EBX = 0) पर गलत संरेखित divORIGINAL_SEH) का पूर्ण पुनर्स्थापनPoC केवल नाइटली-विशेष सुविधाओं का उपयोग करता है:
#![feature(asm_experimental_arch)]
#![feature(naked_functions)]
आवश्यक घटकों को स्थापित करें:
rustup toolchain install nightly
rustup target add i686-pc-windows-msvc --toolchain nightly
चूंकि PoC कस्टम SEH हैंडलर स्थापित करता है जो SAFESEH तालिका में मौजूद नहीं हैं, लिंकर को SAFESEH सत्यापन अक्षम करने का निर्देश दिया जाना चाहिए।
.cargo/config.toml बनाएँ:
[target.i686-pc-windows-msvc]
rustflags = [
"-C", "link-arg=/SAFESEH:NO",
]
बाइनरी बनाएँ:
cargo +nightly build --target i686-pc-windows-msvc --release
आउटपुट यहाँ स्थित है:
target\i686-pc-windows-msvc\release\seh_waterfall.exe
निष्पादित करें:
seh_waterfall.exe
अपेक्षित नियंत्रण-प्रवाह:
चरण 0 → गलत संरेखित blob1 → चरण 1 हैंडलर
चरण 1 → गलत संरेखित blob2 → चरण 2 हैंडलर
चरण 2 → गलत संरेखित blob3 → अंतिम हैंडलर
अंतिम → SEH पुनर्स्थापित करें → बाहर निकलें
दृश्यमान कलाकृतियाँ:
%TEMP%\moew_stage2.txt बनाया जाता है (चरण 2)32-बिट विंडोज़ पर, SEH रिकॉर्ड fs:[0] पर संग्रहीत एक लिंक्ड सूची बनाते हैं:
#[repr(C)]
struct SehRec {
next: *mut SehRec,
handler: usize,
}
प्रत्येक हैंडलर मानक SEH हस्ताक्षर का उपयोग करता है:
extern "system" fn handler(
record: *mut u8,
frame: *mut u8,
context: *mut u8,
dispatcher: *mut u8,
) -> i32
static STAGE_COUNTER: AtomicU32 = AtomicU32::new(0);
static mut ORIGINAL_SEH: *mut SehRec = std::ptr::null_mut();
इसके लिए उपयोग किया जाता है:
fs:[0] को ORIGINAL_SEH के रूप में सहेजें।fs:[0] को इस नए रिकॉर्ड से अधिलेखित करें।blob1 + 5 में गलत संरेखित करें, जो div ecx के रूप में डीकोड होता है (ECX = 0 सेट करने के बाद)।notepad.exe लॉन्च करें।blob2 + 3 में गलत संरेखित करें → div edx (EDX = 0 के साथ)।%TEMP%\moew_stage2.txt लिखें।blob3 + 3 में गलत संरेखित करें → div ebx (EBX = 0 के साथ)।calc.exe लॉन्च करें।ORIGINAL_SEH को fs:[0] में पुनर्स्थापित करें।process::exit(0) के माध्यम से प्रक्रिया को सफाई से बाहर निकालें।blob1#[unsafe(naked)]
pub extern "C" fn blob1() {
naked_asm! {
".byte 0xB8, 0x10, 0x00, 0x00, 0x00", // mov eax, 0x10
".byte 0xF7, 0xF1", // div ecx
".byte 0xC3", // ret
".byte 0x90, 0x90, 0x90", // nop padding
}
}
mov eax, 0x10; div ecx; ret+5 पर गलत संरेखित: div ecx (ECX = 0 → #DE)blob2#[unsafe(naked)]
pub extern "C" fn blob2() {
naked_asm! {
".byte 0x55", // push ebp
".byte 0x8B, 0xEC", // mov ebp, esp
".byte 0xF7, 0xF2", // div edx
".byte 0xC3", // ret
".byte 0x90, 0x90, 0x90", // nop padding
}
}
push ebp; mov ebp, esp; div edx; ret+3 पर गलत संरेखित: div edx (EDX = 0 → #DE)blob3#[unsafe(naked)]
pub extern "C" fn blob3() {
naked_asm! {
".byte 0x53", // push ebx
".byte 0x8B, 0xD8", // mov ebx, eax
".byte 0xF7, 0xF3", // div ebx
".byte 0xC3", // ret
".byte 0x90, 0x90, 0x90", // nop padding
}
}
push ebx; mov ebx, eax; div ebx; ret+3 पर गलत संरेखित: div ebx (EBX = 0 → #DE)प्रत्येक दोषपूर्ण चरण विंडोज़ उपयोगकर्ता-मोड अपवाद पाइपलाइन में पुनः प्रवेश करता है:
KiUserExceptionDispatcher
→ RtlDispatchException
→ SEH श्रृंखला वॉक (fs:[0])
→ MOEW हैंडलर
विशिष्ट डीबगर दृश्य:
seh_waterfall!blobX+offset
ntdll!KiUserExceptionDispatcher
ntdll!RtlDispatchException
seh_waterfall!stageN_handler
वॉटरफॉल पूरी तरह से वास्तविक हार्डवेयर दोषों और SEH डिस्पैच द्वारा संचालित है; कोई सिंथेटिक या नकली अपवाद उपयोग नहीं किए गए हैं।
चरण 2 में लिखी गई फ़ाइल इस प्रकार दिखती है:
MOEW चरण 2 मार्कर
-------------------
यह फ़ाइल चरण 2 SEH हैंडलर द्वारा एक सौम्य प्रदर्शन पेलोड के रूप में लिखी गई थी।
%TEMP% में इसकी उपस्थिति एक सरल, अवलोकनीय प्रमाण के रूप में कार्य करती है कि चरण 2 SEH श्रृंखला के माध्यम से निष्पादित हुआ।
संभावित विस्तारों में शामिल हैं:
पूर्ण PoC कार्यान्वयन इस भंडार में उपलब्ध है (src/main.rs देखें)।
यह परियोजना रक्षात्मक अनुसंधान और शिक्षा के लिए है। कॉपीराइट <2025>
इसके द्वारा, किसी भी व्यक्ति को जो इस सॉफ्टवेयर और संबंधित दस्तावेज़ फ़ाइलों ("सॉफ्टवेयर") की एक प्रति प्राप्त करता है, बिना किसी प्रतिबंध के सॉफ्टवेयर में व्यवहार करने की अनुमति दी जाती है, जिसमें बिना किसी प्रतिबंध के सॉफ्टवेयर की प्रतियां उपयोग करने, कॉपी करने, संशोधित करने, विलय करने, प्रकाशित करने, वितरित करने, उप-लाइसेंस देने और/या बेचने के अधिकार शामिल हैं, और ऐसे व्यक्तियों को ऐसा करने की अनुमति दी जाती है, बशर्ते निम्नलिखित शर्तें पूरी हों:
उपरोक्त कॉपीराइट नोटिस और यह अनुमति नोटिस सॉफ्टवेयर की सभी प्रतियों या महत्वपूर्ण भागों में शामिल किया जाएगा।
सॉफ्टवेयर "जैसा है" प्रदान किया जाता है, बिना किसी प्रकार की वारंटी के, व्यक्त या निहित, जिसमें लेकिन व्यापारिकता, किसी विशेष उद्देश्य के लिए उपयुक्तता और गैर-उल्लंघन की वारंटी शामिल नहीं है। किसी भी स्थिति में लेखक या कॉपीराइट धारक किसी भी दावे, क्षति या अन्य दायित्व के लिए उत्तरदायी नहीं होंगे, चाहे वह अनुबंध की कार्रवाई, टोर्ट या अन्यथा से उत्पन्न हो, सॉफ्टवेयर से या सॉफ्टवेयर के उपयोग या अन्य लेन-देन से संबंधित हो।
वास्तविक दुनिया का MOEW नमूना जिसने इस PoC को प्रेरित किया, उसने निष्पादन के अंत में fs:[0] को पुनर्स्थापित नहीं किया।
इसके बजाय, इसके अंतिम चरण ने:
fs:[0]) को NULL या अमान्य मेमोरी के पॉइंटर से अधिलेखित किया।RtlDispatchException को एक अमान्य हैंडलर पॉइंटर का सामना करने का कारण बना।unknown के रूप में दिखाई दिया।unknown के रूप में दिखाई दिया।Application Error ईवेंट को अर्थहीन दोष ऑफ़सेट के साथ लॉग किया।KiUserExceptionDispatcher कॉल,यह विनाशकारी SEH भ्रष्टाचार कदम नमूने के प्राथमिक विरोधी-फोरेंसिक उद्देश्य की पूर्ति करता है:
कारण श्रृंखला को मिटाना और एक गैर-जिम्मेदार टर्मिनल क्रैश उत्पन्न करना।
वास्तविक नमूने के विपरीत, यह PoC:
मूल SEH हेड को चरण 0 के दौरान कैप्चर करता है:
asm!("mov {old}, fs:[0]", old = out(reg) old_head);
ORIGINAL_SEH = old_head;
अंतिम हैंडलर में मूल SEH हेड को पुनर्स्थापित करता है:
asm!("mov fs:[0], {p}", p = in(reg) ORIGINAL_SEH);
process::exit(0) के माध्यम से सफाई से समाप्त होता है बजाय एक अनियंत्रित दोष ट्रिगर करने के।
परिणामस्वरूप, PoC:
Application Error 1000 प्रविष्टियाँ,हालांकि—महत्वपूर्ण रूप से—PoC MOEW के अपवाद-संचालित टेलीमेट्री क्षरण व्यवहार को समाप्त नहीं करता है।
PoC निश्चित रूप से उसी मौलिक तरीके से टेलीमेट्री को क्षीण करता है:
यह जानबूझकर कई गलत संरेखित हार्डवेयर दोष ट्रिगर करता है।
यह त्वरित क्रम में कई प्रथम-अवसर अपवाद उत्पन्न करता है।
यह विंडोज़ को बार-बार निष्पादित करने के लिए मजबूर करता है:
KiUserExceptionDispatcher
RtlDispatchException
→ कस्टम हैंडलर
→ गलत संरेखित ब्लॉब
→ हार्डवेयर दोष
यह गैर-रैखिक, अपवाद-प्रभुत्व वाले कॉल स्टैक उत्पन्न करता है।
यह डीबगर्स और EDR में नियंत्रण-प्रवाह पुनर्निर्माण को विकृत करता है, निष्पादन को इसके माध्यम से रूट करके:
इस प्रकार PoC ईमानदारी से पुनरुत्पादित करता है:
…जबकि विनाशकारी अंतिम क्रैश से बचता है।
यह PoC को पूर्ण विरोधी-फोरेंसिक पेलोड को आह्वान किए बिना इंस्ट्रूमेंटेशन और अनुसंधान के लिए आदर्श बनाता है।
क्योंकि PoC MOEW के समग्र व्यवहार को SEH भ्रष्टाचार क्रैश को छोड़कर संरक्षित करता है, यह:
PoC अपवाद वॉटरफॉल (MOEW का सार) का मॉडल बनाता है जबकि अंतिम विनाशकारी हस्ताक्षर को हटा देता है।
यह प्रदर्शित करता है कि टेलीमेट्री क्षरण केवल SEH भ्रष्टाचार से नहीं, बल्कि अपवाद-संचालित नियंत्रण-प्रवाह मॉडल से ही उत्पन्न होता है।
यह खंड व्यवहारिक अंतरों को औपचारिक रूप देता है जबकि PoC के उद्देश्य को स्पष्ट रखता है:
विरोधी-फोरेंसिक अंतिम क्रैश के बिना सुरक्षित, अनुसंधान-अनुकूल रूप में MOEW वॉटरफॉल प्रदर्शित करना।
| व्यवहार | वास्तविक MOEW नमूना | PoC कार्यान्वयन |
|---|
| गलत संरेखित ऑपकोड वॉटरफॉल | ✔ | ✔ |
| पुनरावृत्त SEH-संचालित राज्य मशीन | ✔ | ✔ |
| प्रभुत्व अपवाद-डिस्पैच कॉल स्टैक | ✔ | ✔ |
| टेलीमेट्री / स्टैक-ट्रेस क्षरण | ✔ | ✔ |
| जानबूझकर SEH भ्रष्टाचार | ✔ | ❌ |
| लटकते या अमान्य SEH पॉइंटर | ✔ | ❌ |
| अंतिम अनियंत्रित अपवाद | ✔ | ❌ |
| WER "अज्ञात मॉड्यूल" क्रैश | ✔ | ❌ |
fs:[0] की स्वच्छ पुनर्स्थापना | ❌ | ✔ |
| स्वच्छ समाप्ति | ❌ | ✔ |