5- Detours Hook, 32-bit, 64-bit



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



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



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



==========> Detours Hook <==========
الاخوة الاعزاء ، تكلمنا في الدرس السابق عن كيفية تعطيل عمل API
وفي الدرس الذي قبله عن DLL File Injector 

والان سوف نقوم باذن الله ببرمجة DLL File اي سوف نقوم ببرمجة مكتبة الهوك ، حتى نقوم بحقنها ، ومن بعد تشغيلها ، لتقوم بعمل Hook ، ومن ثم يتم تمرير الـParameters على Filter Function الخاصة بنا داخل المكتبة 



وقد كان موضوع الدرس السابق كتابة تعليمة RTN ، وفي هذه الدرس ، سوف نقوم باستخدام Detours Hook ، حيث انه هوك يعتمد على كتابة تعليمة JMP على عنوان الدالة المطلوبة ، وسوف يتم القفز الى عنوان الفنكشن الخاص بنا ، حاملا معه الـParameters التي تم منها الاستدعاء، وهكذا يتم تحقيق الـHook

==========>   الخطوات البرمجية في برمجة Detours Hook Lib <==========

الاختلاف بين نظام 64-bit و 32-bit يكمن في التعليمات البرمجية التي سوف يتم كتابتها لتحقيق القفزة اضافة الى عمل كومبايل على النظام المناسب ، حيث ان ...

1- نظام 32-bit
يتم استخدام تعليمة JMP ، حيث انها تعليمة ياخذ بعدها طول 32-bit اي 4Byte ، هذه الطول ، هو عبارة الادرس المستهدف يطرح منه الادرس الحالي ويطرح منه 5 ، وبذلك يتم القفز الى الفنكشن الخاص بنا داخل مكتبة الـHook 
الان JMP قيمتها 0xE9 ، ومن ثم بعدها 4 Byte الفرق بين الادرس المستهدف والادرس الحالي ، ولهذه السبب يتم طرح 5 


2- نظام 64-bit
لا يمكننا هنا استخدام JMP لان الفرق سوف يكون 64-bit اي 8Byte وليس 4Byte 
لذلك ، سوف نقوم بتخزين عنوان الفنكشن المستهدف ( اي فنكشن الفلترة ) داخل RAX Register ، عن طريق MOV
ومن ثم سوف نقفز الى العنوان المخزن في RAX عن طريق JMP

أول سطر
__asm { MOV RAX, Address_8Bytes }
 MOV = 0x48 , RAX = 0xB8

ثاني سطر
__asm { JMP RAX }
JMP = 0xFF , RAX = 0xE0



الان نحتاج الى تعريف Function الفلترة الخاص بنا ، هذا الفنكشن يجب ان يملك نفس الـParameters الخاصة بالـFunction التي نريد ان تقوم بتنصيب الهوك عليها 
ويتم الحصول على تعريفات الـParameters إما عن طريق البحث في محركات البحث او داخل MSDN او اذا كنت تستعمل Visual Studio IDE ببساطة عند كتابة اسم الـFunction في C++ سوف تجد ...



ونلاحظ القيمة الراجعة من الـFunction بالاعلى وهي int


اذن بالبداية سوف يكون الكود الخاص بالـDLL كالتالي ( ليس void )  ...

BOOL WINAPI DllMain(HMODULE hDLL, DWORD Reason, LPVOID Reserved) { 
switch (Reason) { 
case DLL_PROCESS_ATTACH: 
}
return 1;
}

ثم نضيف Filter Function ... وسوف يكون للـMessageBoxA كالتالي ...
int WINAPI MsgBoxFilter(HWND hWnd, LPCSTR lpText, LPCSTR lpCaption, UINT uType) {
// Your Code Here :) ...
}

عند استخدام return في MsgBoxFilter حيث ترجع القيمة نفسها الى كود الاستدعاء ، يعني انت تتحكم بالقيمة الراجعة
اذن ، انتهينا من موضوع التجهيز وننتقل الى كتابة الهوك






C++ CODE 32-bit
BYTE JMP[5] = { 0xE9, 0x0, 0x0, 0x0, 0x0 }; // __asm { JMP Address_4Bytes }
#define BuffSizeX86 sizeof(JMP)

BOOL Hook_Det_x86(char LibName[], char API_Name[], LPVOID NewFun) {
        DWORD OrgAddress, OldProtect, JMP_Dist;

        OrgAddress = (DWORD)GetProcAddress(LoadLibraryA(LibName), API_Name);
        if (OrgAddress == NULL) return 0;

        JMP_Dist = (DWORD)NewFun - OrgAddress - BuffSizeX86;
        memcpy(&JMP[1], &JMP_Dist, 4);
        VirtualProtect((LPVOID)OrgAddress, BuffSizeX86, PAGE_EXECUTE_READWRITE, &OldProtect);
        memcpy((LPVOID)OrgAddress, JMP, BuffSizeX86);
        VirtualProtect((LPVOID)OrgAddress, BuffSizeX86, OldProtect, &OldProtect);

        return 1;
}

نلاحظ ، قمنا بتخزين عنوان الـAPI التي نريد عمل عليها HOOK داخل OrgAddress
 قمنا باحتساب الفرق بين Filter Function وهو NewFun وبينOrgAddress ثم تخزينه داخل JMP_Dist 

الان علينا تخزين الفرق ( JMP_Dist ) داخل JMP Array حتى نكون تعليمة الاسمبل كاملة
وقمنا بذلك عن طريق memcpy 
حيث ان الـParameter الاول هو Pointer Byte الـمستهدف للنسخ عليه
الـParameter الثاني هو الـPointer Byte المستهدف للنسخ منه على الـParameter الاول
الـParameter الثالث عدد البايتات التي تريد نسخها وهو 32bit - 4Byte

ثم قمنا باستخدام VirtualProtect API لتغيير الحماية على العنوان الذي نريد الكتابة عليه بصلاحيات PAGE_EXECUTE_READWRITE وقد قمنا بشرح VirtualProtectEx API سابقا والفرق بينها وبين الـVirtualProtect API ان VirtualProtectEx API اول Parameter فيها هو HANDLE  وVirtualProtect API  لا تحتوي على HANDLE  اي انها مختصة بالـProcess نفسه (لاننا سوف نحقن الـDLL داخل الـProcess المطلوب)

ثم قمنا بعد ذلك بنسخ JMP Array الى عنوان الـFunction التي نريد عمل عليها هوك ( OrgAddress 
ثم قمنا بارجاع الحماية الى ما كانت عليه عن طريق  VirtualProtect API 






C++ CODE 64-bit
BYTE MOV[10] = { 0x48, 0xB8, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }; // __asm { MOV rax, Address_8Bytes }
BYTE JMP_RAX[2] = { 0xFF, 0xE0 }; // __asm { JMP rax }
#define BuffSizeX64 (sizeof(MOV) + sizeof(JMP_RAX))

BOOL Hook_Det_x64(char LibName[], char API_Name[], LPVOID NewFun) {
        DWORD OldProtect;
        DWORD64 OrgAddress = (DWORD64)GetProcAddress(LoadLibraryA(LibName), API_Name);
        if (OrgAddress == NULL) return 0;

        memcpy(&MOV[2], &NewFun, 8);
        VirtualProtect((LPVOID)OrgAddress, BuffSizeX64, PAGE_EXECUTE_READWRITE, &OldProtect);
        memcpy((LPVOID)OrgAddress, MOV, sizeof(MOV));
        memcpy((LPVOID)(OrgAddress + sizeof(MOV)), JMP_RAX, sizeof(JMP_RAX));
        VirtualProtect((LPVOID)OrgAddress, BuffSizeX64, OldProtect, &OldProtect);

        return 1;
}

نلاحظ ، قمنا بتخزين عنوان الـAPI المراد عمل عليها HOOK داخل OrgAddress 
ثم قمنا بتخزين العنوان داخل MOV Array، لتكوين تعليمة الاسمبل MOV RAX, Adress
وقمنا بذلك عن طريق memcpy 
حيث ان الـParameter الاول هو Pointer Byte الـمستهدف للنسخ عليه
الـParameter الثاني هو الـPointer Byte المستهدف للنسخ منه على الـParameter الاول
الـParameter الثالث عدد البايتات التي تريد نسخها وهو 64bit - 8Byte

ثم قمنا باستخدام VirtualProtect API لتغيير الحماية على العنوان الذي نريد الكتابة عليه بصلاحيات PAGE_EXECUTE_READWRITE وقد قمنا بشرح VirtualProtectEx API سابقا والفرق بينها وبين الـVirtualProtect API ان VirtualProtectEx API اول Parameter فيها هو HANDLE  وVirtualProtect API  لا تحتوي على HANDLE  اي انها مختصة بالـProcess نفسه (لاننا سوف نحقن الـDLL داخل الـProcess المطلوب)

ثم قمنا بكتابة تعليمة MOV على عنوان الـAPI 
اي OrgAddress 

ثم بعد ذلك كتابة JMP بعدها 
وبعد ذلك قمنا بارجاع الحماية الخاصة بالذاكرة كما كانت عن طريق الـVirtualProtect API 



الشكل النهائي ...
C++ CODE 32-bit

C++ CODE 64-bit
ملاحظة : كما نرى في كلا الصورتين داخل MsgBoxFilter قمت باستخادم MessageBoxExA وليس MessageBoxA لان استخدام MessageBoxA سوف يقوم بعمل loop غير منتهي اي ان FiltetFun يستدعي MessageBoxA والـMessageBoxA يستدعي الـFilterFun


==========> Images <==========










إن أصبت فمن الله ، وإن اخطئت فمني ومن الشيطان 
اترككم في امان الله ورعايته 

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

DoneByM

عمل هوك ، صنع هوك ، فلترة دالة ، فلترة API ، القضاء على Function ، انشاء حماية ، منع استخدام Function ، كيفية عمل هوك ، كيفية عمل Hook ، هوك Detours ، هوك trampoline ، هوكات IAT , EAT ، Kernel32.dll , System32 , User32.dll , هوك Ring3 ، User Mode Hook, Kernel Mode Hook , الكتابة على الذاكرة 


هناك تعليق واحد:

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