ROP - Return Oriented Programing
Last updated
Last updated
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)
Return-Oriented Programming (ROP) एक उन्नत शोषण तकनीक है जिसका उपयोग सुरक्षा उपायों जैसे No-Execute (NX) या Data Execution Prevention (DEP) को दरकिनार करने के लिए किया जाता है। शेलकोड को इंजेक्ट और निष्पादित करने के बजाय, एक हमलावर बाइनरी या लोड की गई लाइब्रेरी में पहले से मौजूद कोड के टुकड़ों का लाभ उठाता है, जिसे "gadgets" कहा जाता है। प्रत्येक गेजेट आमतौर पर एक ret
निर्देश के साथ समाप्त होता है और डेटा को रजिस्टर के बीच स्थानांतरित करने या अंकगणितीय संचालन करने जैसे छोटे कार्य करता है। इन गेजेट्स को एक साथ जोड़कर, एक हमलावर मनचाहे संचालन करने के लिए एक पेलोड तैयार कर सकता है, प्रभावी रूप से NX/DEP सुरक्षा को दरकिनार कर सकता है।
Control Flow Hijacking: सबसे पहले, एक हमलावर को एक प्रोग्राम के नियंत्रण प्रवाह को हाईजैक करना होता है, आमतौर पर एक बफर ओवरफ्लो का शोषण करके स्टैक पर एक सहेजे गए लौटने के पते को ओवरराइट करके।
Gadget Chaining: फिर हमलावर सावधानीपूर्वक गेजेट्स का चयन और श्रृंखला बनाता है ताकि इच्छित क्रियाएँ की जा सकें। इसमें एक फ़ंक्शन कॉल के लिए तर्क सेट करना, फ़ंक्शन को कॉल करना (जैसे, system("/bin/sh")
), और किसी भी आवश्यक सफाई या अतिरिक्त संचालन को संभालना शामिल हो सकता है।
Payload Execution: जब संवेदनशील फ़ंक्शन लौटता है, तो यह एक वैध स्थान पर लौटने के बजाय गेजेट्स की श्रृंखला को निष्पादित करना शुरू कर देता है।
आमतौर पर, गेजेट्स को ROPgadget, ropper या सीधे pwntools (ROP) का उपयोग करके पाया जा सकता है।
cdecl: कॉलर स्टैक को साफ करता है। फ़ंक्शन तर्कों को उल्टे क्रम (दाएं से बाएं) में स्टैक पर धकेला जाता है। तर्कों को स्टैक पर दाएं से बाएं धकेला जाता है।
stdcall: cdecl के समान, लेकिन कॉल की गई फ़ंक्शन स्टैक को साफ करने के लिए जिम्मेदार होती है।
पहले, मान लेते हैं कि हमने बाइनरी या इसके लोड की गई लाइब्रेरी में आवश्यक गेजेट्स की पहचान की है। जिन गेजेट्स में हमारी रुचि है, वे हैं:
pop eax; ret
: यह गेजेट स्टैक के शीर्ष मान को EAX
रजिस्टर में डालता है और फिर लौटता है, जिससे हमें EAX
को नियंत्रित करने की अनुमति मिलती है।
pop ebx; ret
: ऊपर के समान, लेकिन EBX
रजिस्टर के लिए, जिससे EBX
पर नियंत्रण प्राप्त होता है।
mov [ebx], eax; ret
: EAX
में मान को EBX
द्वारा इंगित मेमोरी स्थान पर स्थानांतरित करता है और फिर लौटता है। इसे अक्सर write-what-where gadget कहा जाता है।
इसके अतिरिक्त, हमारे पास system()
फ़ंक्शन का पता उपलब्ध है।
pwntools का उपयोग करते हुए, हम ROP श्रृंखला निष्पादन के लिए स्टैक को इस प्रकार तैयार करते हैं ताकि system('/bin/sh')
को निष्पादित किया जा सके, ध्यान दें कि श्रृंखला इस प्रकार शुरू होती है:
संरेखण उद्देश्यों के लिए एक ret
निर्देश (वैकल्पिक)
system
फ़ंक्शन का पता (मान लेते हैं कि ASLR अक्षम है और libc ज्ञात है, अधिक जानकारी Ret2lib में)
system()
से लौटने के पते के लिए प्लेसहोल्डर
"/bin/sh"
स्ट्रिंग का पता (सिस्टम फ़ंक्शन के लिए पैरामीटर)
System V AMD64 ABI कॉलिंग कन्वेंशन का उपयोग यूनिक्स-जैसे सिस्टम पर किया जाता है, जहाँ पहले छह पूर्णांक या पॉइंटर तर्क RDI
, RSI
, RDX
, RCX
, R8
, और R9
रजिस्टर में पास किए जाते हैं। अतिरिक्त तर्क स्टैक पर पास किए जाते हैं। लौटने का मान RAX
में रखा जाता है।
Windows x64 कॉलिंग कन्वेंशन पहले चार पूर्णांक या पॉइंटर तर्कों के लिए RCX
, RDX
, R8
, और R9
का उपयोग करता है, जबकि अतिरिक्त तर्क स्टैक पर पास किए जाते हैं। लौटने का मान RAX
में रखा जाता है।
Registers: 64-बिट रजिस्टर में RAX
, RBX
, RCX
, RDX
, RSI
, RDI
, RBP
, RSP
, और R8
से R15
शामिल हैं।
हमारे उद्देश्य के लिए, आइए उन गैजेट्स पर ध्यान केंद्रित करें जो हमें RDI रजिस्टर सेट करने की अनुमति देंगे (ताकि system() को तर्क के रूप में "/bin/sh" स्ट्रिंग पास कर सकें) और फिर system() फ़ंक्शन को कॉल करें। हम मान लेते हैं कि हमने निम्नलिखित गैजेट्स की पहचान की है:
pop rdi; ret: स्टैक के शीर्ष मान को RDI में पॉप करता है और फिर लौटता है। system() के लिए हमारे तर्क को सेट करने के लिए आवश्यक।
ret: एक साधारण रिटर्न, कुछ परिदृश्यों में स्टैक संरेखण के लिए उपयोगी।
और हम जानते हैं कि system() फ़ंक्शन का पता क्या है।
नीचे एक उदाहरण है जो pwntools का उपयोग करके system('/bin/sh') को x64 पर निष्पादित करने के लिए ROP चेन सेटअप और निष्पादित करता है:
In this example:
हम pop rdi; ret
गैजेट का उपयोग करते हैं ताकि RDI
को "/bin/sh"
के पते पर सेट किया जा सके।
हम RDI
सेट करने के बाद सीधे system()
पर कूदते हैं, जिसमें system() का पता श्रृंखला में होता है।
यदि लक्षित वातावरण की आवश्यकता हो, तो संरेखण के लिए ret_gadget
का उपयोग किया जाता है, जो x64 में कार्यों को कॉल करने से पहले उचित स्टैक संरेखण सुनिश्चित करने के लिए अधिक सामान्य है।
x86-64 ABI सुनिश्चित करता है कि जब call instruction निष्पादित होती है, तो stack 16-byte aligned हो। LIBC, प्रदर्शन को अनुकूलित करने के लिए, SSE instructions (जैसे movaps) का उपयोग करता है जो इस संरेखण की आवश्यकता होती है। यदि स्टैक ठीक से संरेखित नहीं है (जिसका अर्थ है कि RSP 16 का गुणांक नहीं है), तो ROP chain में system जैसे कार्यों के लिए कॉल विफल हो जाएंगे। इसे ठीक करने के लिए, अपने ROP श्रृंखला में system को कॉल करने से पहले बस एक ret gadget जोड़ें।
चूंकि x64 पहले कुछ तर्कों के लिए रजिस्टर का उपयोग करता है, इसलिए यह अक्सर सरल कार्य कॉल के लिए x86 की तुलना में कम गैजेट की आवश्यकता होती है, लेकिन सही गैजेट खोजने और श्रृंखला में जोड़ने में अधिक जटिलता हो सकती है क्योंकि रजिस्टर की संख्या और पता स्थान बढ़ जाता है। x64 आर्किटेक्चर में रजिस्टर की बढ़ी हुई संख्या और बड़े पते के स्थान ने विशेष रूप से Return-Oriented Programming (ROP) के संदर्भ में शोषण विकास के लिए अवसर और चुनौतियाँ दोनों प्रदान की हैं।
इस जानकारी के लिए निम्नलिखित पृष्ठ देखें:
Stack Canaries: BOF के मामले में, ROP श्रृंखला का दुरुपयोग करने के लिए लौटने वाले प्वाइंटर्स को ओवरराइट करने के लिए स्टोर स्टैक कैनरी को बायपास करना आवश्यक है।
गैजेट्स की कमी: यदि पर्याप्त गैजेट नहीं हैं, तो ROP श्रृंखला उत्पन्न करना संभव नहीं होगा।
ध्यान दें कि ROP केवल मनमाने कोड को निष्पादित करने की एक तकनीक है। ROP के आधार पर कई Ret2XXX तकनीकें विकसित की गई हैं:
Ret2lib: मनमाने पैरामीटर के साथ लोड की गई लाइब्रेरी से मनमाने कार्यों को कॉल करने के लिए ROP का उपयोग करें (आमतौर पर कुछ ऐसा जैसे system('/bin/sh')
।
Ret2Syscall: ROP का उपयोग करके एक syscall, जैसे execve
, के लिए कॉल तैयार करें, और इसे मनमाने आदेश निष्पादित करने के लिए बनाएं।
EBP2Ret और EBP चेनिंग: पहला EIP के बजाय EBP का दुरुपयोग करेगा ताकि प्रवाह को नियंत्रित किया जा सके और दूसरा Ret2lib के समान है लेकिन इस मामले में प्रवाह मुख्य रूप से EBP पते के साथ नियंत्रित होता है (हालांकि EIP को भी नियंत्रित करना आवश्यक है)।
64 बिट, पाई और एनएक्स सक्षम, कोई कैनरी नहीं, एक vsyscall
पते के साथ RIP को ओवरराइट करें जिसका एकमात्र उद्देश्य स्टैक में अगले पते पर लौटना है जो फ्लैग लीक करने वाले कार्य के भाग का आंशिक ओवरराइट होगा
arm64, कोई ASLR नहीं, स्टैक में शेलकोड पर कूदने और स्टैक को निष्पादित करने के लिए ROP गैजेट
Learn & practice AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE) Learn & practice GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)