برای طرح سوال و دسترسی به آموزش ها  کانال ما در تلگرام بپویندید  

آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش سوم

در ادامه بحث های مطرح شده در آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش اول  و همچنین آنالیز ساختار ویندوز و روت کیت های سطح هسته-بخش دوم ادامه بحث را دنبال خواهیم کرد.

یکی دیگر از تکنیک های که روت کیت ها استفاده می نمایند درواقع می توان گفت نسل جدیدتر روت کیت ها، استفاده از تکنیک DKOM[۱] نام دارد. در این تکنیک ساختار های کرنل را تغییر میدهیم . ساختارهایی مانند لیست پروسه های فعال ، درایورها.

در این روش هیچگونه هوک و یا تغییری در جداولی مانند SSDT,IDT انجام نمیدهیم. روت کیت ها می توانند با Unlink نمودن یک شی EPROCESS از ActiveProcesLinks خود را پنهان نمایند و پروسه ای را از دید تابع ZwQuerySystemInformation() که برای بدست آوردن لیست پروسه های اجراشده در سیستم استفاده می نماییم پنهان نماید. کرنل از ساختاری به نام KPCR[۲] استفاده می کند. در این ساختار اطلاعات مهم و اساسی مانند IDT ، GDT و … ذخیره می شود. برای دسترسی راحتتر به KPCR کرنل آدرس آن را در نسخه های x86 ویندوز درون رجیستر fs و همچنین در ویندوزهای x64 در رجیستر gs ذخیره می کند. KPCR شامل ساختاری است به نام KPRCB[۳] است. KPCR مستند شده است ولی KPRCB یک ساختار خصوصی است و تنها در ntoskrnl مورد استفاده قرار می گیرد. این ساختار شامل اطلاعات درباره Scheduling پروسه ها می باشد.

در ساختار _KPRCB فیلدی به نا م CurrentThread وجود دارد که برایمان مهم می باشد همانطور در تصویر زیر می بینیم این فیلد از نوع ساختار _KTHREAD است:

برای مشاهده محتوای ساختارهای KPCR و KPRCB می توانیم از دستور های !pcr و !prcb استفاده نماییم، مقدار Current  را به یاد داشته باشید.

مقدار CurrentThread که در واقع آدرس ساختاری از نوع _KTHREAD است که در تصویر بالا مشاهده می کنیم. خوب بحث ساختار در ساختار شد که ممکن است برای اولین بار کمی گیج کننده باشد. حال این مقدار را کمی درون کدها و خود کرنل جستجو کنیم و دوباره به ادامه توضیحات برگردیم.

اطلاعات مربوط به پروسه درون ساختاری به نام EPROCESS قرار می گیرد. با استفاده از تابع PsGetCurrentProcess() می توانیم به آبجکت EPROCESS مرتبط با پروسه جاری دسترسی پیدا کنیم، این تابع از کتابخانه NtosKrnl می باشد ،

PEPROCESS  PsGetCurrentProcess(void);

این تابع ساختاری از نوع EPROCESS را بعنوان خروجی بر میگرداند، برای درک بهتر به کدهای اسمبلی این تابع نگاهی میاندازیم:

خوب همانطور که قبلا گفته شد کرنل برای دسترسی بهتر به ساختار KPCR آدرس آن را در رجیستر fs ذخیره می کند. حال برای دسترسی به CurrentThread بدینگونه عمل می کنیم:

CurrentThread(fs:124) = KPCR 	(fs)+ PrcbData (120)+ CurrentThread (4)

خوب در تصویر زیر میبینیم که براحتی این مقدار بدست آمد که در تصاویر قبل این آدرس را بدست آورده ایم:

در تصویر بالا میبینیم که ساختار KTHREAD دارای فیلدی به نام APcState است. در APcState  فیلد Process وظیفه نگهداری آدرس ساختاری از نوع EPROCESS را بعهده دارد. مقدار 0x44 برای دسترسی به این مقدار است.

نکته قابل ذکر است که EPROCESS ساختارش با KPROCESS متفاوت و یا ETHREAD با KTREAD ، حال سوال ممکن است پیش آید که چرا در تصویر بالا ما به ساختار KPROCESS رسیدیم درصورتی که هدف EPROCESS بود!؟ ساختار EPROCESS را در تصویر زیر میبینیم که وقتی به KPROCESS برسیم و آدرس را بدست آوریم در واقع به EPROCESS رسیده ایم:

در تصویر بالا عضوی به نام ActiveProcessLinks وجود دارد که از نوع لیست پیوندی دو طرفه است. بنابراین بایستی دارای Head باشد. آدرس گره Head را می توان از nt!PsActiveProcessHead بدست آوریم حال با استفاده از دستور dl[۴]  این لیست را مشاهده می کنیم:

PsActiveProcessHead دارای مقدار 0x8055a258 است و کامند dl از این آدرس شروع به پیمایش لیست می کند. برای اینکه بدانیم لیست پیوندی تمامی ساختار از ابتدا تا انتها لیست صحیح و دارای آدرس معتبر هستند، از دستور زیر استفاده می کنیم:

آدرس گره Head را بدست آوریم حال در لیست پروسه ها میخواهیم تغییرات ایجاد کنیم، در تصویر زیر تسک منیجر قبل از تغییرات را می بینید:

با استفاده از کامند  kd> ed nt!PsActiveProcessHead آدرس های FLink,Blink لیست پیوندی را تغییر می دهیم و چند گره را از لیست جدا می کنیم:

در تصویر بالا مشاهده می کنیم پروسه system از لیست حذف شده است،  یا می توان گره Head را تغییر دهیم تا FLink,Blink به خود Head اشاره نمایند. تصویر زیر بعد از تغییرات است:

تمامی پروسه را از لیست حذف کردیم ولی پروسه ها در حال اجرا هستند، تصویر زیر ساختار ها و روند انجام حذف نمودن یک پروسه از لیست را به تصویر کشانده است:

تکنیک DKOM توسط روت کیت FU,FUTo مورد استفاده قرار گرفت. BlackLight نیز برای شناسایی پروسه های فعال بصورت bruteforce تابع OpenProcess() را با تمامی PID ها در محدوده 0x00 تا  0x41DC اجرا می کند، روند اجرای تابع OpenProcess را در تصویر زیر مشاهده می کنیم که در انتها با استفاده از PspCidTable لیست پروسه ها برگردانده می شود:

بعد از بدست آوردن لیست پروسه ها با استفاده از این تکنیک، با استفاده از یک تکنیک قدیمی از تابع CreateToolhelp32Snapshot()  لیست دومی از پروسه های فعال را بدست میاورد، حال اگر اختلافی بین این دو لیست وجود داشته باشد آن را بعنوان پروسه مخفی شناسایی می کند[۵]. سپس روت کیت FUTo با استفاده از ایجاد تغییرات در PspCidTable پروسه ها را مخفی می کرد که BlackLight دیگر قادر به شناسایی آن نخواهد بود. PspCidTable وظیفه نگهداری تمامی پروسه ها و تریدها را بعهده دارد. درواقع PspCidTable به ساختار HANDLE_TABLE اشاره می کند. بر ای بدست آوردن آدرس PspCidTable می توانیم بصورت زیر عمل نماییم:

ساختار KPCR دارای فیلدی به نام KdVersionBlock است که در ساختار آن مقادیر مهم و ضروری وجود دارد بعنوان مثال آدرس PspCidTable و یا PsActiveProcessHead و …. که در تصویر بالا براحتی می توان آنها را مشاهده کرد. در آفست 0x80 از این ساختار مقدار PspCidTable قرار دارد، در آفست 0x78 از این ساختار نیز مقدار PsActiveProcessHead قرار دارد.

 


 

[۱] Direct Kernel Object Manipulation

[۲] Kernel  processor control region

[۳] kernel processor control block

[۴] Display Linked List

[۵] Cross-View Detection Mechanism


انتشار

در

, , ,

توسط

نظرات

دیدگاهتان را بنویسید

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