بسم الله الرحمن الرحيم
السلام عليكم ورحمة الله وبركاته
اللهم علمنا ما ينفعنا وانفعنا بما علمتنا انك انت السميع العليم وبعد
==========> Dll File Injector <==========
بحمد الله وبفضله قد شرحنا سابقا الهوك ومفهومه واّليته
وقد قلنا سابقا بان الـHook
عملية فلترة وتنقية للـAPI والـFunctions
نحن نريد تنقية API ، اي بمعنى اخر نريد بدل استدعاء WinAPI الاصلية يتم استدعاء الـFunction الخاص بنا ليتم الفلترة والتنقية كما نريد ، ولكن كيف سوف يتم المرور على الـFunction الخاص بنا ، وهو اصلا ليس جزئا من البرنامج نفسه ؟ وكيف سوف يتم تمرير الـParameters الخاصة بالاستدعاء الى الـFunction الخاص بنا والـFunction الخاص بنا للفلترة غير محمل بالذاكرة اصلا ؟
ومن هنا جائت الحاجة الى Dll File Injector
اذ اننا سوف نقوم بتشغيل ملف Dll داخل Process اخر ، اي نحن بحاجة لحقن ملف Dll داخل Process
(وذلك الـDLL يحتوي على Function الفلترة وايضا يحتوي على اكواد عمل الـHook على الـAPI التي نريد ) ليتم عمل هوك على الـAPI المطلوبة ، وليتم تمرير الاجرائات المستخدمة على الـFunction الخاصة بنا داخل نفس البرنامج اي بدون الحاجة لبرامج خارجية او او ...
حسنا ! ، بالبداية حتى ننشئ هذا Dll File Injector
نحتاج لنعرف قرابة 5 API's ، وربما لن نتطرق لشرح كافة الـParameters الخاصة بها شرحا وافيا الا ما نحتاجه
الان ، بالبرنامج العادي الذي تبرمجه كمبرمج ! كيف يتم تحميل DLL File داخله ؟
يتم ذلك عن طريق LoadLibrary API (ادخل لتقرا عنها اذا كنت لا تعرفها)
==========> LoadLibrary API <==========
HMODULE WINAPI LoadLibrary(
_In_ LPCTSTR lpFileName );
هذه الـAPI تقوم بتحميل الـDLL File داخل البرنامج
وتاخذ 1Parm وهو مسار المكتبة او اسمها
_In_ LPCTSTR lpFileName
وتقوم بارجاع Handle المكتبة
طبعا هذا لو نحن برمجناه
لكن المشكلة باننا لسنا من برمجه ونحتاج الى حقن هذه الـDLL من برنامج خارجي وبطريقة غير رسمية تقريبا ...
==========> CreateRemoteThread API <==========
HANDLE WINAPI CreateRemoteThread(
_In_ HANDLE hProcess,
_In_ LPSECURITY_ATTRIBUTES lpThreadAttributes,
_In_ SIZE_T dwStackSize,
_In_ LPTHREAD_START_ROUTINE lpStartAddress,
_In_ LPVOID lpParameter,
_In_ DWORD dwCreationFlags,
_Out_ LPDWORD lpThreadId );
هذه الـAPI تقوم بانشاء Thread ، وهذه الـThread سوف يتم تحديد موضوعه ومحتواه ، اي ماذا يفعل وماذا سوف يستدعي من API ، فنحن نريد انشاء Thread داخل الـProcess المستهدف يستدعي LoadLibrary ببارميتر مسار مكتبة الـHOOK التي سوف نبرمجها لاحقا ليقوم الثرد بتحميل المكتبة الى الـProcess ومن ثم تشغيلها
وتاخذ 7 Parameters
ما يهمنا الاول ، والرابع والخامس
الاول - وهو Process Handle مقبض العملية التي تريد الحقن فيها
_In_ HANDLE hProcess
..........
_In_ LPTHREAD_START_ROUTINE lpStartAddress
..........
الخامس - وهو الـParamter الذي نريد ارفاقه للـFunction التي نريد استدعائها في الParameter الرابع
_In_ LPVOID lpParameter
تقوم بارجاع Handle الـThread الذي تم انشائه اذا نجحت العملية ، واذا فشلت ترجع NULL
نلاحظ في CreateRemoteThread API
الـParameters المستخدمة ! نحتاج الى تجهيزها
الان نلاحظ ! الـParameter الاول نوع Handle اي اننا نحتاج مقبض
وسوف نحصل عليه من OpenProcess API
==========> OpenProcess API <==========
HANDLE WINAPI OpenProcess(
_In_ DWORD dwDesiredAccess,
_In_ BOOL bInheritHandle,
_In_ DWORD dwProcessId );
ببساطة تاخذ 3 Parameters
نلاحظ الـParameter الاول ، وهو الصلاحيات التي نريدها وللاطلاع على الصلاحيات
طبعا اذا قمنا بالدخول على CreateRemoteThread API
نلاحظ باننا نحتاج صلاحيات هذه كافة
PROCESS_CREATE_THREAD, PROCESS_QUERY_INFORMATION,
PROCESS_VM_OPERATION, PROCESS_VM_WRITE, and PROCESS_VM_READ
او سوف نستخدم PROCESS_ALL_ACCESS ، لكن احذر عند استخدامها ، يمكن ان يفشل ولا سمح لك الـProcess بالحصول على كافة الصلاحيات
_In_ DWORD dwDesiredAccess
..........
اما الـParameter الثاني ، لن نتطرق لشرحه كثيرا ولا يعنينا ، لكن ! اذا كان هذا الـParameter قيمته TRUE
فان العمليات التي انشئت تحت هذا Process سوف يتم وراثتها من قبل الهاندل والعكس صحيح
_In_ BOOL bInheritHandle
..........
اما الـParameter الثالث ، فهو PID اي Process ID
_In_ DWORD dwProcessId
بعد ذلك اما ان تقوم الـAPI بارجاع الـHandle ويعني نجاحها او ان تقوم بارجاع NULL ويعني فشلها
نلاحظ في CreateRemoteThread API الـParameter الرابع
وهو البارميتر الذي نريد تمرير له عنوان الـAPI التي نريد استدعائها
ولنحصل على ذلك العنوان نستخدم ...
==========> GetProcAddress API <==========
FARPROC WINAPI GetProcAddress(
_In_ HMODULE hModule,
_In_ LPCSTR lpProcName
);
تاخذ 2 Parameters
الاول - هو Handle المكتبة التي نريد استدعاء منها الـAPI
وقد سبق الكلام عن استدعاء Handle للمكتبة عن طريق LoadLibrary API
_In_ HMODULE hModule
..........
الثاني - وهو اسم المكتبة والذي سوف يكون "LoadLibraryA"
لماذا LoadLibraryA
تدل على ANSI ، ونحن نريد تمرير عنوان المكتبة ، ANSI وليس UNICODE
_In_ LPCSTR lpProcName
اذا نجحت سوف تقوم بارجاع العنوان داخل المكتبة للـFunction المطلوبة وان لم تنجح سوف تقوم بارجاع NULL
نلاحظ في CreateRemoteThread API الـParameter الخامس
نلاحظ انه LPVOID اي انه Pointer وليس LPCSTR
لذلك يستحيل ان نمرر البارميتر الذي نريده مباشرة ، كـLPCSTR او String عادي ، لذلك نحتاج الى كتابته على الذاكرة الخاصة بالـProcess لتمريره ، والذاكرة الخاصة بالبروسس لا نريد الكتابة عليها عشوائيا ، حتى لا يحدث خلل ، وحتى لو اردنا الكتابة عليها عشوائيا نحتاج الى صلاحيات معينة ايضا
ولنقوم بذلك نحتاج الى 2 API's
بالبداية دعنا نتعرف على
==========> WriteProcessMemory API <==========
BOOL WINAPI WriteProcessMemory(
_In_ HANDLE hProcess,
_In_ LPVOID lpBaseAddress,
_In_ LPCVOID lpBuffer,
_In_ SIZE_T nSize,
_Out_ SIZE_T *lpNumberOfBytesWritten );
وهي API تستخدم للكتابة على الذاكرة نلاحظ انها تاخذ 5 Parameters
الاول - Process Handle وقد سبق شرح جلبه عن طريق OpenProcess API
مع العلم باننا نحتاج الى الصلاحيات
PROCESS_VM_WRITE and PROCESS_VM_OPERATION
ولا داعي لإعادة جلب Handle بهذه الصلاحيات لاننا استخدمنا الصلاحيات نفسها ضمن جلب صلاحيات لانشاء الـThread في CreateRemoteThread API
_In_ HANDLE hProcess
..........
الثاني - ويتم تمرير له العنوان الذي نريد الكتابة عليه
_In_ LPVOID lpBaseAddress
وسوف يتم الشرح عنه بالاسفل وكيف سوف نجلبه عن طريق API اخرى
..........
الثالث - وهو الـString الذي نريد كتابته
نلاحظ
LPCVOID
Long Pointer Char
وهو المتغير الذي سوف نحفظ فيه مسار مكتبة الـHook
_In_ LPCVOID lpBuffer
..........
الرابع - وهو طول عنوان المكتبة التي تم تمريرها في الـParamter الثالث
_In_ SIZE_T nSize
..........
الخامس - لا يهمنا ، ويتم تمرير له Pointer من نوع SIZE_T
ليتم تخزين فيه عدد البايتات الفعلية التي تمت كتابتها كما ترون _Out_
_Out_ SIZE_T *lpNumberOfBytesWritten
اذا تمت العملية بنجاح ترجع TRUE ، اذا فشلت NULL
الان WriteProcessMemory API سبق وقلنا بان الـParameter الثاني نريد تمرير له العنوان الذي نريد الكتابة عليه ، اي اننا نريد حجز جزء من الذاكرة بمقدار ما نريد كتابتة ( الـParameter الرابع ) ولفعل ذلك نحتاج الى
==========> VirtualAllocEx API <==========
LPVOID WINAPI VirtualAllocEx(
_In_ HANDLE hProcess,
_In_opt_ LPVOID lpAddress,
_In_ SIZE_T dwSize,
_In_ DWORD flAllocationType,
_In_ DWORD flProtect );
طبعا هي تقوم بحجز جزء من الذاكرة بالصلاحيات التي تريدها ونلاحظ ان لها 5 Parameters
الاول - Process Handle وقد تم شرح جلب Handle عن طريق OpenProcess API
وهذه الـAPI تحتاج الى صلاحية
PROCESS_VM_OPERATION
_In_ HANDLE hProcess
..........
الثاني - طبعا كما تلاحظون هو optional اختياري _In_opt_ ، وسوف نستخدم قيمة NULL له
لكن ببساطة هذه الـParameter يتم وضع فيه العنوان الذي نريد البدء منه في حجز الذاكرة
_In_opt_ LPVOID lpAddress
واذا قمنا باختيار عنوان محدد ، يمكن ان يفشل في الحجز فيه لذلك
سوف نستخدم NULL
ليختار المكان المناسب لحجز الذاكرة داخل الذاكرة
..........
الثالث - وهو مقدار المساحة التي نريد حجزها وسوف يكون طول مسار مكتبة الـHook
_In_ SIZE_T dwSize
..........
الرابع - وهو نوع المساحة التي نريد حجزها
وله اربع انواع بشكل رئيسي ! ولا نريد التكلم عنها جميعا لانها ليست موضوعنا
ويمكنك رؤيتها في المرجع الخاصة بالـAPI اعلاه
الا اننا سوف نقوم باستخدام نوع MEM_COMMIT
اذ ان هذه النوع يستخدم لتخزين المعلومات وهذا ما نريده
..........
الخامس - وهو صلاحيات الحماية التي نريد استخدامها
ويمكن رؤية جميع الصلاحيات من هنا
الان بما اننا نريد ان نكتب على الذاكرة ومن ثم سوف يتم قرائتها من قبل
يعني ذلك باننا نحتاج الى صلاحيات للكتابة والقرائة لذلك سوف نستخدم
PAGE_READWRITE
_In_ DWORD flProtect
سوف يتم ارجاع العنوان الذي تم فيه حجز الذاكرة ويعني ذلك نجاحها ، في حالة ارجاع NULL يعني ذلك
فشلها في حجز الذاكرة
==========> الان الخطوات البرمجية <==========
1- تعريف متغير ووضع فيه مسار المكتبة المطلوبة حقنها
2- جلب مقبض HANDLE للـProcess المراد حقنها
3- حجز ذاكرة بمقدار طول مسار المكتبة
4- كتابة المسار على الذاكرة المحجوزة
5- انشاء Thread ليقوم بتشغيل LoadLibraryA على المكتبة
6- اغلاق الـHANDLE
C++ CODE
#include <Windows.h>
#include <iostream>
void main() {
int ProcessID = 1760; // Process identifier
char* LibPath = "C:\\ProgrammingTest\\DllFile.dll"; // Dll File Path
HANDLE hProc = OpenProcess(PROCESS_ALL_ACCESS, FALSE, ProcessID); // Get Process Handle
LPVOID BufferAddress;
BufferAddress = VirtualAllocEx(hProc, NULL, strlen(LibPath) + 1, MEM_COMMIT, PAGE_READWRITE); // Allocate A Buffer And Get The Address
WriteProcessMemory(hProc, BufferAddress, LibPath, strlen(LibPath), NULL); // Write the LoadLibraryA API Parameter(DLL Path) On Memory Buffer(BufferAddress) .
// Create A Thread That Runs In The Virtual Address Space In The Process With LoadLibraryA With Our Parameter
HANDLE x = CreateRemoteThread(hProc, NULL, NULL, (LPTHREAD_START_ROUTINE)GetProcAddress(LoadLibraryA("Kernel32"), "LoadLibraryA"), BufferAddress, NULL, NULL);
CloseHandle(hProc);
if (x == 0) std::cout << "Injection Failed.\n";
else std::cout << "Injected Successfully.\n";
system("pause");
}
ملاحظات :
1- يمكنك تجربة الـInjector اعلاه ، قم ببرمجة ملف dll ليكون كتجربة كالتالي
#include <Windows.h>
void WINAPI DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) {
switch (Reason) {
case DLL_PROCESS_ATTACH: // Beginning
MessageBoxA(0, "Injected Successfully." , "M" , 0); break;
case DLL_PROCESS_DETACH: // At End
MessageBoxA(0, "End ...", "M", 0);
}
2- اغلق الـAnti-Virus
3- اذا كان البرنامج الذي تريد حقنه لديه صلاحيات Admin يجب ان يكون لديك ايضا نفس الصلاحيات
4- اذا كان البرنامج المراد حقنه x64 يجب ان تعمل Compile على x64 للـDll File وايضا Dll File Injector
إن أصبت فمن الله ، وإن اخطئت فمني ومن الشيطان
اترككم في امان الله ورعايته
اترككم في امان الله ورعايته
والسلام عليكم ورحمة الله وبركاته
DoneByM
عمل هوك ، صنع هوك ، فلترة دالة ، فلترة API ، القضاء على Function ، انشاء حماية ، منع استخدام Function ، كيفية عمل هوك ، كيفية عمل Hook ، هوك Detours ، هوك trampoline ، هوكات IAT , EAT ، Kernel32.dll , System32 , User32.dll , هوك Ring3 ، User Mode Hook, Kernel Mode Hook , الكتابة على الذاكرة
بارك الله فيك اخي على الشرح لكن لدي سؤال طالما خطر ببالي هل يمكن عمل حقن بالفجوال نت لاني اظن ان هذه اللغة قوية جدا ويستحيل الا يوجد بها هذا النوع فان كان ذلك فممكن ان تخصصوا قسم لشرح خفايا الدوت نت شكرا لكم
ردحذفيمكن برمجة هوك كامل بمكتبات .Net
حذفالا ان الاصل بمكتبات الـNative وسوف نتطرق فيما بعد الى .Net ان شاء الله ، لكن اذا تم الولوج الى .Net فورا سوف يصعب الفهم وتحدث مشاكل ، ولن يتم استيعاب العملية بشكل كامل
اضافة الى انه نحن نشرح Ring3 والاهم من ذلك Ring0 والتي بالطبع تحتاج عند برمجتها الى C , Delphi او اي لغة اخرى تدعم برمجة Drivers .sys ، ولا مجال للـ.Net في ذلك ، والـ.Net لن يزيد الامور الا تعقيدا
بارك الله بك اخي على الشرح وعلى ماتقدمه
ردحذف