Skip to content
KitploitKITPLOIT
أدواتعمليات الاستغلالالمدونة
Log in
إرسال
أدواتعمليات الاستغلالالمدونة
إرسال

أدوات الاختراق واختبار الاختراق والأمن السيبراني لترسانتك الأمنية!

Kitploit هو دليل لأدوات الاختراق والأمن السيبراني واختبار الاختراق. اكتشف آخر تحديثات المشاريع للعثور على الثغرات وتحليل الأنظمة وأتمتة الاختبارات وتعزيز أمنك.

··الخلاصات·اتصال·الخصوصية·© 2026 Kitploit

دليل الأدوات

الفئات

عرض جميع الفئات
Loading categories
page_table_walk — تجول في جداول الصفحات x86-64 يدويًا في qemu و gdb. حلل عنوانًا افتراضيًا، اتبع سجل cr3 عبر جميع مستويات الذاكرة الفعلية، واستخرج علمًا من البايتات الخام. | Kitploit
أدوات/GitHubGitHub/jazho76/page_table_walk
تحليل الذاكرة الجنائيالهندسة العكسيةمصممي الأخطاءCTFتحليل الملفات الثنائيةالتعلم والتعليممختبرات وتدريب عملي
GitHubjazho76/page_table_walk

page_table_walk

تجول في جداول الصفحات x86-64 يدويًا في qemu و gdb. حلل عنوانًا افتراضيًا، اتبع سجل cr3 عبر جميع مستويات الذاكرة الفعلية، واستخرج علمًا من البايتات الخام.

عرض المستودع
28112منذ 6 أشهرتمت المراجعة من قبل Kitploit

الأكثر شعبية

عرض الكل →

اكتشف الأدوات الأكثر استخدامًا من قبل مجتمعنا.

استكشف جميع الأدوات

تصفح مجموعتنا من الأدوات

عرض جميع الأدوات →
مشاركة

التقاط العلم في الذاكرة الفعلية

لقد قرأت عن التقسيم الصفحي. المخططات منطقية. أربعة مستويات، 9 بتات لكل منها، إطار الصفحة، الإزاحة. بالتأكيد. لكن بعد ذلك تواجه تحديًا يتطلب فعليًا التنقل في جداول الصفحات، وتدرك أنك لا تعرفها حقًا. أنت تعرف عنها. فرق كبير.

ما نجح معي هو الجلوس أمام QEMU و gdb والقيام بالتنقل بنفسي: حساب كل مؤشر، قراءة كل إدخال من الذاكرة الفعلية، تتبع كل مؤشر يدويًا. ظهر واحد من ذلك يمكن أن يعلم أكثر من ساعات من المحاضرات.

هذه مجموعة من ملاحظاتي من تلك العملية. إذا كنت لا تزال تفتقر إلى الجانب المفاهيمي، شاهد محاضرة Zardus حول إدارة ذاكرة النواة أولاً. تلك هي النظرية. هذا هو المختبر.

الهدف: أخذ عنوان افتراضي وتعقبه عبر الذاكرة الفعلية الخام حتى نجد البيانات. لا مساعدات النواة. لا تجريدات. مجرد آلة افتراضية QEMU، gdb، وذاكرة فعلية خام.

بحلول النهاية، لن يكون التقسيم الصفحي شيئًا تقرأ عنه، بل سيكون شيئًا تعرفه لأنك قمت به يدويًا.


إعداد المختبر

تم تضمين نواة مبنية مسبقًا و initramfs، قمت بتشغيل هذا في فيدورا، لكن أي نظام تشغيل يدير 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

### The challenge binary

الهدف هو برنامج بسيط بلغة C يخزن علمًا (flag) في الذاكرة ويطبع عنوانه الافتراضي:```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)
    {
    }
}

الحلقة المزدحمة (busy loop) مقصودة. لقد استخدمت في الأصل pause()، لكن ذلك يضع العملية في حالة سكون في استدعاء نظام (syscall): عندما يوقف gdb الجهاز الافتراضي (VM)، فمن المحتمل أن وحدة المعالجة المركزية (CPU) تقوم بتشغيل مهمة الخمول (idle task) مع CR3 مختلف. الحلقة الدورانية (spinning loop) تبقي العملية على المعالج، لذا التوقف يضمن أنك في سياقها مع جداول الصفحات (page tables) الصحيحة.

تم تضمين initramfs مسبقة البناء مع هذا الثنائي بالفعل في initramfs.cpio.gz. إذا كنت بحاجة إلى إعادة بنائها (لنظام Linux فقط، يتطلب busybox و glibc-static)، قم بتشغيل make في هذا الدليل.

تشغيل QEMU```

./start.sh

يقوم البرنامج النصي بتشغيل النواة المجمعة و initramfs تحت QEMU مع `-s`
(خادم gdb على `localhost:1234`) و `nokaslr` بحيث تظل عناوين النواة
ثابتة بين عمليات التشغيل.

يتم تشغيل الجهاز الافتراضي فورًا ويتم تشغيل binary التحدي. سترى عنوان
العلم الافتراضي مطبوعًا على وحدة التحكم.```
secret @ 0x7ffe08985c90
pid = 1
Spinning. Walk the page tables to find the flag.

اكتب ذلك العنوان الافتراضي. هذا هو هدفك.

طرفية QEMU بعد الإقلاع، تُظهر مخرجات الثنائي التحدي مع عنوان العلامة ومعرف العملية

مفتاح الهروب الافتراضي لـ QEMU هو Ctrl-a، لكنه يتعارض مع بادئة tmux الخاصة بي، لذلك يستخدم السكريبت -echr 0x11 لإعادة تعيينه إلى Ctrl-q. إذا كنت تستخدم Ctrl-q لشيء آخر، فغيّر القيمة السداسية العشرية في start.sh لتناسب إعداداتك.

إرفاق gdb

في طرفية ثانية:``` gdb -ex "target remote :1234"

![طرفية gdb بعد الإرفاق، متوقفة وجاهزة](https://assets.kitploit.com/production/public/readmes/12435/9fb13e082596378677ea0d42cf7da3a86706df44127860fc724b2bad0a9f138c.png)

---

## تفكيك العنوان الافتراضي

لديك عنوان افتراضي. لكن أين البيانات، _حقًا_؟

العناوين الافتراضية هي الخيال المهذب لنظام التشغيل. كل عملية تعتقد أن لديها ذاكرة خاصة بها تبدأ من الصفر. في الواقع، تعيش البيانات في موقع غير مرتبط تمامًا في ذاكرة الوصول العشوائي الفعلية. جدول الصفحات هو الخريطة بينهما: بنية شجرية يقوم المعالج المركزي باجتيازها في كل وصول للذاكرة (أو يبحث عنها من ذاكرة التخزين المؤقت TLB الخاصة به).

لذا دعنا نفعل ما يفعله المعالج المركزي. يدويًا. لترجمة ذلك العنوان، نحتاج إلى تفكيكه إلى المؤشرات التي يستخدمها المعالج المركزي في كل مستوى.

العنوان الافتراضي في 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 كيلوبايت (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 هو مجرد مثال. استخدم أي عنوان يطبعه برنامج التحدي الخاص بك.

ملاحظة حول التقسيم بخمس مستويات. تدعم المعالجات والنواة الحديثة LA57، الذي يضيف مستوى خامسًا (PML5) فوق PGD ويمدد العناوين الافتراضية إلى 57 بتًا. المسار هو نفس النمط: مؤشر 9 بتات إضافي، بحث إضافي في جدول واحد. معظم الأنظمة لا تزال تستخدم التقسيم بأربعة مستويات. يمكنك التحقق من نظامك: cat /proc/cpuinfo | grep la57. كل شيء في هذه المقالة يفترض التقسيم بأربعة مستويات.


إيجاد CR3: جذر الشجرة

كل شجرة لها جذر. بالنسبة لجداول الصفحات، هذا الجذر موجود في المسجل CR3: فهو يحمل العنوان المادي للجدول الأعلى مستوى، وهو PGD. كل عملية تحصل على قيمة CR3 خاصة بها، وتقوم النواة بتبديلها عند تبديل السياق.

هذه هي نقطة دخولنا إلى المسار. اقرأها من gdb:``` (gdb) info registers cr3 cr3 0x66c7000 [ PDBR=26311 PCID=0 ]

قاعدة جدول الصفحات هي `0x66c7000`. البتات الـ 12 السفلية هي PCID/أعلام (صفر هنا)، لذا فإن العنوان الأساسي هو القيمة كما هي.

هنا يبدأ التجوال.

---

## التجوال

إليك الحيلة: كل مستوى يتبع نفس النمط. تختلف الأعلام قليلاً بين المستويات، لكن العملية لا تتغير. النمط:

1. **حساب عنوان الإدخال:** `base + index * 8` (كل إدخال هو 8 بايت)
2. **قراءة الإدخال من الذاكرة الفعلية** باستخدام أمر `xp` في مراقب QEMU
3. **فك تشفير الأعلام** (انظر المرجع أدناه). إذا كانت بتة الوجود (bit 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 يتم تجاهلها بواسطة العتاد وهي متاحة لنظام التشغيل. يستخدمها لينكس لأغراض حفظ الدفاتر (تتبع الأوساخ الناعمة، على سبيل المثال). البتات 52-62 محجوزة. ستواجه كليهما عند قراءة PTEs في كتابات الاستغلال.

احتفظ بجدول الأعلام هذا في متناول يدك أثناء السير.

لنبدأ.

المستوى 4: PGD (الدليل العام للصفحات)

لدينا قاعدة PGD من CR3: 0x66c7000. مؤشر PGD الخاص بنا هو 0xff.

احسب عنوان الإدخال:``` entry = 0x66c7000 + 0xff * 8 = 0x66c77f8

اقرأها من gdb باستخدام أمر فحص الذاكرة الفعلية لـ QEMU:```
(gdb) monitor xp/1gx 0x66c77f8
000000066c77f8: 0x0000000006713067

المدخل: 0x6713067 [Present RW User Accessed Dirty].

القاعدة التالية: 0x6713067 & 0x000FFFFFFFFFF000 = 0x6713000.

المستوى 3: PUD (Page Upper Directory)

تنزيل الأداة