Leaking libc address with ROP
त्वरित सारांश
ओवरफ्लो ऑफसेट खोजें
POP_RDI
गैजेट,PUTS_PLT
औरMAIN
गैजेट खोजेंपिछले गैजेट्स का उपयोग करके puts या अन्य libc फ़ंक्शन का मेमोरी पता लीक करें और libc संस्करण खोजें (डाउनलोड करें)
पुस्तकालय के साथ, ROP की गणना करें और इसका शोषण करें
अभ्यास के लिए अन्य ट्यूटोरियल और बाइनरी
यह ट्यूटोरियल इस ट्यूटोरियल में प्रस्तावित कोड/बाइनरी का शोषण करने जा रहा है: https://tasteofsecurity.com/security/ret2libc-unknown-libc/ अन्य उपयोगी ट्यूटोरियल: https://made0x78.com/bseries-ret2libc/, https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html
कोड
फाइल का नाम: vuln.c
ROP - LIBC लीक करने का टेम्पलेट
एक्सप्लॉइट डाउनलोड करें और इसे कमजोर बाइनरी के समान निर्देशिका में रखें और स्क्रिप्ट को आवश्यक डेटा दें:
Leaking libc - template1- ऑफसेट खोजना
टेम्पलेट को एक्सप्लॉइट के साथ आगे बढ़ने से पहले एक ऑफसेट की आवश्यकता होती है। यदि कोई प्रदान किया गया है, तो यह इसे खोजने के लिए आवश्यक कोड निष्पादित करेगा (डिफ़ॉल्ट रूप से OFFSET = ""
):
Execute python template.py
एक GDB कंसोल खोला जाएगा जिसमें प्रोग्राम क्रैश हो रहा है। उस GDB कंसोल के अंदर x/wx $rsp
चलाएँ ताकि bytes प्राप्त कर सकें जो RIP को ओवरराइट करने वाले थे। अंत में एक python कंसोल का उपयोग करके offset प्राप्त करें:
ऑफसेट (इस मामले में 40) खोजने के बाद, उस मान का उपयोग करके टेम्पलेट के अंदर OFFSET चर को बदलें।
OFFSET = "A" * 40
एक और तरीका होगा: pattern create 1000
-- ret तक निष्पादित करें -- pattern seach $rsp
GEF से।
2- गैजेट्स खोजना
अब हमें बाइनरी के अंदर ROP गैजेट्स खोजने की आवश्यकता है। ये ROP गैजेट्स puts
को कॉल करने के लिए उपयोगी होंगे ताकि libc का पता लगाया जा सके, और बाद में अंतिम हमले को लॉन्च करने के लिए।
The PUTS_PLT
फंक्शन puts को कॉल करने के लिए आवश्यक है।
The MAIN_PLT
मुख्य फंक्शन को फिर से कॉल करने के लिए आवश्यक है एक इंटरैक्शन के बाद overflow को फिर से exploits करने के लिए (exploitation के अनंत राउंड)। यह प्रत्येक ROP के अंत में प्रोग्राम को फिर से कॉल करने के लिए उपयोग किया जाता है।
The POP_RDI को कॉल किए गए फंक्शन को पैरामीटर पास करने के लिए आवश्यक है।
इस चरण में आपको कुछ भी निष्पादित करने की आवश्यकता नहीं है क्योंकि सब कुछ pwntools द्वारा निष्पादन के दौरान पाया जाएगा।
3- libc लाइब्रेरी खोजना
अब यह पता लगाने का समय है कि कौन सी libc लाइब्रेरी का संस्करण उपयोग किया जा रहा है। ऐसा करने के लिए हम फंक्शन puts
के मेमोरी में पता को leak करने जा रहे हैं और फिर हम यह खोजने जा रहे हैं कि उस पते में puts संस्करण किस लाइब्रेरी संस्करण में है।
इसको करने के लिए, निष्पादित कोड की सबसे महत्वपूर्ण पंक्ति है:
यह कुछ बाइट्स भेजेगा जब तक कि RIP को ओवरराइट करना संभव न हो: OFFSET
.
फिर, यह गैजेट POP_RDI
का पता सेट करेगा ताकि अगला पता (FUNC_GOT
) RDI रजिस्टर में सहेजा जा सके। इसका कारण यह है कि हम puts को कॉल करना चाहते हैं उसे PUTS_GOT
का पता पास करते हुए क्योंकि मेमोरी में puts फ़ंक्शन का पता PUTS_GOT
द्वारा इंगित किए गए पते में सहेजा गया है।
इसके बाद, PUTS_PLT
को कॉल किया जाएगा (जिसमें PUTS_GOT
RDI के अंदर है) ताकि puts PUTS_GOT
के अंदर की सामग्री (मेमोरी में puts फ़ंक्शन का पता) को पढ़े और इसे प्रिंट करे।
अंत में, मुख्य फ़ंक्शन फिर से कॉल किया जाता है ताकि हम फिर से ओवरफ्लो का लाभ उठा सकें।
इस तरह हमने puts फ़ंक्शन को प्रिंट करने के लिए धोखा दिया कि फ़ंक्शन puts का पता मेमोरी में (जो libc लाइब्रेरी के अंदर है) है। अब जब हमारे पास वह पता है, हम खोज सकते हैं कि कौन सा libc संस्करण उपयोग में है।
चूंकि हम कुछ स्थानीय बाइनरी का शोषण कर रहे हैं, इसलिए यह जानने की आवश्यकता नहीं है कि कौन सा libc संस्करण उपयोग में है (बस /lib/x86_64-linux-gnu/libc.so.6
में लाइब्रेरी खोजें)।
लेकिन, एक दूरस्थ शोषण मामले में, मैं यहाँ बताऊंगा कि आप इसे कैसे खोज सकते हैं:
3.1- libc संस्करण की खोज (1)
आप वेब पृष्ठ पर देख सकते हैं कि कौन सी लाइब्रेरी उपयोग में है: https://libc.blukat.me/ यह आपको खोजे गए libc के संस्करण को डाउनलोड करने की भी अनुमति देगा।
3.2- libc संस्करण की खोज (2)
आप यह भी कर सकते हैं:
$ git clone https://github.com/niklasb/libc-database.git
$ cd libc-database
$ ./get
इसमें कुछ समय लगेगा, धैर्य रखें। इसके लिए हमें आवश्यकता है:
Libc प्रतीक नाम:
puts
लीक किया गया libc पता:
0x7ff629878690
हम यह पता लगा सकते हैं कि कौन सा libc सबसे अधिक संभावना है कि उपयोग में है।
हमें 2 मिलान मिलते हैं (यदि पहला काम नहीं कर रहा है तो आपको दूसरे को आजमाना चाहिए)। पहला डाउनलोड करें:
libs/libc6_2.23-0ubuntu10_amd64/libc-2.23.so
से libc को हमारी कार्यशील निर्देशिका में कॉपी करें।
3.3- अन्य फ़ंक्शन लीक करने के लिए
4- libc पते को खोजने और शोषण करने के लिए
इस बिंदु पर हमें उपयोग की जाने वाली libc लाइब्रेरी के बारे में पता होना चाहिए। चूंकि हम एक स्थानीय बाइनरी का शोषण कर रहे हैं, मैं केवल उपयोग करूंगा: /lib/x86_64-linux-gnu/libc.so.6
तो, template.py
की शुरुआत में libc वेरिएबल को बदलें: libc = ELF("/lib/x86_64-linux-gnu/libc.so.6") #जब पता हो तो लाइब्रेरी पथ सेट करें
libc लाइब्रेरी को पथ देने से बाकी का शोषण स्वचालित रूप से गणना किया जाएगा।
get_addr
फ़ंक्शन के अंदर libc का आधार पता गणना किया जाएगा:
ध्यान दें कि अंतिम libc आधार पता 00 पर समाप्त होना चाहिए। यदि ऐसा नहीं है, तो आप एक गलत पुस्तकालय लीक कर सकते हैं।
फिर, फ़ंक्शन system
का पता और स्ट्रिंग "/bin/sh" का पता libc के आधार पते से गणना किया जाएगा और libc पुस्तकालय को दिया जाएगा।
अंत में, /bin/sh निष्पादन शोषण तैयार किया जाएगा:
चलो इस अंतिम ROP को समझाते हैं।
अंतिम ROP (rop1
) ने फिर से मुख्य फ़ंक्शन को कॉल किया, फिर हम फिर से शोषण कर सकते हैं ओवरफ्लो (इसलिए OFFSET
यहाँ फिर से है)। फिर, हम POP_RDI
को कॉल करना चाहते हैं जो "/bin/sh" (BINSH
) के पते की ओर इशारा करता है और system फ़ंक्शन (SYSTEM
) को कॉल करते हैं क्योंकि "/bin/sh" का पता एक पैरामीटर के रूप में पास किया जाएगा।
अंत में, exit फ़ंक्शन का पता कॉल किया जाता है ताकि प्रक्रिया अच्छी तरह से समाप्त हो जाए और कोई अलर्ट उत्पन्न न हो।
इस तरह शोषण एक _/bin/sh_** शेल को निष्पादित करेगा।**
4(2)- ONE_GADGET का उपयोग करना
आप ONE_GADGET का उपयोग करके system और "/bin/sh" के बजाय एक शेल प्राप्त कर सकते हैं। ONE_GADGET libc पुस्तकालय के अंदर एक शेल प्राप्त करने का एक तरीका खोजेगा जो केवल एक ROP पता का उपयोग करता है।
हालांकि, सामान्यतः कुछ सीमाएँ होती हैं, सबसे सामान्य और आसानी से बचने वाली सीमाएँ हैं जैसे [rsp+0x30] == NULL
। चूंकि आप RSP के अंदर के मानों को नियंत्रित करते हैं, इसलिए आपको कुछ और NULL मान भेजने की आवश्यकता है ताकि सीमा से बचा जा सके।
EXPLOIT FILE
आप इस कमजोरियों का फायदा उठाने के लिए एक टेम्पलेट यहाँ पा सकते हैं:
Leaking libc - templateसामान्य समस्याएँ
MAIN_PLT = elf.symbols['main'] नहीं मिला
यदि "main" प्रतीक मौजूद नहीं है। तो आप यह पता कर सकते हैं कि मुख्य कोड कहाँ है:
और पते को मैन्युअल रूप से सेट करें:
Puts नहीं मिला
यदि बाइनरी Puts का उपयोग नहीं कर रही है, तो आपको यह जांचना चाहिए कि क्या यह उपयोग कर रही है
sh: 1: %s%s%s%s%s%s%s%s: नहीं मिला
sh: 1: %s%s%s%s%s%s%s%s: नहीं मिला
यदि आप सभी एक्सप्लॉइट बनाने के बाद यह त्रुटि पाते हैं: sh: 1: %s%s%s%s%s%s%s%s: नहीं मिला
तो "/bin/sh" के पते से 64 बाइट घटाने का प्रयास करें:
Last updated