TAHA
10-28-2009, 09:00 PM
روشهای بررسی وجود یک دیباگر رو میشه از نظر سطح دسترسی ، به دو دستهء Ring 3 ( سطح کاربر ) و Ring 0 ( سطح کرنل ) طبقه بندی کرد . سعی میکنم طی چند نوشته کوتاه و حتی الامکان ساده ، روشهای متداول هر کدام از این دسته ها رو معرفی کنم . بدیهیه که این روشها ، شناخته شده و متداول هستند و برای کاربرد مناسب اونها ، باید از خلاقیت استفاده کرد .
شناسائی دیباگر در سطح کاربر
1. استفاده از API های ویندوز : CheckRemoteDebuggerPresent و IsDebuggerPresent . به MSDN مراجعه کنید .
2. استفاده از SEH یا Structured Exception Handling : عموما" هنگام استفاده از یک دیباگر یک یا تعدادی Breakepoint موجوده ؛ اگر نرم افزار دارای Thread خاصی باشه که تو همهء روتینهای برنامه لااقل یکبار فراخوانی بشه و با برانگیختن یک استثناء زمان اجرای مجازی دائما" روتینهای SEH رو فراخوانی کنه ، بالاخره یکجا ، Hardware Breakpoint های دیباگر گیر خواهند افتاد . طبیعیه که این روش باعث کاهش کارائی نرم افزار نمیشه چون صرفا" قسمتهای خاصی که نیاز به حفاظت دارند رو پوشش میده که قاعدتا" بخشهای کوچک و خاصی از برنامه هستند . رجوع به تاپیک همه چیز دربارهء SEH .
3. Process Injection : بررسی مورد دیباگرهای مورد نظر و کسب اطلاع از فضاهای اختصاص نیافتهء حافظه در قسمتهای بالای محدوده آدرسی پروسه اصلی و آنگاه تلاش برای تخصیص حافظه ( VirtualAllocEx ) و دسترسی به این نقاط روی کلیه پروسه های سیستم و بررسی خطاهای بازگردانده شده . اگر و فقط اگر خطای دریافت شده ، دربارهء Commit نشدن آدرس مذکور بود ، دیباگر "مورد نظر" فعال است . رجوع به تاپیک Process Injection .
4. یکی از رکوردهای PEB ( یا Process Environment Block ) بنام NtGlobalFlag اگر 0x70 بود دیباگری وجود دارد . PEB روی ویندوز اکس پی از آدرس 0x7ffdf000 ( یا همان FS:0x30 ) شروع میشه ، روی سایر نسخ ویندوز ممکنه این آدرس تغییر کنه یا کرده باشه یا نکرده باشه ، هر چند عموما" این آدرس ثابته ، اما تضمینی برای این مساله وجود نداره . تابعی برای دریافت PEB :
کد:
DWORD GetPEB()
{
DWORD* dwPebBase = NULL;
/* Return PEB address for current process
address is located at FS:0x30 */
__asm
{
push eax
mov eax, FS:[0x30]
mov [dwPebBase], eax
pop eax
}
return (DWORD)dwPebBase;
}
( کد رو از Phrack برداشتم ؛ خدایش بیامرزاد )
5. استفاده از ProcessHeap : تابع ProcessHeap همیشه هندل Heap پیش فرض رو برمیگردونه . اگر دیباگری وجود داشته باشه و از یک یا چند Memory Breakpoint هم استفاده کرده باشه ، قاعدتا" قبل از فراخوانی تابعی که قراره حافظه رو تخصیص بده و نهایتا" به اجرای ProcessHeap منجر بشه ( مثلا" malloc روی سی یا new روی دلفی و ... ) آدرس روتین SEH دیباگر بجای آدرس ProcessHeap بازنویسی شده ( که دیباگر بتونه وقوع دسترسی به اون آفست رو درک و شناسائی کنه و دوباره آدرس اصلی ProcessHeap رو جایگزین کنه و برنامه به کنترل عادی برگرده )
ادامه دارد
شناسائی دیباگر در سطح کاربر
1. استفاده از API های ویندوز : CheckRemoteDebuggerPresent و IsDebuggerPresent . به MSDN مراجعه کنید .
2. استفاده از SEH یا Structured Exception Handling : عموما" هنگام استفاده از یک دیباگر یک یا تعدادی Breakepoint موجوده ؛ اگر نرم افزار دارای Thread خاصی باشه که تو همهء روتینهای برنامه لااقل یکبار فراخوانی بشه و با برانگیختن یک استثناء زمان اجرای مجازی دائما" روتینهای SEH رو فراخوانی کنه ، بالاخره یکجا ، Hardware Breakpoint های دیباگر گیر خواهند افتاد . طبیعیه که این روش باعث کاهش کارائی نرم افزار نمیشه چون صرفا" قسمتهای خاصی که نیاز به حفاظت دارند رو پوشش میده که قاعدتا" بخشهای کوچک و خاصی از برنامه هستند . رجوع به تاپیک همه چیز دربارهء SEH .
3. Process Injection : بررسی مورد دیباگرهای مورد نظر و کسب اطلاع از فضاهای اختصاص نیافتهء حافظه در قسمتهای بالای محدوده آدرسی پروسه اصلی و آنگاه تلاش برای تخصیص حافظه ( VirtualAllocEx ) و دسترسی به این نقاط روی کلیه پروسه های سیستم و بررسی خطاهای بازگردانده شده . اگر و فقط اگر خطای دریافت شده ، دربارهء Commit نشدن آدرس مذکور بود ، دیباگر "مورد نظر" فعال است . رجوع به تاپیک Process Injection .
4. یکی از رکوردهای PEB ( یا Process Environment Block ) بنام NtGlobalFlag اگر 0x70 بود دیباگری وجود دارد . PEB روی ویندوز اکس پی از آدرس 0x7ffdf000 ( یا همان FS:0x30 ) شروع میشه ، روی سایر نسخ ویندوز ممکنه این آدرس تغییر کنه یا کرده باشه یا نکرده باشه ، هر چند عموما" این آدرس ثابته ، اما تضمینی برای این مساله وجود نداره . تابعی برای دریافت PEB :
کد:
DWORD GetPEB()
{
DWORD* dwPebBase = NULL;
/* Return PEB address for current process
address is located at FS:0x30 */
__asm
{
push eax
mov eax, FS:[0x30]
mov [dwPebBase], eax
pop eax
}
return (DWORD)dwPebBase;
}
( کد رو از Phrack برداشتم ؛ خدایش بیامرزاد )
5. استفاده از ProcessHeap : تابع ProcessHeap همیشه هندل Heap پیش فرض رو برمیگردونه . اگر دیباگری وجود داشته باشه و از یک یا چند Memory Breakpoint هم استفاده کرده باشه ، قاعدتا" قبل از فراخوانی تابعی که قراره حافظه رو تخصیص بده و نهایتا" به اجرای ProcessHeap منجر بشه ( مثلا" malloc روی سی یا new روی دلفی و ... ) آدرس روتین SEH دیباگر بجای آدرس ProcessHeap بازنویسی شده ( که دیباگر بتونه وقوع دسترسی به اون آفست رو درک و شناسائی کنه و دوباره آدرس اصلی ProcessHeap رو جایگزین کنه و برنامه به کنترل عادی برگرده )
ادامه دارد