3- DLL File Injector

بسم الله الرحمن الرحيم 

السلام عليكم ورحمة الله وبركاته 

اللهم علمنا ما ينفعنا وانفعنا بما علمتنا انك انت السميع العليم وبعد 

==========>  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
..........
الرابع - هو عنوان الـFunction التي نريد تشغيلها وهي LoadLibrary API لكن نحتاج لجلب عنوانها 
  _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
ومن خلال هذه الـParameter سوف نقوم بجلب هاندل عن طريق   LoadLibrary API للمكتبة التي تحتوي
لاننا نريد ان نستخدم   LoadLibrary API داخل الـProcess المستهدف
_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 

ولا داعي لإعادة جلب Handle لان الصلاحيات المطلوبة تم استخدامها نفسها في CreateRemoteThread API  
_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 , الكتابة على الذاكرة 



هناك 3 تعليقات:

  1. بارك الله فيك اخي على الشرح لكن لدي سؤال طالما خطر ببالي هل يمكن عمل حقن بالفجوال نت لاني اظن ان هذه اللغة قوية جدا ويستحيل الا يوجد بها هذا النوع فان كان ذلك فممكن ان تخصصوا قسم لشرح خفايا الدوت نت شكرا لكم

    ردحذف
    الردود
    1. يمكن برمجة هوك كامل بمكتبات .Net

      الا ان الاصل بمكتبات الـNative وسوف نتطرق فيما بعد الى .Net ان شاء الله ، لكن اذا تم الولوج الى .Net فورا سوف يصعب الفهم وتحدث مشاكل ، ولن يتم استيعاب العملية بشكل كامل

      اضافة الى انه نحن نشرح Ring3 والاهم من ذلك Ring0 والتي بالطبع تحتاج عند برمجتها الى C , Delphi او اي لغة اخرى تدعم برمجة Drivers .sys ، ولا مجال للـ.Net في ذلك ، والـ.Net لن يزيد الامور الا تعقيدا

      حذف
  2. بارك الله بك اخي على الشرح وعلى ماتقدمه

    ردحذف

يمكنك النقل من المدونة كيف ما تشاء وبدون ذكر المصدر