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

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

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

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

Kernel processor control region

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

kernel processor control block

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

pcr-command-windbg

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

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

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

PsGetCurrentProcess

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

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

KTHREAD_APCState

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

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

EProcess

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

PsActiveProcessHead

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

validlist_command

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

taskmgr1

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

taskmgr2

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

taskmgr3

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

DKOM

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

OpenProcess

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

KDVersionBlock

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

 


 

[1] Direct Kernel Object Manipulation

[2] Kernel  processor control region

[3] kernel processor control block

[4] Display Linked List

[5] Cross-View Detection Mechanism

AHA

قطره ای از دریای بیکران IT

More Posts

پاسخ دهید

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