الإغراء
في برمجة الحاسوب ، يُعرف مصطلح "الربط" بأنه مجموعة من التقنيات المستخدمة لتغيير أو تحسين سلوك نظام التشغيل ، أو التطبيقات ، أو مكونات البرامج الأخرى، وذلك عن طريق اعتراض استدعاءات الدوال أو الرسائل أو الأحداث المتبادلة بين مكونات البرامج . ويُطلق على الكود الذي يتعامل مع استدعاءات الدوال أو الأحداث أو الرسائل المعترضة اسم " الربط" .
تُعدّ دوال الربط ذات أهمية خاصة في نمط الدوال القالبية ، حيث يُمكن إضافة شيفرة مخصصة إلى الشيفرة العامة في فئة مجردة ضمن فئة فرعية. في هذه الحالة، تُعرَّف كل دالة ربط في الفئة المجردة بتنفيذ فارغ، مما يسمح بتوفير تنفيذ مختلف في كل فئة فرعية ملموسة.
يُستخدم الربط البرمجي لأغراضٍ عديدة، منها تصحيح الأخطاء وتوسيع الوظائف. ومن الأمثلة على ذلك اعتراض رسائل أحداث لوحة المفاتيح أو الفأرة قبل وصولها إلى التطبيق، أو اعتراض استدعاءات نظام التشغيل لمراقبة سلوك التطبيق أو تعديل وظيفته أو وظيفة مكون آخر. كما يُستخدم على نطاق واسع في برامج قياس الأداء، مثل قياس معدل الإطارات في ألعاب ثلاثية الأبعاد، حيث تتم عمليات الإدخال والإخراج من خلال الربط البرمجي.
يمكن أيضًا استخدام تقنية التشويش بواسطة البرامج الضارة. على سبيل المثال، غالبًا ما تستخدم برامج التجسس الخفية ، وهي برامج تحاول إخفاء نفسها عن طريق تزييف مخرجات استدعاءات واجهة برمجة التطبيقات التي من شأنها أن تكشف وجودها، تقنيات التشويش.
طُرق
عادةً ما تُضاف الخطافات أثناء تشغيل البرنامج، ولكن يمكن أيضًا استخدام هذه التقنية قبل بدء تشغيل التطبيق. سيتم شرح كلتا التقنيتين بمزيد من التفصيل أدناه.
تعديل المصدر
يمكن تحقيق عملية الاختراق عن طريق تعديل مصدر الملف التنفيذي أو المكتبة قبل تشغيل التطبيق، وذلك باستخدام تقنيات الهندسة العكسية . ويُستخدم هذا عادةً لاعتراض استدعاءات الدوال إما لمراقبتها أو استبدالها بالكامل.
على سبيل المثال، باستخدام أداة تفكيك التعليمات البرمجية ، يمكن تحديد نقطة دخول دالة داخل وحدة نمطية . بعد ذلك ، يمكن تعديلها لتحميل وحدة نمطية أخرى من المكتبة ديناميكيًا، ثم تنفيذ الطرق المطلوبة داخل تلك المكتبة المحملة. عند الاقتضاء، هناك طريقة أخرى مشابهة لتحقيق الربط، وهي تعديل جدول الاستيراد في الملف التنفيذي. يمكن تعديل هذا الجدول لتحميل أي وحدات نمطية إضافية من المكتبة، بالإضافة إلى تغيير التعليمات البرمجية الخارجية التي يتم استدعاؤها عند استدعاء دالة من قِبل التطبيق.
تتمثل إحدى الطرق البديلة لتحقيق ربط الدوال في اعتراض استدعاءات الدوال عبر مكتبة وسيطة . المكتبة الوسيطة هي نسخة من مكتبة يقوم التطبيق بتحميلها، وتحتفظ بكافة وظائف المكتبة الأصلية التي ستحل محلها. أي أن جميع الدوال المتاحة متطابقة تقريبًا بين المكتبة الأصلية والبديلة. يمكن تصميم هذه المكتبة الوسيطة لاستدعاء أي من وظائف المكتبة الأصلية، أو استبدالها بمجموعة جديدة كليًا من المنطق.
التفاف الرمز
يدعم رابط GNU خيار --wrap=fooسطر الأوامر. عند استخدامه، يستبدل الرابط جميع استدعاءات fooباستدعاءات __wrap_foo. يمكن الآن الإشارة إلى التعريف الأصلي لـ fooباستخدام الرمز __real_foo. [ 1 ] بما أن هذه الطريقة لا تستخدم الرابط الديناميكي ، فلا يمكن استخدامها إلا عندما يكون كود المصدر للبرنامج متاحًا ويمكن تعديل خطوة الربط في عملية البناء.
تعديل وقت التشغيل
قد توفر أنظمة التشغيل والبرامج وسائل لإدراج نقاط ربط الأحداث بسهولة أثناء التشغيل . ويُتاح ذلك شريطة منح العملية التي تُدرج نقطة الربط الصلاحيات الكافية للقيام بذلك. على سبيل المثال، يسمح نظام التشغيل مايكروسوفت ويندوز للمستخدمين بإدراج نقاط ربط يمكن استخدامها لمعالجة أو تعديل أحداث النظام وأحداث التطبيقات الخاصة بالحوارات وأشرطة التمرير والقوائم ، بالإضافة إلى عناصر أخرى. كما يسمح بإدراج أو إزالة أو معالجة أو تعديل أحداث لوحة المفاتيح والماوس . ويُقدم نظام لينكس مثالًا آخر حيث يمكن استخدام نقاط الربط بطريقة مماثلة لمعالجة أحداث الشبكة داخل النواة من خلال NetFilter .
عندما لا تتوفر هذه الوظيفة، يُستخدم شكل خاص من أشكال اعتراض الدوال، حيث يتم اعتراض استدعاءات دوال المكتبة التي يُجريها أحد العمليات. ويتم تنفيذ اعتراض الدوال بتغيير التعليمات البرمجية القليلة الأولى للدالة المستهدفة للانتقال إلى كود مُضاف. بدلاً من ذلك، في الأنظمة التي تستخدم مفهوم المكتبة المشتركة ، يمكن تعديل جدول متجه المقاطعة أو جدول واصفات الاستيراد في الذاكرة. وتعتمد هذه الأساليب أساسًا على نفس أفكار تعديل الكود المصدري، ولكنها تُغير التعليمات والهياكل الموجودة في ذاكرة العملية بعد تشغيلها.
نموذج التعليمات البرمجية
ربط جدول الأساليب الافتراضية
عندما تُعرّف فئةٌ ما دالةً (أو طريقةً) افتراضيةً أو ترثها، يُضيف المُصرّف مُتغيرًا عضويًا مخفيًا إلى الفئة يُشير إلى جدول الطرق الافتراضية (VMT أو Vtable). يضع مُعظم المُصرّفين مؤشر VMT المخفي في أول 4 بايتات من كل نسخة من الفئة. VMT هو في الأساس مصفوفة من المؤشرات إلى جميع الدوال الافتراضية التي يُمكن لنسخ الفئة استدعاؤها. في وقت التشغيل، تُضبط هذه المؤشرات لتشير إلى الدوال الصحيحة، لأنه في وقت الترجمة ، لا يُعرف بعد ما إذا كان سيتم استدعاء الدالة الأساسية أو نسخة مُعدّلة من الدالة من فئة مُشتقة (مما يسمح بتعدد الأشكال ). لذلك، يُمكن ربط الدوال الافتراضية عن طريق استبدال المؤشرات إليها داخل أي VMT تظهر فيه. يُظهر الكود أدناه مثالًا على ربط VMT نموذجي في نظام التشغيل Microsoft Windows، مكتوب بلغة C++. [ 2 ]
#include <iostream> #include "windows.h" using namespace std ; class VirtualClass { public : int number ; virtual void VirtualFn1 () // هذه هي الدالة الافتراضية التي سيتم استدعاؤها. { cout << "تم استدعاء VirtualFn1 " << number ++ << " \n\n " ; } }; using VirtualFn1_t = void ( __thiscall * )( void * thisptr ); VirtualFn1_t orig_VirtualFn1 ;void __fastcall hkVirtualFn1 ( void * thisptr , int edx ) // هذه دالة الربط التي سنجعل البرنامج يستدعيها بدلاً من دالة VirtualFn1 الأصلية بعد اكتمال الربط. { cout << "تم استدعاء دالة الربط" << " \n " ; orig_VirtualFn1 ( thisptr ); // استدعاء الدالة الأصلية. } int main () { VirtualClass * myClass = new VirtualClass (); // إنشاء مؤشر إلى نسخة مُخصصة ديناميكيًا من VirtualClass. void ** vTablePtr = * reinterpret_cast < void ***> ( myClass ); // إيجاد العنوان الذي يشير إلى قاعدة VMT الخاصة بـ VirtualClass (والتي بدورها تشير إلى VirtualFn1) وتخزينه في vTablePtr. DWORD oldProtection ; VirtualProtect ( vTablePtr , 4 , PAGE_EXECUTE_READWRITE , & oldProtection ); // يزيل حماية الصفحة في بداية جدول البيانات الظاهرية (VMT) حتى نتمكن من استبدال مؤشره الأول. orig_VirtualFn1 = reinterpret_cast <VirtualFn1_t> ( * vTablePtr ) ; // يخزن المؤشر إلى VirtualFn1 من جدول البيانات الظاهرية في متغير عام بحيث يمكن الوصول إليه مرة أخرى لاحقًا بعد استبدال مدخله في جدول البيانات الظاهرية باستخدام دالة الربط الخاصة بنا. * vTablePtr = & hkVirtualFn1 ; // يستبدل المؤشر إلى VirtualFn1 داخل جدول البيانات الظاهرية بمؤشر إلى دالة الربط الخاصة بنا (hkVirtualFn1). VirtualProtect ( vTablePtr , 4 , oldProtection , 0 ); // يستعيد حماية الصفحة القديمة. myClass- > VirtualFn1 (); // يستدعي الدالة الظاهرية من مثيل الفئة. نظرًا لأنه مرتبط الآن، فسيتم استدعاء دالة الربط الخاصة بنا (hkVirtualFn1). myClass- > VirtualFn1 (); myClass -> VirtualFn1 (); delete myClass ; return 0 ; }يجب أن تكون جميع الدوال الافتراضية دوالًا أعضاءً في الصنف، وتُستدعى جميع دوال الأعضاء (غير الثابتة) باستخدام اصطلاح الاستدعاء __thiscall (إلا إذا كانت دالة العضو تأخذ عددًا متغيرًا من الوسائط، فحينها تُستدعى باستخدام __cdecl). يمرر اصطلاح الاستدعاء __thiscall مؤشرًا إلى نسخة الصنف المستدعية (يُشار إليه عادةً بمؤشر "this") عبر سجل ECX (في بنية x86). لذلك، لكي تتمكن دالة الربط من اعتراض مؤشر "this" المُمرر بشكل صحيح وأخذه كوسيط، يجب عليها البحث في سجل ECX. في المثال أعلاه، يتم ذلك عن طريق ضبط دالة الربط (hkVirtualFn1) لاستخدام اصطلاح الاستدعاء __fastcall، مما يجعل دالة الربط تبحث في سجل ECX عن أحد وسائطها.
لاحظ أيضًا أنه في المثال أعلاه، دالة الربط (hkVirtualFn1) ليست دالة عضوية بحد ذاتها، لذا لا يمكنها استخدام اصطلاح الاستدعاء __thiscall. يجب استخدام __fastcall بدلاً من ذلك، لأنه اصطلاح الاستدعاء الوحيد الآخر الذي يبحث في سجل ECX عن وسيط.
خطاف أحداث لوحة المفاتيح في لغة C#
سيقوم المثال التالي بالربط بأحداث لوحة المفاتيح في نظام التشغيل Microsoft Windows باستخدام إطار عمل Microsoft .NET .
باستخدام System.Runtime.InteropServices ؛مساحة الاسم Hooks ;public class KeyHook { /* متغيرات الأعضاء */ protected static int Hook ; protected static LowLevelKeyboardDelegate Delegate ; protected static readonly object Lock = new object (); protected static bool IsRegistered = false ;/* استيراد DLL */ [DllImport("user32")] private static extern int SetWindowsHookEx ( int idHook , LowLevelKeyboardDelegate lpfn , int hmod , int dwThreadId );[DllImport("user32")] private static extern int CallNextHookEx ( int hHook , int nCode , int wParam , KBDLLHOOKSTRUCT lParam );[DllImport("user32")] private static extern int UnhookWindowsHookEx ( int hHook );/* الأنواع والثوابت */ protected delegate int LowLevelKeyboardDelegate ( int nCode , int wParam , ref KBDLLHOOKSTRUCT lParam ); private const int HC_ACTION = 0 ; private const int WM_KEYDOWN = 0x0100 ; private const int WM_KEYUP = 0x0101 ; private const int WH_KEYBOARD_LL = 13 ;[StructLayout(LayoutKind.Sequential)] public struct KBDLLHOOKSTRUCT { public int vkCode ; public int scanCode ; public int flags ; public int time ; public int dwExtraInfo ; }/* طرق */ static private int LowLevelKeyboardHandler ( int nCode , int wParam , ref KBDLLHOOKSTRUCT lParam ) { if ( nCode == HC_ACTION ) { if ( wParam == WM_KEYDOWN ) System . Console . Out . WriteLine ( "تم الضغط على مفتاح: " + lParam . vkCode ); else if ( wParam == WM_KEYUP ) System . Console . Out . WriteLine ( "تم رفع مفتاح: " + lParam . vkCode ); } return CallNextHookEx ( Hook , nCode , wParam , lParam ); }public static bool RegisterHook ( ) { lock ( Lock ) { if ( IsRegistered ) return true ; Delegate = LowLevelKeyboardHandler ; Hook = SetWindowsHookEx ( WH_KEYBOARD_LL , Delegate , Marshal.GetHINSTANCE ( System.Reflection.Assembly.GetExecutingAssembly ( ) . GetModules ( ) [ 0 ] ) . ToInt32 ( ), 0 ) ;إذا كان ( Hook != 0 ) فقم بإرجاع IsRegistered = true ؛ Delegate = null ؛ قم بإرجاع false ؛ } }public static bool UnregisterHook () { lock ( Lock ) { return IsRegistered = ( UnhookWindowsHookEx ( Hook ) != 0 ); } } }ربط/اعتراض واجهة برمجة التطبيقات/الدوال باستخدام تعليمة JMP المعروفة أيضًا باسم الربط
يُقدّم الكود المصدري التالي مثالًا على طريقة ربط واجهة برمجة التطبيقات/الدالة، حيث يتم الربط عن طريق استبدال أول ستة بايتات من دالة الوجهة بتعليمات JMP إلى دالة جديدة. يُجمّع الكود في ملف DLL ثم يُحمّل في العملية المستهدفة باستخدام أي طريقة من طرق حقن DLL . باستخدام نسخة احتياطية من الدالة الأصلية، يمكن استعادة أول ستة بايتات مرة أخرى لضمان عدم انقطاع الاستدعاء. في هذا المثال، يتم ربط دالة MessageBoxW من واجهة برمجة تطبيقات Win32 . [ 3 ]
/* هذه الفكرة مبنية على نهج مكتبة chrom-lib، الموزعة بموجب رخصة جنو العمومية العامة المحدودة. مصدر مكتبة chrom-lib: https://github.com/linuxexp/chrom-lib حقوق النشر © 2011 راجا جاموال */ #include <windows.h> #define SIZE 6typedef int ( WINAPI * pMessageBoxW )( HWND , LPCWSTR , LPCWSTR , UINT ); // نموذج أولي لصندوق الرسائل int WINAPI MyMessageBoxW ( HWND , LPCWSTR , LPCWSTR , UINT ); // مسارنا الجانبيvoid BeginRedirect ( LPVOID ); pMessageBoxW pOrigMBAddress = NULL ; // عنوان البايت الأصلي oldBytes [ SIZE ] = { 0 }; // بايت احتياطي JMP [ SIZE ] = { 0 }; // تعليمة JMP بحجم 6 بايت DWORD oldProtect , myProtect = PAGE_EXECUTE_READWRITE ;INT APIENTRY DllMain ( HMODULE hDLL , DWORD Reason , LPVOID Reserved ) { switch ( Reason ) { case DLL_PROCESS_ATTACH : // إذا كانت مُرفقة pOrigMBAddress = ( pMessageBoxW ) GetProcAddress ( GetModuleHandleA ( "user32.dll" ), // الحصول على عنوان "MessageBoxW" الأصلي ); if ( pOrigMBAddress != NULL ) BeginRedirect ( MyMessageBoxW ); // بدء التوجيه break ;case DLL_PROCESS_DETACH : VirtualProtect (( LPVOID ) pOrigMBAddress , SIZE , myProtect , & oldProtect ); // تعيين حماية القراءة والكتابة memcpy ( pOrigMBAddress , oldBytes , SIZE ); // استعادة النسخة الاحتياطية VirtualProtect (( LPVOID ) pOrigMBAddress , SIZE , oldProtect , & myProtect ); // إعادة ضبط الحمايةcase DLL_THREAD_ATTACH : case DLL_THREAD_DETACH : break ; } return TRUE ; }void BeginRedirect ( LPVOID newFunction ) { BYTE tempJMP [ SIZE ] = { 0xE9 , 0x90 , 0x90 , 0x90 , 0xC3 }; // 0xE9 = JMP 0x90 = NOP 0xC3 = RET memcpy ( JMP , tempJMP , SIZE ); // تخزين تعليمة القفز في JMP DWORD JMPSize = (( DWORD ) newFunction - ( DWORD ) pOrigMBAddress - 5 ); // حساب مسافة القفز VirtualProtect ( ( LPVOID ) pOrigMBAddress , SIZE , // تعيين حماية القراءة والكتابة PAGE_EXECUTE_READWRITE , & oldProtect ); memcpy ( oldBytes , pOrigMBAddress , SIZE ); // إنشاء نسخة احتياطية memcpy ( & JMP [ 1 ], & JMPSize , 4 ); // ملء خانات nop بمسافة القفز (JMP, distance(4bytes), RET) memcpy ( pOrigMBAddress , JMP , SIZE ); // تعيين تعليمة القفز في بداية الدالة الأصلية VirtualProtect (( LPVOID ) pOrigMBAddress , SIZE , oldProtect , & myProtect ); // إعادة ضبط الحماية }int WINAPI MyMessageBoxW ( HWND hWnd , LPCWSTR lpText , LPCWSTR lpCaption , UINT uiType ) { VirtualProtect (( LPVOID ) pOrigMBAddress , SIZE , myProtect , & oldProtect ); // تعيين حماية القراءة والكتابة memcpy ( pOrigMBAddress , oldBytes , SIZE ); // استعادة النسخة الاحتياطية int retValue = MessageBoxW ( hWnd , lpText , lpCaption , uiType ); // الحصول على القيمة المُعادة من الدالة الأصلية memcpy ( pOrigMBAddress , JMP , SIZE ); // إعادة تعيين تعليمة القفز VirtualProtect (( LPVOID ) pOrigMBAddress , SIZE , oldProtect , & myProtect ); // إعادة ضبط الحماية return retValue ; // إرجاع القيمة الأصلية }خطاف فلتر الشبكة
يوضح هذا المثال كيفية استخدام تقنية الربط لتغيير حركة مرور الشبكة في نواة لينكس باستخدام Netfilter .
#include <linux/module.h> #include <linux/kernel.h> #include <linux/skbuff.h>#include <linux/ip.h> #include <linux/tcp.h> #include <linux/in.h> #include <linux/netfilter.h> #include <linux/netfilter_ipv4.h>/* المنفذ الذي نريد إسقاط الحزم عليه */ static const uint16_t port = 25 ;/* هذه هي دالة الربط نفسها */ static unsigned int hook_func ( unsigned int hooknum , struct sk_buff ** pskb , const struct net_device * in , const struct net_device * out , int ( * okfn )( struct sk_buff * )) { struct iphdr * iph = ip_hdr ( * pskb ); struct tcphdr * tcph , tcpbuf ;إذا كان ( iph- > protocol != IPPROTO_TCP ) فقم بإرجاع NF_ACCEPT ؛tcph = skb_header_pointer ( * pskb , ip_hdrlen ( * pskb ), sizeof ( * tcph ), & tcpbuf ); if ( tcph == NULL ) return NF_ACCEPT ;return ( tcph -> dest == port ) ? NF_DROP : NF_ACCEPT ; }/* تُستخدم لتسجيل دالة الربط الخاصة بنا */ static struct nf_hook_ops nfho = { . hook = hook_func , . hooknum = NF_IP_PRE_ROUTING , . pf = NFPROTO_IPV4 , . priority = NF_IP_PRI_FIRST , };static __init int my_init ( void ) { return nf_register_hook ( & nfho ); }static __exit void my_exit ( void ) { nf_unregister_hook ( & nfho ); }module_init ( my_init ); module_exit ( my_exit );ربط IAT الداخلي
يوضح الكود التالي كيفية ربط الدوال المستوردة من وحدة نمطية أخرى. يمكن استخدام هذه الطريقة لربط الدوال في عملية مختلفة عن العملية المُستدعِية. يتطلب ذلك تجميع الكود في ملف DLL ثم تحميله في العملية المستهدفة باستخدام أي طريقة من طرق حقن DLL . تتميز هذه الطريقة بصعوبة اكتشافها بواسطة برامج مكافحة الفيروسات أو برامج مكافحة الغش ، ويمكن تحويلها إلى ربط خارجي لا يستخدم أي استدعاءات ضارة. يحتوي رأس الملف التنفيذي المحمول على جدول عناوين الاستيراد (IAT)، والذي يمكن تعديله كما هو موضح في الكود المصدر أدناه. يعمل الكود المصدر أدناه على نظام التشغيل Microsoft Windows.
#include <windows.h>typedef int ( __stdcall * pMessageBoxA ) ( HWND hWnd , LPCSTR lpText , LPCSTR lpCaption , UINT uType ); // هذا هو نوع استدعاء MessageBoxA. pMessageBoxA RealMessageBoxA ; // سيتم تخزين مؤشر إلى الدالة الأصلية.void DetourIATptr ( const char * function , void * newfunction , HMODULE module );int __stdcall NewMessageBoxA ( HWND hWnd , LPCSTR lpText , LPCSTR lpCaption , UINT uType ) { // دالة وهمية printf ( "النص المرسل إلى MessageBoxA هو: %s \n " , lpText ); return RealMessageBoxA ( hWnd , lpText , lpCaption , uType ); // استدعاء الدالة الحقيقية }int main ( int argc , CHAR * argv []) { DetourIATptr ( "MessageBoxA" ,( void * ) NewMessageBoxA , 0 ); // ربط الدالة MessageBoxA ( NULL , "Just A MessageBox" , "Just A MessageBox" , 0 ); // استدعاء الدالة -- سيؤدي هذا إلى استدعاء الربط الوهمي. return 0 ; }void ** IATfind ( const char * function , HMODULE module ) { // البحث عن مدخل IAT (جدول عناوين الاستيراد) الخاص بالدالة المعطاة. int ip = 0 ; if ( module == 0 ) module = GetModuleHandle ( 0 ); PIMAGE_DOS_HEADER pImgDosHeaders = ( PIMAGE_DOS_HEADER ) module ; PIMAGE_NT_HEADERS pImgNTHeaders = ( PIMAGE_NT_HEADERS )(( LPBYTE ) pImgDosHeaders + pImgDosHeaders -> e_lfanew ); PIMAGE_IMPORT_DESCRIPTOR pImgImportDesc = ( PIMAGE_IMPORT_DESCRIPTOR )(( LPBYTE ) pImgDosHeaders + pImgNTHeaders -> OptionalHeader . DataDirectory [ IMAGE_DIRECTORY_ENTRY_IMPORT ]. VirtualAddress );إذا كان ( pImgDosHeaders -> e_magic != IMAGE_DOS_SIGNATURE ) printf ( "libPE Error : e_magic is no valid DOS signature \n " );for ( IMAGE_IMPORT_DESCRIPTOR * iid = pImgImportDesc ; iid -> Name != NULL ; iid ++ ) { for ( int funcIdx = 0 ; * ( funcIdx + ( LPVOID * )( iid -> FirstThunk + ( SIZE_T ) module )) != NULL ; funcIdx ++ ) { char * modFuncName = ( char * )( * ( funcIdx + ( SIZE_T * )( iid -> OriginalFirstThunk + ( SIZE_T ) module )) + ( SIZE_T ) module + 2 ); const uintptr_t nModFuncName = ( uintptr_t ) modFuncName ; bool isString = ! ( nModFuncName & ( sizeof ( nModFuncName ) == 4 ? 0x80000000 : 0x80000000000000000 )); if ( isString ) { if ( ! _stricmp ( function , modFuncName )) return funcIdx + ( LPVOID * )( iid -> FirstThunk + ( SIZE_T ) module ); } } } return 0 ; }void DetourIATptr ( const char * function , void * newfunction , HMODULE module ) { void ** funcptr = IATfind ( function , module ); if ( * funcptr == newfunction ) return ;DWORD oldrights , newrights = PAGE_READWRITE ; // تحديث الحماية إلى READWRITE VirtualProtect ( funcptr , sizeof ( LPVOID ), newrights , & oldrights );RealMessageBoxA = ( pMessageBoxA ) * funcptr ; // تتطلب بعض المترجمات التحويل (مثل MinGW)، لست متأكدًا من MSVC * funcptr = newfunction ;// استعادة علامات حماية الذاكرة القديمة. VirtualProtect ( funcptr , sizeof ( LPVOID ), oldrights , & newrights ); }انظر أيضاً
مراجع
- ↑ "ld(1) - صفحة دليل لينكس" . www.man7.org . تم الاطلاع عليه بتاريخ 16-03-2026 .
- ↑ psyfl
- ↑ لمزيد من المعلومات، انظر الرابط التالي: http://ntvalk.blogspot.nl/2013/11/hooking-explained-detouring-library.html
- جوناثان دانيال (27 نوفمبر 2013). "شرح تقنية الربط: تجاوز استدعاءات المكتبات وتصحيح جداول الدوال الافتراضية في أنظمة ويندوز/لينكس/ماك أو إس إكس" . تم الاطلاع عليه بتاريخ 1 يناير 2014 .
- بينه نغوين (16 أغسطس 2004). "معجم القرصنة / قاموس لينكس الإصدار 0.16" . تم الاطلاع عليه بتاريخ 23 فبراير 2008.
هوك
- [29-06-2012: يبدو أن الرابط معطل] المؤلف: الأب المقدس (10-06-2002). "ربط واجهة برمجة تطبيقات ويندوز - تقنيات ربط وظائف واجهة برمجة التطبيقات على ويندوز 1.1 باللغة الإنجليزية" (ملف PDF) . مؤرشف من النسخة الأصلية (PDF) بتاريخ 29-12-2009 . تاريخ الاطلاع: 21-02-2008 .
{{cite web}}له|author=اسم عام ( مساعدة )
روابط خارجية
ويندوز
- معلومات حول ربط وظيفة جدول عناوين الاستيراد.
- معلومات من مايكروسوفت حول الربط
- معلومات وتقنيات متنوعة تتعلق بربط معالجات x86.
- APISpy32 هو تطبيق يستخدم لاختراق واجهة برمجة تطبيقات win32.
- Detours هي مكتبة ربط وظائف للأغراض العامة تم إنشاؤها بواسطة Microsoft Research وتعمل بلغة C / C++.
- winspy ثلاث طرق لحقن التعليمات البرمجية في عملية أخرى.
- توفر حزمة تطوير البرمجيات HookTool (ACF SDK) نظرة شاملة على ربط واجهات برمجة التطبيقات وحقن التعليمات البرمجية . يتوفر منتج تجاري أيضًا.
- madCodeHook هي مكتبة تجارية لربط واجهات برمجة التطبيقات x86 و x64 وحقن DLL للغة C++ و Delphi.
- EasyHook هو محرك ربط مفتوح المصدر يدعم x86 و x64 في نظام التشغيل Windows في كل من بيئة المستخدم وبيئة النواة.
- SpyStudio Application Trace SpyStudio هو برنامج لتتبع التطبيقات يقوم بربط الاستدعاءات وعرض النتائج بطريقة منظمة.
- rohitab.com API Monitor هو تطبيق مجاني يمكنه ربط وعرض أكثر من 10000 واجهة برمجة تطبيقات Windows وواجهات COM في تطبيقات وخدمات 32 بت و 64 بت.
- Deviare API Hook Deviare هو إطار عمل مجاني لربط العمليات يمكن استخدامه لاعتراض استدعاءات واجهة برمجة التطبيقات (API) للعمليات الأخرى وعرض معلومات المعلمات الكاملة أو إنشاء مراقبات واجهة برمجة التطبيقات (API).
- برنامج WinAPIOverride هو برنامج مجاني للاستخدام غير التجاري. يمكنه ربط واجهات برمجة تطبيقات ويندوز 32، وCOM، وOLE، وActiveX، و.NET في عمليات 32 بت و64 بت. ويتضمن أدوات مراقبة وتحليل لاحقة.
- مكتبة urmem C++11 متعددة المنصات (x86) للعمل مع الذاكرة (الخطافات، التصحيحات، غلاف المؤشر، ماسح التوقيعات، إلخ).
لينكس
إيماكس
- خطافات إيماكس: تُعدّ الخطافات آليةً مهمةً لتخصيص إيماكس. الخطاف عبارة عن متغير في لغة ليسب يحتوي على قائمة من الدوال، يتم استدعاؤها في مناسبة محددة. (يُطلق على هذا اسم تشغيل الخطاف).
نظام التشغيل OS X ونظام التشغيل iOS
- Cydia Substrate هو إطار عمل لأجهزة iOS التي تم كسر حمايتها، مما يسمح للمطورين بالربط مع أي إطار عمل أو تطبيق آخر.
- هاربون هي مكتبة لنظام التشغيل ماك أو إس إكس لربط وظائف وقت التشغيل.
شرح مفصل لعملية ربط واجهات برمجة التطبيقات
- مقال مبسط حول طرق ربط واجهات برمجة التطبيقات (API Hooking) المختلفة، لبنية x86.
- تدفق التحكم
- حقن DLL
