Skip to content
KitploitKITPLOIT
उपकरणएक्सप्लॉइटब्लॉग
Log in
जमा करें
उपकरणएक्सप्लॉइटब्लॉग
जमा करें

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

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

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

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

श्रेणियाँ

सभी श्रेणियाँ देखें
Loading categories
page_table_walk — qemu और gdb में हाथ से x86-64 पेज टेबल्स को चलें। एक वर्चुअल एड्रेस को डीकंपोज़ करें, भौतिक मेमोरी के सभी स्तरों के माध्यम से cr3 का अनुसरण करें, और रॉ बाइट्स से एक फ्लैग निकालें। | Kitploit
उपकरण/GitHubGitHub/jazho76/page_table_walk
मेमोरी फोरेंसिकरिवर्स इंजीनियरिंगडीबगर्सCTFबाइनरी विश्लेषणलर्निंग और शिक्षालैब और अभ्यास
GitHubjazho76/page_table_walk

page_table_walk

qemu और gdb में हाथ से x86-64 पेज टेबल्स को चलें। एक वर्चुअल एड्रेस को डीकंपोज़ करें, भौतिक मेमोरी के सभी स्तरों के माध्यम से cr3 का अनुसरण करें, और रॉ बाइट्स से एक फ्लैग निकालें।

रिपॉजिटरी देखें
281136 महीने पहलेKitploit द्वारा समीक्षित

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

सभी देखें →

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

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

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

सभी उपकरण देखें →
साझा करें

भौतिक मेमोरी में फ़्लैग कैप्चर करना

आपने पेजिंग के बारे में पढ़ा है। आरेख समझ में आते हैं। चार स्तर, 9 बिट प्रत्येक, पेज फ्रेम, ऑफसेट। बिल्कुल। लेकिन फिर आप एक ऐसी चुनौती पर आते हैं जिसमें वास्तव में पेज तालिकाओं को चलने की आवश्यकता होती है, और आपको एहसास होता है कि आप इसे जानते नहीं हैं। आप इसे के बारे में जानते हैं। बड़ा अंतर।

मेरे लिए जो काम कर गया वह QEMU और gdb के सामने बैठकर स्वयं वॉक करना था: हर इंडेक्स की गणना करना, हर एंट्री को भौतिक मेमोरी से पढ़ना, हर पॉइंटर को हाथ से अनुसरण करना। उस दोपहर ने घंटों के व्याख्यानों से अधिक सिखाया होगा।

यह उस प्रक्रिया से मेरे नोट्स का एक संग्रह है। यदि आप अभी भी सैद्धांतिक पक्ष से चूक रहे हैं, तो पहले Zardus का कर्नेल मेमोरी प्रबंधन पर व्याख्यान देखें। वह सिद्धांत है। यह प्रयोगशाला है।

लक्ष्य: एक वर्चुअल पता लेना और उसे कच्ची भौतिक मेमोरी के माध्यम से तब तक ट्रैक करना जब तक हम डेटा न ढूंढ लें। कोई कर्नेल सहायक नहीं। कोई अमूर्तता नहीं। सिर्फ एक QEMU VM, gdb, और कच्ची भौतिक मेमोरी।

अंत में, पेजिंग कुछ ऐसा नहीं होगा जिसके बारे में आपने पढ़ा है, यह कुछ ऐसा होगा जिसे आप जानते हैं क्योंकि आपने इसे हाथ से किया है।


प्रयोगशाला स्थापित करना

एक पूर्व-निर्मित कर्नेल और initramfs शामिल हैं, मैंने इसे Fedora में चलाया, लेकिन कोई भी OS जो QEMU और gdb चलाता है, काम करना चाहिए। इन्हें अपने पैकेज मैनेजर से स्थापित करें:```

Ubuntu/Debian

sudo apt install qemu-system-x86 gdb

Fedora/RHEL

sudo dnf install qemu-system-x86 gdb

macOS

brew install qemu gdb

### चुनौती बाइनरी

लक्ष्य एक सामान्य C प्रोग्राम है जो मेमोरी में एक फ़्लैग संग्रहीत करता है और उसका वर्चुअल पता प्रिंट करता है:```c
#include <stdio.h>
#include <unistd.h>

int main(void)
{
    char secret[] = "FLAG{p4g3_t4bl3_w4lk3r}";

    printf("secret @ %p\n", (void *)secret);
    printf("pid = %d\n", getpid());
    printf("Spinning. Walk the page tables to find the flag.\n");

    while (1)
    {
    }
}

बिज़ी लूप जानबूझकर है। मैंने मूल रूप से pause() का उपयोग किया था, लेकिन वह प्रक्रिया को syscall में सोने के लिए डालता है: जब gdb VM को रोकता है, तो CPU संभवतः अलग CR3 के साथ निष्क्रिय कार्य चला रहा होता है। एक स्पिनिंग लूप प्रक्रिया को CPU पर रखता है, इसलिए रोकना यह सुनिश्चित करता है कि आप सही पेज टेबल के साथ इसके संदर्भ में हैं।

इस बाइनरी के साथ एक पूर्व-निर्मित initramfs initramfs.cpio.gz में पहले से शामिल है। यदि आपको इसे पुनर्निर्माण करने की आवश्यकता है (केवल Linux, busybox और glibc-static की आवश्यकता है), तो इस निर्देशिका में make चलाएँ।

QEMU लॉन्च करना```

./start.sh

स्क्रिप्ट बंडल कर्नेल और initramfs को QEMU के तहत `-s` (gdb सर्वर `localhost:1234` पर) और `nokaslr` के साथ बूट करती है ताकि कर्नेल पते रनों के बीच स्थिर रहें।

VM तुरंत बूट होता है और चुनौती बाइनरी चलती है। आप कंसोल पर फ़्लैग का वर्चुअल पता प्रिंट होता देखेंगे।```
secret @ 0x7ffe08985c90
pid = 1
Spinning. Walk the page tables to find the flag.

उस वर्चुअल पते को लिख लें। यही आपका लक्ष्य है।

बूट के बाद QEMU टर्मिनल, चैलेंज बाइनरी का आउटपुट दिखाता हुआ जिसमें फ्लैग पता और PID है

डिफ़ॉल्ट QEMU एस्केप कुंजी Ctrl-a है, लेकिन यह मेरे tmux प्रीफिक्स से टकराता है, इसलिए स्क्रिप्ट इसे Ctrl-q पर रीमैप करने के लिए -echr 0x11 का उपयोग करती है। यदि आप Ctrl-q का उपयोग किसी और चीज़ के लिए करते हैं, तो start.sh में हेक्स मान को अपने सेटअप के अनुसार बदलें।

gdb अटैच करना

दूसरे टर्मिनल में:``` gdb -ex "target remote :1234"

![gdb टर्मिनल अटैच करने के बाद, रुका हुआ और तैयार](https://assets.kitploit.com/production/public/readmes/12435/9fb13e082596378677ea0d42cf7da3a86706df44127860fc724b2bad0a9f138c.png)

---

## वर्चुअल एड्रेस को विघटित करना

आपके पास एक वर्चुअल एड्रेस है। लेकिन डेटा, _वास्तव में_ कहाँ है?

वर्चुअल एड्रेस ऑपरेटिंग सिस्टम का एक शिष्ट कल्पना (polite fiction) हैं। हर प्रक्रिया सोचती है कि उसकी अपनी निजी मेमोरी शून्य से शुरू होती है। वास्तव में, डेटा फिजिकल RAM में किसी पूरी तरह से असंबंधित स्थान पर रहता है। पेज टेबल दोनों के बीच का नक्शा है: एक पेड़ संरचना जिसे CPU हर एक मेमोरी एक्सेस पर चलता है (या अपने TLB कैश से देखता है)।

तो चलिए वही करते हैं जो CPU करता है। मैन्युअली। उस एड्रेस का अनुवाद करने के लिए, हमें इसे उन सूचकांकों में विघटित करना होगा जिनका उपयोग CPU प्रत्येक स्तर पर करता है।

एक x86-64 वर्चुअल एड्रेस 48 बिट चौड़ा होता है। उन 48 बिटों को पाँच क्षेत्रों में विभाजित किया गया है:```
 63    48 47    39 38    30 29    21 20    12 11       0
┌────────┬────────┬────────┬────────┬────────┬──────────┐
│ sign   │  PGD   │  PUD   │  PMD   │   PT   │  Offset  │
│ extend │ index  │ index  │ index  │ index  │          │
│ (16b)  │ (9b)   │ (9b)   │ (9b)   │ (9b)   │  (12b)   │
└────────┴────────┴────────┴────────┴────────┴──────────┘

प्रत्येक 9-बिट इंडेक्स उस स्तर पर पेज टेबल में 512 प्रविष्टियों में से एक का चयन करता है। 12-बिट ऑफ़सेट अंतिम 4 KB (0x1000) पेज के भीतर एक बाइट का चयन करता है।

इंडेक्स निकालने के लिए, शिफ्ट और मास्क करें:``` PGD index = (VA >> 39) & 0x1FF PUD index = (VA >> 30) & 0x1FF PMD index = (VA >> 21) & 0x1FF PT index = (VA >> 12) & 0x1FF Offset = VA & 0xFFF

gdb में, आप इन्हें सीधे गणना कर सकते हैं:```
(gdb) p/x (0x7ffe08985c90 >> 39) & 0x1ff
$1 = 0xff
(gdb) p/x (0x7ffe08985c90 >> 30) & 0x1ff
$2 = 0x1f8
(gdb) p/x (0x7ffe08985c90 >> 21) & 0x1ff
$3 = 0x44
(gdb) p/x (0x7ffe08985c90 >> 12) & 0x1ff
$4 = 0x185
(gdb) p/x 0x7ffe08985c90 & 0xfff
$5 = 0xc90

इन्हें लिख लें। आप प्रत्येक का उपयोग उसके संबंधित स्तर पर करेंगे।

आपके मान भिन्न होंगे। पता 0x7ffe08985c90 केवल एक उदाहरण है। अपने चैलेंज बाइनरी द्वारा मुद्रित किसी भी पते का उपयोग करें।

5-स्तरीय पेजिंग पर एक नोट। हाल के CPUs और कर्नेल LA57 का समर्थन करते हैं, जो PGD के ऊपर एक पाँचवाँ स्तर (PML5) जोड़ता है और वर्चुअल पतों को 57 बिट तक विस्तारित करता है। वॉक वही पैटर्न है: एक और 9-बिट इंडेक्स, एक और टेबल लुकअप। अधिकांश सिस्टम अभी भी 4-स्तरीय पेजिंग चलाते हैं। आप अपना जाँच सकते हैं: cat /proc/cpuinfo | grep la57। इस लेख में सब कुछ 4-स्तरीय मानता है।


CR3 ढूँढना: पेड़ की जड़

हर पेड़ की एक जड़ होती है। पेज टेबल के लिए, वह जड़ CR3 रजिस्टर में है: इसमें शीर्ष-स्तरीय तालिका, PGD का भौतिक पता होता है। प्रत्येक प्रक्रिया को अपना स्वयं का CR3 मान मिलता है, कर्नेल इसे कॉन्टेक्स्ट स्विच पर बदलता है।

यह वॉक में हमारा प्रवेश बिंदु है। इसे gdb से पढ़ें:``` (gdb) info registers cr3 cr3 0x66c7000 [ PDBR=26311 PCID=0 ]

पेज टेबल बेस `0x66c7000` है। निचले 12 बिट PCID/फ़्लैग्स (यहाँ शून्य) हैं, इसलिए बेस पता ज्यों का त्यों मान है।

यहीं से वॉक शुरू होता है।

---

## वॉक

यहाँ ट्रिक है: हर स्तर एक ही पैटर्न का पालन करता है। फ़्लैग्स स्तरों के बीच थोड़े भिन्न होते हैं, लेकिन प्रक्रिया नहीं बदलती। पैटर्न:

1. **प्रविष्टि पता निकालें:** `base + index * 8` (प्रत्येक प्रविष्टि 8 बाइट्स है)
2. **भौतिक मेमोरी से प्रविष्टि पढ़ें** QEMU मॉनिटर के `xp` कमांड का उपयोग करके
3. **फ़्लैग्स को डिकोड करें** (नीचे दिए गए संदर्भ देखें)। यदि Present (बिट 0) 0 है, तो पेज मैप नहीं हुआ है और वॉक रुक जाता है
4. **अगले टेबल का बेस निकालें:** प्रविष्टि को `& 0x000FFFFFFFFFF000` से मास्क करें
5. **अगले स्तर पर जाएँ**

प्रत्येक प्रविष्टि 64 बिट्स की होती है। सामान्य फ़्लैग बिट्स:```
Bit   Name              Meaning when set
 0    Present           Page/table is mapped
 1    Read/Write        Writable
 2    User/Supervisor   Accessible from userspace
 3    Write-Through     Write-through caching
 4    Cache Disable     Caching disabled
 5    Accessed          CPU has read this entry
 6    Dirty             CPU has written to the page (final level only)
 7    Page Size         1 GB page (PUD) or 2 MB page (PMD)
63    NX                No-execute

बिट्स [51:12] अगली तालिका (या अंतिम स्तर पर पेज फ्रेम) का भौतिक पता रखते हैं। बिट्स 9-11 हार्डवेयर द्वारा अनदेखा किए जाते हैं और OS उपयोग के लिए उपलब्ध हैं। लिनक्स उन्हें बुककीपिंग (उदाहरण के लिए, सॉफ्ट-डर्टी ट्रैकिंग) के लिए उपयोग करता है। बिट्स 52-62 आरक्षित हैं। आप एक्सप्लॉइट राइटअप में PTEs पढ़ते समय दोनों का सामना करेंगे।

टूल डाउनलोड करें