EDR
Call Stack
فرض کنید یه برنامه داریم
main()
↓
Function_A()
↓
Function_B()
↓
Function_C()
`یعنی main اومده Function_A رو صدا زده
Function_A
هم Function_B رو صدا زده
Function_B
هم Function_C رو صدا زده
حالا وقتی Function_C داره اجرا میشه
میشه یه تصویر از مسیر فراخوانیهایی که باعث رسیدن برنامه به این نقطه شدن داشت
به زبان خیلی ساده
میتونیم پرسیم
این Function از کجا به اینجا رسید
یه تصویر ساده از Call Stack
┌──────────────────┐
│ Function_C │ ← الان اینجاییم
├──────────────────┤
│ Function_B │
├──────────────────┤
│ Function_A │
├──────────────────┤
│ main() │
└──────────────────┘
به این زنجیره میگیم
Call Stack
البته در سیستم واقعی موضوع کمی پیچیده تر از این تصویر ساده ست
چون Stack واقعا فقط اسم Function ها رو نگه نمیداره اطلاعات مختلفی مثل Stack Frame و Return Address و Local Data و موارد دیگه میتونن در Stack قرار داشته باشن
فعلا برای اینکه مفهوم رو درست بگیریم
همین تصویر ساده کافیه
چرا Call Stack برای EDR مهمه
فرض کنید یه API حساس اجرا شده
خود API به تنهایی همیشه اطلاعات کاملی درباره اینکه چه مسیری باعث رسیدن به اینجا شده در اختیار ما نمیذاره
اینجاست که Call Stack میتونه Context بیشتری بده
مثلا:
Sensitive Operation
↑
Function_B
↑
Function_A
↑
Application
حالا EDR میتونه به این فکر کنه
این عملیات از چه مسیری به وجود اومده
ایا این مسیر با رفتار معمول این برنامه جور درمیاد
مثلا فرض کنی یه نرم افزار Backup داریم
Backup.exe
↓
BackupEngine.dll
↓
Memory Manager
این مسیر کاملا میتونه طبیعی باشه
چون برنامه Backup داره کار مربوط به خودش رو انجام میده
حالا یه حالت دیگه رو تصور کنید
Unknown Memory
↓
Unusual Execution
↓
Sensitive Operation
اینجا داستان یه مقدار مشکوک تر میشه
چون مسیر اجرای عملیات با چیزی که انتظار داریم فرق داره
ولی یه نکته خیلی مهم
غیرعادی بودن Stack به تنهایی یعنی حمله اتفاق افتاده نیست
ممکنه دلیل کاملا قانونی داشته باشه
پس EDR حرفهای فقط با دیدن یه Stack عجیب نمیاد حکم صادر کنه
Stack Walking
حالا فرض کنید یه ابزار امنیتی میخواد Stack یه Thread رو بررسی کنه
به صورت خیلی ساده میتونه چنین مسیری رو بررسی کنه
Thread
↓
Stack
↓
Return Addresses
↓
Loaded Modules
↓
Memory Regions
یعنی ابزار میاد ادرس هایی که توی مسیر اجرای Thread وجود دارن رو بررسی میکنه
بعد میپرسه
این Address متعلق به کجاست
مثلا ممکنه چیزی شبیه این ببینیم
0x7FF... → known DLL
0x7FF... → known DLL
0x1A3... → private executable memory
دو تای اول ممکنه کاملا عادی باشن
ولی مورد آخر میتونه نیاز به بررسی بیشتری داشته باشه
چرا
چون حالا داریم میبینیم یکی از ادرس های مسیر اجرا به یه Memory Region خصوصی و قابل اجرا مربوطه
باز هم
این به تنهایی اثبات حمله نیست
فقط یه Signal محسوب میشه
اینجا یه نکته مهم درباره Stack داریم
Stack
حقیقت مطلق نیست
یعنی نمیشه فقط Stack رو دید و گفت
پس حتما اتفاق بدی افتاده
برنامههای واقعی میتونن Stack های خیلی پیچیدهای داشته باشن
مثلا:
JIT
Runtimeهای مختلف
Debugger
Instrumentation
Exception Handling
Thread Pool
همه اینا میتونن باعث ایجاد مسیرهای غیرمعمول در Stack بشن
پس Detection حرفهای معمولا فقط به یه Signal تکیه نمیکنه
ممکنه چندتا چیز رو کنار هم بذاره
مثلا:
Process
Thread
Memory
Call Stack
Network
Timing
و اطلاعات دیگه
حالا میرسیم به بخش جالبتر
Stack و Memory و Thread
تا اینجا درباره اینا جدا جدا صحبت کردیم
ولی توی دنیای واقعی اینا از هم جدا نیستن
یه EDR میتونه این اطلاعات رو کنار هم ببینه
Process
│
┌──────┴──────┐
▼ ▼
Memory Thread
│ │
│ ▼
│ Call Stack
│ │
└──────┬──────┘
▼
Behavior
یعنی به جای اینکه فقط بگه
این API خطرناکه
میتونه سوال خیلی بزرگتری بپرسه