تکنیک‌های اجرا و تزریق shellcode با استفاده از پاورشل
مقاله
  • ۳۰ بهمن ۱۴۰۲
  • Learning Road Map
  • ۶ دقیقه خواندن

تکنیک‌های اجرا و تزریق shellcode با استفاده از پاورشل

یکی از چالش‌هایی که تمام تیم‌های قرمز هنگام اجرای عملیات‌‌های ارزیابی خود با آن مواجه می‌شوند، اجرای کد و ابزارهایشان بر روی سیستم‌عامل‌ها بدون ایجاد حساسیت در راهکارهای امنیت Endpoint مانند آنتی‌ویروس و EDR‌ است. به عبارت دیگر گاهی نیاز دارند تا این راهکارهای امنیتی را دور بزنند. تکنیک‌ها و روش‌های متعددی با این هدف به صورت مستمر در دنیا معرفی و ارایه می‌شوند، راهکارهای امنیتی تلاش می‌کنند تا این تکنیک‌ها را شناسایی و بی‌اثر کنند اما از طرف مقابل هم، نفوذگران روش‌های جدیدی برای دور زدن آن‌ها ارایه می‌کنند. این چرخه و جدال، سال‌هاست که بین نفوذگران و شرکت‌های امنیتی جریان دارد. در این مقاله یکی از روش‌های موثر که برای دور زدن آنتی‌ویروس ‌و EDR در سیستم‌عامل‌های ویندوز کاربرد دارد را با استفاده از PowerShell بررسی می‌کنیم. تزریق و اجرای shellcode، یکی از روش‌های مورد علاقه‌ی تیم‌های هکری و تیم‌های قرمز برای نصب و اجرای payloadهایشان بر روی سیستم قربانیان است. اما shellcode اساسا به چه معناست؟ «Michael Sikroski»، در تعریف خود shellcode‌ را این‌چنین معرفی می‌کند: «اصطلاحی که به‌طور عام برای توصیف هر کد قابل اجرا به صورت مستقل، به کار برده می شود». اغلب شرکت‌های تولید کننده‌ی نرم‌افزارهای تست نفوذ مانند Empire، Cobalt Strike یا Metasploit از shellcode generatorهای مخصوص به خود در داخل ابزارهایشان استفاده می‌کنند. shellcode generatorها فارغ از این‌که محصول کدام شرکت باشند، معمولا از فرمت Binary یا Hex بهره می‌برند.  

چرا از shellcodeها برای اجرایpayload استفاده می‌کنیم؟

استفاده از shellcode ها در ارزیابی تیم قرمز به ما این اجازه را می‌دهد تا در انتخاب و استفاده از نوع payload بسیار منعطف باشیم. در واقع با استفاده از shellcode می‌توانیم برنامه‌ها و اسکریپت‌های مختلف خود را اجرا کنیم بدون این‌که نگران شناسایی آن‌ها توسط EDR یا آنتی‌ویروس‌ها باشیم. به عنوان مثال روش و تکنیک‌های مختلفی مانند رمزنگاری و کد گذاری جهت کوتاه کردن shellcode ها وجود دارد که کار را برای محصولات EDR در پیدا کردن اینshellcode ها بسیار سخت می‌کند. بنابراین در فرآیند تیم قرمز می‌توان قابلیت‌ها سازمان مورد ارزیابی را در زمینه‌ی شناسایی بدافزارها نیز بررسی و تحلیل کرد.  

مقایسه‌ی Shellcode Injection و Shellcode Execution

یکی از مهم‌ترین قسمت‌های ارزیابی هر تیم قرمز توسعه‌ی ابزارهایی است که بتواند به صورت موفقیت آمیز، قابل اعتماد و بی سرو صدا در سیستم هدف اجرا شود. Payload ها می‌توانند shellcode را از درون پروسس خود اجرا کنند یا آنها را به یک آدرس از یک پروسس دیگر تزریق کنند تا shellcode را به صورت کامل اجرا کند. در این مقاله ما به بررسی روش دوم یعنی تزریق shellcode در حافظه‌ی سیستم‌عامل با استفاده از پاورشل می‌پردازیم. تزریق shellcode در واقع تکنیکی است که تیم‌های قرمز و همچنین مهاجمین خرابکار از آن استفاده می کنند تا از شناسایی شدن توسط EDR‌ یا سایر راهکارهای امنیتی مشابه سازمان‌ها جلوگیری کنند. لازم به ذکر است که بسیاری از محصولات EDR فرآیندهای شناسایی خود را بر اساس رفتار مورد انتظار در پروسس‌های قانونی ویندوز پیاده‌سازی کرده‌اند. به عنوان مثال، مهاجمی که از Mimikatz با یک پروسس دلخواه ویندوز مثلا DefinitelyNotEvil.exe استفاده می‌کند ممکن است شناسایی و بلاک شود، چرا که یک EDR انتظار ندارد که این پروسس (DefinitelyNotEvil.exe) برای فعالیت عادی خود نیاز به دسترسی به حافظه‌ی پروسس lsass.exe را داشته باشد. اما در صورت اجرای Mimikatz با یک پروسس دیگر ویندوز مانند svchost.exe که برای انجام فعالیت‌های خود به صورت مداوم با lsass.exe در ارتباط است، این امکان وجود دارد که از شناسایی شدن توسط EDR جلوگیری کرد چرا که EDR این فرآیند را به عنوان یک رفتار مورد انتظار و عادی می‌بیند. لازم به توضیح است که پروسس svchost.exe برای انجام وظایف روزمره‌ی خود نیاز دارد تا به دفعات با پروسس lsas.exe‌ در ارتباط باشد و اگر Mimikatz را نیز اجرا کند، از نظر EDR یک رفتار عادی به نظر می‌رسد. بنابراین می‌بینیم که با تزریق بدافزار خود در راستای اجرا شدن با یک پروسس قانونی که به درستی انتخاب شده باشد می‌توان از شناسایی شدن توسط راهکارهای امنیتی پیشرفته‌ی سازمان‌ها گریخت. در ادامه ۳ روش متفاوت و پرکاربرد در اجرای shellcode را به صورت خلاصه معرفی می‌کنیم:
  1. CreateThread
  2. CreateRemoteThread
  3. QueueUserAPC
هر کدام از این تکنیک‌ها مربوط به یکی از توابع windows API می‌باشد که مسوول اختصاص Thread به shellcode است و در نهایت منجر به اجرای shellcode می‌شود. دقت داشته باشید Create Thread مربوط به shellcode execution است در حالی‌که CreateRemoteThread و QueueUserAPC از توابعی هستند که در shellcode injection کاربرد دارند. در بخش‌های بعد، مراحل مربوط به هر کدام از این تکنیک‌ها به‌صورت موردی و خلاصه آورده شده است.  

روش CreateThread

  1. اختصاص حافظه‌ی مربوط به یک پروسس در حال اجرا
  2. کپی کردن shellcode در داخل حافظه‌ی اختصاصی داده شده
  3. تغییر تنظیمات محافظتی حافظه‌ی اختصاصی جدید به‌گونه‌ای که اجازه‌ی اجرای کد از داخل فضای حافظه را بدهد
  4. ایجاد یک thread با یک آدرس پایه از بخش حافظه‌ی اختصاص داده شده
  5. صبر کردن (Wait) بر روی thread handle تا زمانی که Return رخ دهد
 

روش CreateRemoteThread

  1. شناسایی و دریافت ID‌مربوط به یک پروسس مورد نظر جهت انجام تزریق در آن
  2. باز کردن پروسس هدف
  3. اختصاص یک حافظه‌ی قابل اجرا در پروسس هدف
  4. نوشتن shellcode در داخل حافظه‌ی اختصاص داده شده
  5. ایجاد یک Thread‌ در پروسس Remote با آدرس شروع بخش حافظه‌ی اختصاص داده شده
 

QueueUserAPC

  1. شناسایی و دریافت ID‌مربوط به یک پروسس مورد نظر جهت انجام تزریق در آن
  2. باز کردن پروسس هدف
  3. اختصاص یک حافظه‌ی قابل اجرا در پروسس هدف
  4. نوشتن shellcode در داخل حافظه‌ی اختصاص داده شده
  5. تغییر تنظیمات محافظتی حافظه‌ی اختصاصی جدید به‌گونه‌ای که اجازه‌ی اجرای کد از داخل فضای حافظه را بدهد
  6. ایجاد یک Thread‌ در پروسس Remote با آدرس شروع بخش حافظه‌ی اختصاص داده شده
  7. ثبت یک Thread در صف، به منظور اجرا در زمان قرار گرفتن در حالت «alertable»
  8. بازیابی Thread‌به‌گونه‌ای که در حالت «alertable» قرار گیرد
در ادامه ویدیوی آموزش یک نمونه از اجرای shellcode با استفاده از روش CreateThread را می‌توانید تماشا کنید. اسکریپت استفاده شده در این ویدیو، از اینجا قابل دریافت است (رمز فایل فشرده ravinacademy می‌باشد). اگر علاقه‌مند به فراگیری و درک عمیق‌تر تکنیک‌های ذکر شده هستید، این تکنیک‌ها به همراه تعداد زیادی از تکنیک‌های پیشرفته‌ی دیگر در دوره «پاورشل برای هکرها» به صورت عملی تدریس می‌شود. همچنین در صورت علاقه‌مندی، متن کامل این مقاله را می‌توانید اینجا مطالعه کنید.