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

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

Dynamic Linking

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

در مقابل این روش Static Linking یا پیوند ایستا وجود دارد . در این روش تمامی نیازمندی های یک فایل PE حین Compile کردن آن و قبل از اجرا به خود فایل پیوست میشوند . در این صورت حین اجرا دیگر نیازی به بارگذاری فایل های مورد نیاز نیست و این باعث بارگذاری و اجرای سریع تر میشود اما حجم فایل تولیدی بیشتر میشود زیرا تمامی نیازمندی های آن به آن پیوست شده است . 

در ساختار فایل PE یک Section به نام idata. مخفف Import Data میتواند وجود داشته باشد که شامل اطلاعات مربوط به واردات فایل است . Loader ویندوز از طریق بررسی این اطلاعات متوجه میشود فایل فعلی به چه فایل های دیگری و به کدام توابع صادراتی شان نیاز دارد .

بخش idata.

Import Directory Table

اولین ساختار در بخش idata. ، ساختار Import Directory Table است که شامل آرایه ای از ساختار های IMAGE_IMPORT_DESCRIPTOR است . هر کدام از اعضای این آرایه مربوط به یک فایل DLL وارد شده است و توصیف کننده اطلاعات آن است . این قسمت اندازه مشخصی ندارد و بسته به تعداد DLL های وارداتی تعداد اعضای آن متفاوت است برای نمایش انتهای این آرایه  ، در آخر آن مقداری داده ۰ (به اندازه اندازه یک ساختار IMAGE_IMPORT_DESCRIPTOR) قرار داده میشود . ساختار  IMAGE_IMPORT_DESCRIPTOR به این صورت تعریف شده است :

typedef struct _IMAGE_IMPORT_DESCRIPTOR {
    union {
        DWORD   Characteristics;
        DWORD   OriginalFirstThunk;
    } DUMMYUNIONNAME;
    DWORD   TimeDateStamp;
    DWORD   ForwarderChain;
    DWORD   Name;
    DWORD   FirstThunk;
} IMAGE_IMPORT_DESCRIPTOR;
typedef IMAGE_IMPORT_DESCRIPTOR UNALIGNED *PIMAGE_IMPORT_DESCRIPTOR;

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

OriginalFirstThunk : حاوی RVA مربوط به ILT فایل DLL وارداتی است (ILT فایل های DLL وارداتی در بخش بعدی یعنی Import Lookup Table قرار میگیرند که در ادامه کاربرد آن ها را توضیح خواهیم داد)

Name : حاوی RVA به یک رشته (string) است که نشان دهنده اسم فایل DLL وارداتی است .

FirstThunk : حاوی RVA مربوط به IAT فایل DLL وارداتی است (IAT فایل های DLL وارداتی در بخش های بعدی یعنی Import Address Table قرار میگیرند که در ادامه کاربرد آن ها را توضیح خواهیم داد) 

 

دقت کنید همانطور که گفته شد به ازای هر DLL که فایل PE از آن توابعی را وارد میکند ، یک ساختار IMAGE_IMPORT_DESCRIPTOR در بخش Import Directory Table وجود دارد . دو عضو مهم این ساختار OriginalFirstThunk و FirstThunk بوندن که به ترتیب به ILT و IAT فایل DLL وارداتی اشاره میکردند . در ادامه بررسی میکنیم این دو چه هستند .

Import Lookup Table (ILT)

به ازای هر فایل DLL وارداتی یک Import Lookup Table در فایل PE وجود دارد که IMAGE_IMPORT_DESCRIPTOR.OriginalFirstThunk مربوط به همان DLL در بخش Import Directory Table به این ILT اشاره میکند (در بخش قبلی اشاره شد) . 

هر ILT یک آرایه ای از اعداد ۳۲ بیتی (برای فایل های ۳۲ بیتی) یا اعداد ۶۴ بیتی (برای فایل های ۶۴ بیتی) است . هر کدام از این اعداد ۳۲ یا ۶۴ بیتی مشخص کننده یک تابع وارداتی از DLL مربوطه است . اگر بیت های این عدد را از راست به چپ شماره گذاری کنیم به طوری که کم ارزش ترین بیت شماره صفر را داشته باشد و پرارزش ترین بیت شماره ۳۱ (یا ۶۳ برای ۶۴ بیتی) ، ساختار این عدد به شکل زیر است :

بیت ۳۱ (یا ۶۳ برای ۶۴ بیت) : این بیت Ordinal/Name نام دارد که مشخص کننده این است که تابع با استفاده از ordinal یا name وارد شود . اگر این بیت ۰ باشد مشخص میکند که تابع با استفاده از name وارد میشود اما اگر ۱ باشد تابع با استفاده از ordinal وارد میشود .

بیت ۰ تا ۱۵ : اگر بیت Ordinal/Name برابر ۱ باشد ، این ۱۶ بیت مشخص کننده ordinal تابع وارداتی است . در این صورت بیت های ۱۶ تا ۳۰ (یا ۱۶ تا ۶۲ برای ۶۴ بیت)‌ برابر صفر خواهند بود .

بیت ۰ تا ۳۰ : اگر بیت Ordinal/Name برابر ۰ باشد ، این ۳۲ بیت حاوی یک RVA به یک ساختار Hint/Name است که دربردارنده نام تابع وارداتی است . 

هر ساختار Hint/Name به شکل زیر تعریف شده است :

typedef struct _IMAGE_IMPORT_BY_NAME {
    WORD    Hint;
    BYTE    Name[1];
} IMAGE_IMPORT_BY_NAME, *PIMAGE_IMPORT_BY_NAME;

برای هر تابع وارداتی که با استفاده از Name وارد میشود ، ابتدا مقدار عددی داخل عضو Hint به عنوان یک اندیس داخل Export Name Pointer Table فایل DLL وادراتی استفاده میشود . اگر تابع مورد نظر در همان اندیس بود که چه بهتر اما اگر در اندیس مورد نظر تابع وارداتی مدنظر نبود ، با استفاده از الگوریتم جستوجو دودوئی (Binary Search) رشته Ascii که در عضو Name ذخیره شده است در فایل DLL مقصد جستوجو میشود تا import شود. بنابراین در عضو Name که از نوع آرایه بایتی است ، اسم تابع وارداتی مدنظر ذخیره شده است . شاید سوال پیش بیاید که چرا اندازه این آرایه ۱ است ؟ مشکلی نیست این عضو فقط شروع رشته را نگهداری میکند ادامه رشته در بایت های بعدی نوشته خواهند شد .

Import Address Table (IAT)

قبل از بارگذاری فایل PE ، محتوای بخش Import Address Table دقیقا برابر  و همسان با بخش Import Lookup Table است . اما وقتی فایل به طور کامل بارگذاری شد و توابع وارداتی فایل نیز وارد شدند ، آدرس توابع وارد شده در بخش IAT جایگزین محتوای ILT میشوند . در اعضای Import Directory Table ، عضو IMAGE_IMPORT_DESCIRPTOR.FirstThunk به IAT مربوط به DLL مربوطه اشاره میکند . در بخش IAT آدرس توابع وارد شده که ۳۲ بیتی است (یا ۶۴ بیتی برای فایل های ۶۴ بیتی) به همان ترتیبی که ILT های مربوط به آن توابع قرار گرفته اند ، در IAT نوشته میشوند . نهایتا وقتی فایل PE اجرا میشود ، از طریق خواندن بخش IAT آدرس توابع وارد شده در حافظه اش را پیدا میکند و آن ها را صدا میزند .

مشاهده توابع وارداتی فایل PE در PE-BEAR

اگر فایل calc.exe یا هر فایل دیگری را در PE-BEAR باز کنیم به راحتی میتوانیم با مراجعه به سربرگ Imports توابع وارداتی را ببینیم :

در بخش Imports دو لیست میبینیم . لیست بالایی اسم فایل های DLL را دربردارد که هر کدام از آن ها را انتخاب کنیم توابع وارداتی از همان DLL در لیست پایینی نمایان میشود .

مارا دنبال کنید

پست های مرتبط

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

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

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

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

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

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

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

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

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

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

نظرات

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

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