ساختار فایل PE قسمت ۲ – Section ها

در قسمت قبلی مجموعه ساختار فایل های PE ، به بررسی بخش DOS HEADER & DOS STUB و NT HEADERS در فایل های PE پرداختیم . در این قسمت به بررسی Section های یک فایل PE خواهیم پرداخت .

همانطور که در قسمت قبلی اشاره شد ، یک فایل PE به طور کلی تشکیل شده از بخش های زیر است :

همانطور که در تصویر بالا مشاهده میکنیم در یک فایل PE پس از بخش NT HEADERS ، بخش مربوط به Section ها قرار میگیرد که خود شامل دو بخش Section Table و Sections است . 

Section در فارسی از نظر لغوی به معنای “بخش” است . در تعریف Section اینگونه میتوان گفت که هر فایل PE شامل چندین بخش (Section) است که داده های آن داخل Section هایش ذخیره شده اند . در واقع Section ها یک روش دسته بندی و جداسازی اطلاعات مختلف از یکدیگر در فایل های PE است . ما در فایل های PE بخش ها یا Section های مختلفی داریم که داخل هر کدام از آن ها یک سری اطلاعات خاص ذخیره میشود و هر Section یک اسم دارد . برای مثال ما در فایل های اجرایی PE یک Section به نام “text.” داریم که کد های اجرایی فایل PE داخل این Section ذخیره میشود . همینطور یک Section به نام “data.” داریم که داده های مقدار دهی شده درون آن ذخیره میشوند . 

در فایل های PE اجرایی چندین Section پیشفرض و با اهداف مشخص وجود دارد که در ادامه آن ها را معرفی میکنیم. نمونه هایی از این Section های پیشفرض همان text. و data. بودند که معرفی کردیم . 

Section Table

هر Section در فایل PE دارای یک Header است که اطلاعاتی مثل اسم آن Section , اندازه اش ، آدرس اش و … داخل Header مربوط به آن نوشته شده است . در ساختار فایل PE بخشی وجود دارد به نام Section Table که در این بخش Header های تمام Section های موجود در فایل PE , به ترتیب در آن قرار میگیرند . به عبارتی به ازای هر Section در فایل PE ، یک Header در بخش Section Table وجود دارد . 

در فایل winnt.h یک ساختار مخصوص Section Header به نام IMAGE_SECTION_HEADER تعریف شده است . به شکلی میتوان گفت بخش Section Table در فایل های PE یک آرایه ای از ساختار IMAGE_SECTION_HEADER است که تعداد اعضای آن برابر مقدار فیلد NumberOfSections در FileHeader است که در قسمت قبلی توضیح دادیم . این ساختار به شکل زیر تعریف شده است :

typedef struct _IMAGE_SECTION_HEADER {
  BYTE  Name[IMAGE_SIZEOF_SHORT_NAME];
  union {
    DWORD PhysicalAddress;
    DWORD VirtualSize;
  } Misc;
  DWORD VirtualAddress;
  DWORD SizeOfRawData;
  DWORD PointerToRawData;
  DWORD PointerToRelocations;
  DWORD PointerToLinenumbers;
  WORD  NumberOfRelocations;
  WORD  NumberOfLinenumbers;
  DWORD Characteristics;
} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER;

به بررسی فیلد های این ساختار میپردازیم .

Name : یک آرایه ۸ بایتی است که اسم Section در آن ذخیره میشود . اگر اسم Section کمتر از ۸ بایت باشد ، ادامه آرایه با صفر پر میشود در غیر این صورت اگر اسم Section دقیقا ۸ بایت باشد ، در کل این آرایه بدونه هیچ صفری در آخر آن نوشته میشود . دقت کنید اسامی بیشتر از ۸ بایت برای Section ها در فایل های اجرایی امروزی پشتیبانی نمیشود . 

PhysicalAddress و VirtualSize : همانطور که میبینید این دو مورد عضوی از یک union به نام Misc هستند . به عبارتی هر دو اینها دو اسم متفاوت هستند برای یک عضو . این عضو اندازه کل Section وقتی در حافظه بارگذاری میشود را به واحد بایت ذخیره میکند .

VirtualAddress : حاوی RVA اولین بایت این Section وقتی در حافظه بارگذاری میشود . 

SizeOfRawData : اندازه داده های مقداردهی شده (Initialized Data) داخل این Section روی دیسک در واحد بایت . این مقدار باید مضرب صحیحی از عضو FileAlignment در ساختار OptionalHeader باشد که در قسمت قبلی توضیح دادیم . اگر Section فقط حاوی داده های مقداردهی نشده (UnInitialized Data) باشد ، مقدار این فیلد صفر خواهد بود. 

به تفاوت میان فیلد های VirtualSize و SizeOfRawData دقت کنید . اولی اندازه Section وقتی در حافظه بارگذاری میشود را مشخص میکند ولی دومی اندازه داده های Section داخل فایل روی دیسک (و نه حافظه) . گاهی اوقات میتواند اندازه SizeOfRawData کوچک تر از VirtualSize باشد . در این صورت وقتی Section در حافظه بارگذاری میشود ، ادامه ی داده های Section با صفر پر میشود تا نهایتا اندازه آن به عددی که در فیلد VirtualSize مشخص شده است برسد .

PointerToRawData : آدرس شروع Section روی دیسک (offset) . این مقدار باید مضرب صحیحی از FileAlignment در OptionalHeader باشد .

PointerToRelocations , PointerToLineNumbers , NumberOfRelocations, NumberOfLineNumbers : در فایل های اجرایی امروزی برابر صفر خواهند بود .

Characteristics : این فیلد ویژگی های Section مثل اینکه آیا این Section حاوی کد اجرایی است یا نه. آیا حاوی داده مقدار دهی شده / مقدار دهی نشده است یا اینکه آیا این Section قابل اشتراک گذاری در حافظه است یا نه و خیلی ویژگی های دیگر که میتوانید مقادیر مختلف آن را از لینک زیر که مرجع اصلی است مطالعه کنید :

https://learn.microsoft.com/en-us/windows/win32/api/winnt/ns-winnt-image_section_header

 

Section های خاص در فایل PE

در فایل های PE میتوان به شکل دلخواه Section هایی با ویژگی های دلخواه تعریف کرد اما همانطور که پیش تر اشاره شد ، یکسری از Section ها در فایل های PE معنا های خاص دارند . این Section ها حاوی اطلاعاتی هستند که مورد نیاز Loader ویندوز هست تا بتواند از این فایل استفاده کند . طبق گفته مرجع اصلی ، خاص بودن این Section ها از طریق ویژگی های آن ها (فیلد Characteristics در Section Header) ، اسم Section یا اینکه مثلا یک جایی در OptionalHeader به داده های آن Section اشاره شده باشد مشخص میشود . برای مثال Section با نام text. حاوی کد های اجرایی فایل PE است . اگر یادتان باشد در OptionalHeader که قسمت قبلی معرفی کردیم فیلدی وجود داشت به نام AddressOfEntryPoint که به نقطه شروع کد های اجرایی فایل اشاره میکرد . این نقطه شروع در text. خواهد بود و از این جهت این یک Section خاص است .

در چند مورد از مرسوم ترین Section های خاص در فایل های PE را معرفی میکنیم :

text. : حاوی کد های اجرایی فایل PE

bss. : حاوی داده های مقدار دهی نشده (Uninitialized Data) 

data. : حاوی داده های مقدار دهی شده (Initialized Data)

edata. : اطلاعات مربوط به توابعی که این فایل PE صادر (Export) میکند در این Section ذخیره میشوند . (در مورد Export ها در قسمت های بعدی صحبت خواهد شد)

idata. : اطلاعات مربوط به توابعی که این فایل PE وارد (Import) میکند در این Section ذخیره میشود . (این بخش نیز در قسمت های بعدی توضیح داده میشود‌) 

rdata. : حاوی اطلاعات مقدار دهی شده فقط خواندنی (Read-Only)

برای مطالعه لیست کامل Section های خاص به مرجع رسمی مراجعه کنید .

بررسی Section های فایل های PE در PE-BEAR 

اگر یک فایل PE را در نرم افزار PE-BEAR که در قسمت قبلی معرفی شد باز کنیم ، این نرم افزار این قابلیت را دارد تا تمام Section های فایل به همراه ویژگی های آن Section ها را به ما نمایش دهد .  مثل قسمت قبلی فایل calc.exe را در ویندوز داخل نرم افزار PE-BEAR باز میکنیم و به تب Section Hdrs مراجعه میکنیم . همانطور که میبینید لیست تمام Section های داخل فایل به همراه اطلاعات مربوط به آن Section مثل آدرس شروع آن در حافظه ، اندازه آن ، ویژگی های آن و … به ما نمایش داده میشود :

جالب است بدانید نرم افزار PE-BEAR حتی به ما اجازه میدهد Section به یک فایل PE اضافه کنیم که برای مقاصد خاصی میتواند کاربردی باشد . در پست های آینده نمونه ای از کاربرد این موضوع را خواهیم داشت .

این آموزش متعلق به بخش مهندسی معکوس است

برای مشاهده تمام آموزش های مهندسی معکوس وبسایت مسترپایتون به بخش مهندسی معکوس مراجعه کنید

پست های مرتبط

مطالعه این پست ها رو از دست ندین!

ساختار فایل PE قسمت ۵ – Relocation ها

مشکل از آنجایی شروع میشود که ویندوز ، همیشه فایل های PE را در آن آدرسی از حافظه که انتظار میرود بارگذاری نمیکند و در این صورت خیلی از چیز ها بهم میریزد ! در این بخش از ساختار فایل PE به بررسی Relocation ها در فایل PE میپردازیم . اینکه اصلا Relocation به چه معناست و در فایل PE چگونه پیاده سازی میشود .

بیشتر بخوانید

ساختار فایل PE قسمت ۴ – واردات (Imports)

در قسمت قبلی صادرات فایل های PE را بررسی کردیم . قطعا وقتی بحث صادرات را داریم ، از طرفی واردات را هم خواهیم داشت . فایل های PE در ویندوز میتوانند توابع صادراتی فایل های دیگر را وارد (Import) کرده و از آن ها استفاده کنند. این رفتار مستلزم این است که خود فایل های PE دیگر که از صادرات آن ها استفاده میکنیم نیز در حافظه بارگذاری شوند که این کار وظیفه ی Loader ویندوز است .

بیشتر بخوانید

ساختار فایل PE قسمت ۳ – صادرات (Exports)

در سیستم عامل ویندوز ، فایل های PE میتوانند توابعی را صادر (export) کنند تا فایل های PE دیگر از طریق وارد (import) کردن ، از آن ها استفاده کنند . این رفتار را اغلب در فایل های DLL مشاهده میکنیم ولی در واقعیت هر فایل PE حتی فایل های اجرایی میتوانند export هایی داشته باشند .

بیشتر بخوانید

نظرات

سوالات و نظراتتون رو با ما به اشتراک بذارید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *