انتقل إلى المحتوى

فهارس المجلدات ($I30)

ما هو $I30

يحتفظ كل مجلد في NTFS بفهرس للملفات الموجودة فيه، يُسمى $I30. ويحتفظ المجلد الصغير به في سجل $MFT الخاص به ($INDEX_ROOT)؛ أما المجلد الأكبر فيملك أيضًا سجلات INDX، حجم كل منها عادةً 4,096 بايت، في دفق $INDEX_ALLOCATION:$I30. ويحمل كل إدخال في الفهرس نسخة من $FILE_NAME الخاص بالملف: اسمه، ومرجع MFT، والمجلد الأب، وأربعة طوابع زمنية، وحجمين، كما كانت في آخر مرة حدّث فيها NTFS الإدخال.

عندما يُحذف ملف أو يُعاد تسميته فيخرج من مجلد، يزيل NTFS إدخاله وينقل الإدخالات التي تليه. وتبقى البايتات القديمة في المساحة الراكدة (slack) لسجل INDX، بعد الإدخالات المستخدمة، إلى أن تكتب فوقها إدخالات لاحقة. ويمكن أن تحتفظ المساحة الراكدة في الفهرس باسم ملف وأوقاته وحجمه حتى لو أُعيد استخدام سجل $MFT الخاص به ودارت سجلات دفتر يومية USN الخاصة به.

أفضل استنتاج: الاسم الموجود في المساحة الراكدة للفهرس كان، في وقت ما، في فهرس هذا المجلد بأوقات $FILE_NAME وأحجامه المذكورة. ولا يوضح إدخال المساحة الراكدة متى أُزيل، ولا ما إذا كان قد حُذف أو أُعيد تسميته أو نُقل بسبب إعادة الموازنة.

الموقع والجمع

C:\<directory>:$I30:$INDEX_ALLOCATION

$I30 هو بيانات وصفية لـ NTFS: اجمعه بأداة جنائية تدعم الوصول الخام ويمكنها تصدير دفق $I30 الخاص بمجلد (كثيرًا ما تُسمى الملفات المصدّرة $I30). ويمكن لـ Juntei أيضًا البحث في صورة قرص أو مساحة غير مخصصة عن سجلات INDX. واجمع أيضًا $MFT و$J من وحدة التخزين نفسها، لمعرفة ماهية إدخالات المساحة الراكدة.

تحذيرات للمحلل

  • المساحة الراكدة في الفهرس جزئية وغير مرتبة. تُكتب الإدخالات فوق بعضها مع تغيّر المجلد؛ و غياب اسم ما لا يثبت شيئًا.
  • كثير من إدخالات المساحة الراكدة نسخ من إدخالات لا تزال مستخدمة، تُركت عند نقل الإدخالات. ويميّزها CopyOfEntryInUse. وقد يوجد الاسم المحذوف نفسه أيضًا في المساحة الراكدة عدة مرات.
  • الأوقات في إدخال الفهرس هي أوقات $FILE_NAME كما كانت عند آخر تحديث للإدخال. وقد تختلف عن كل من أوقات $STANDARD_INFORMATION و$FILE_NAME في سجل $MFT الخاص بالملف.
  • AllocatedSize وRealSize هما أيضًا كما كانا عند آخر تحديث للإدخال، وقد يكونان قديمين.
  • قد يكون FileEntry (أو ParentEntry) الخاص بإدخال في المساحة الراكدة مفقودًا عندما تكتب بايتات لاحقة فوقه. وعند وجوده، ربما يكون سجل MFT الذي يشير إليه قد أُعيد استخدامه منذ ذلك الحين: قارن رقم التسلسل.
  • يقرأ parse-ntfs i30 سجلات INDX. ولا يوجد فهرس المجلد الصغير إلا في سجل $MFT الخاص به ($INDEX_ROOT)؛ وتوجد ملفاته في $MFT.

التحليل باستخدام Juntei

Usage: juntei parse-ntfs i30 <INPUT> [OPTIONS]

Input:
  -d, --directory <DIR>  Recursively find $I30 files (with $I30 in their name, or starting with an INDX record)
  -f, --file <FILE>      Parse one $I30 stream, or any file holding INDX records (a disk image, unallocated space)

Filtering:
      --slack-only  Only the entries found in slack
      --no-copies   Leave out the slack entries that copy an entry in use

Output:
  -o, --output <FILE>       Save every entry
  -t, --output-type <TYPE>  csv, json, or jsonl
juntei parse-ntfs i30 -f 'Users_$I30'
juntei parse-ntfs i30 -d evidence/ -o i30.csv
juntei parse-ntfs i30 -f 'Users_$I30' --slack-only --no-copies -t jsonl
juntei parse-ntfs i30 -f disk.raw -o carved-i30.csv

يسرد الملخص سجلات INDX (وعدد ما كُتب منها جزئيًا)، والإدخالات المستخدمة والموجودة في المساحة الراكدة، وأسماء إدخالات المساحة الراكدة التي ليست نسخًا مطابقة لإدخالات مستخدمة. وهذه الأسماء مرشحة لأن تكون ملفات محذوفة أو أُعيدت تسميتها، وليست حكمًا قاطعًا بحد ذاتها.

حقول إخراج CSV

الحقل التفسير
SourcePath ملف الإدخال؛ يميّز بين المضيفين والمجلدات.
RecordOffset، EntryOffset إزاحتا البايت لسجل INDX وللإدخال في ملف الإدخال. ضروريتان للتحقق وللسجلات الموجودة في صور الأقراص.
RecordVCN، RecordLSN موضع السجل في دفق الفهرس ورقم تسلسل $LogFile الخاص به.
FromSlack True للإدخال الموجود بعد الإدخالات المستخدمة.
CopyOfEntryInUse إدخال في المساحة الراكدة له الاسم ومساحة الأسماء والملف (عند معرفته) والأب والأوقات نفسها لإدخال مستخدم في فهرس المجلد نفسه. وعادةً ما يكون بقايا نقل الإدخالات، لا ملفًا محذوفًا.
Filename الاسم في المجلد.
Namespace win32 أو dos (الاسم المختصر 8.3) أو win32_and_dos أو posix.
FileEntry، FileSequence مرجع MFT الخاص بالملف. فارغ لإدخال في المساحة الراكدة كُتب فوق ترويسته.
ParentEntry، ParentSequence مرجع MFT الخاص بالمجلد. فارغ عندما تُكتب بايتات أخرى فوقه.
CreatedUTC، ModifiedUTC، MFT-ModifiedUTC، AccessedUTC أوقات $FILE_NAME، بدقة 100 نانوثانية، كما كانت عند آخر تحديث للإدخال.
AllocatedSize، RealSize الأحجام التي نسخها NTFS إلى الإدخال؛ راجع التحذيرات أعلاه.
FileAttributes أسماء السمات مدمجة بالرمز | (hidden|archive)؛ وis_directory للمجلد الفرعي. وتُحفظ البتات التي لا يسميها هذا الإصدار من Juntei بالنظام السداسي عشري (0x00800000).
ReparseValue وسم إعادة التوجيه (reparse tag) أو حجم السمات الموسعة من $FILE_NAME.
Problems تلف في السجل، مثل قطاعات كُتبت جزئيًا. ولا تزال الإدخالات من سجل تالف تستحق المراجعة، بحذر.

تحتوي JSON/JSONL على الحقول نفسها بصيغة snake_case، مع problems على هيئة قائمة وnull للقيم غير المعروفة.

كيف تُكتشف إدخالات المساحة الراكدة

تُفحص المساحة الراكدة عند كل حد من 8 بايتات، حيث تبدأ الإدخالات، بحثًا عن إدخالات كاملة، وعن سمات $FILE_NAME التي كُتب فوق ترويسة إدخالها، وفي بداية المساحة الراكدة، عن $FILE_NAME كتبت نهاية الإدخالات المستخدمة فوق مرجع الأب الخاص به. ويجب أن يبدو المرشح مثل ما يكتبه Windows: اسم UTF-16 صالح بلا أحرف تحكم أو فواصل مسارات، وأربعة أوقات بين 1980 و2100، ومساحة أسماء معروفة، وأعلام سمات معروفة. ومرجع الأب الذي يتجاوز 32 بت هو بايتات كُتبت فوقه، ويُترك فارغًا.

تُطبَّق مصفوفة تسلسل التحديث (update sequence array) لكل سجل. والقطاع الذي لا ينتهي بقيمة تسلسل التحديث قد كُتب جزئيًا؛ ويقرأ Juntei السجل كما هو ويسمّي القطاعات في Problems.

استراتيجية التحقيق

  1. ابدأ بالأسماء غير المنسوخة في المساحة الراكدة الواردة في الملخص، ثم صفِّ باستخدام --slack-only --no-copies.
  2. ابحث عن FileEntry في $MFT. يعني FileSequence المماثل الملف نفسه؛ أما القيمة الأعلى فتعني أن السجل حُرّر منذ ذلك الحين، وربما أُعيد استخدامه.
  3. ابحث عن الاسم في دفتر يومية USN لمعرفة متى حُذف أو أُعيدت تسميته.
  4. قارن أوقات $FILE_NAME بأوقات $STANDARD_INFORMATION في $MFT للكشف عن التلاعب بالطوابع الزمنية (timestomping).
  5. اربط ذلك بـ Prefetch وLNK وJump Lists وسجلات الأحداث لمعرفة كيفية استخدام الملف.

مزيد من التفاصيل