تتمتع الخطافات الموجودة في أنظمة Windows بوظائف قوية للغاية، ومن خلال هذه التقنية، يمكن اعتراض جميع الرسائل الموجودة في أنظمة Windows ومراقبتها ومعالجتها تقريبًا. يمكن استخدام هذه التقنية على نطاق واسع في العديد من البرامج، وخاصة البرامج التي تتطلب المراقبة والتسجيل التلقائي ووظائف مراقبة النظام الأخرى. تتناول هذه المقالة هذا الموضوع، على أمل أن تكون مرجعًا للقراء.
1. آلية ونوع الخطاف
تعتمد جميع تطبيقات Windows على الرسائل، ويعتمد تشغيل التطبيق على نوع ومحتوى الرسالة التي يتلقاها. تشبه الخطافات آلية معالجة اعتراض مقاطعة Dos. الخطاف عبارة عن منصة لآلية معالجة رسائل Windows، من خلال تثبيت خطافات مختلفة، يمكن للتطبيق إعداد إجراءات فرعية عليها لمراقبة رسائل معينة في النافذة المحددة ومعالجة الرسالة قبل أن تصل إلى النافذة المستهدفة.
في نظام التشغيل Windows، هناك نوعان من الخطافات، أحدهما هو خطاف النظام (RemoteHook)، الذي يراقب الرسائل داخل النظام بأكمله، والآخر هو خطاف الخيط (LocalHook)، الذي يعترض الرسائل داخل العملية فقط. بالنسبة لخطافات النظام، يجب تنفيذ وظيفة الخطاف (HookFunction) في مكتبة الارتباط الديناميكي (DLL) لنظام Windows. بالنسبة لخطافات الخيوط، يمكن تنفيذ وظيفة الخطاف في ملف DLL أو في التطبيق المقابل. وذلك لأنه عندما يقوم المطور بإنشاء خطاف، يقوم Windows أولاً بإنشاء بنية بيانات في ذاكرة النظام، والتي تحتوي على معلومات حول الخطاف، ثم يضيف البنية إلى قائمة الخطافات الموجودة، وسيتم فرز الخطافات الجديدة أمام الخطافات الأقدم خطافات. عند وقوع حدث ما، إذا تم تثبيت خطاف محلي، فسيتم استدعاء وظيفة الخطاف في العملية الحالية. إذا كان خطافًا عن بعد، فيجب على النظام إدراج وظيفة الخطاف في مساحة العنوان للعمليات الأخرى. وللقيام بذلك، يجب أن تكون وظيفة الخطاف في مكتبة الارتباط الديناميكي، لذلك إذا كنت تريد استخدام خطاف بعيد، فيجب عليك وضعه الخطاف ضع الوظيفة في مكتبة الارتباط الديناميكي. بالنسبة لأنواع الرسائل التي يتم مراقبتها بواسطة الخطافات، يوفر Windows إجمالي الأنواع التالية: كما هو موضح في الجدول 1:
الجدول 1. أنواع رسائل Windows
معرف ثابت لنوع الرسالة | قيمة | نوع الرسالة | نطاق التطبيق |
WH_CALLWNDPROC | 4 | رسالة إلى النافذة | الموضوع أو النظام |
WH_CALLWNDPROCRET | 12 | الرسالة التي عادت من النافذة | الموضوع أو النظام |
WH_CBT | 5 | رسائل مثل تغييرات النافذة وإعدادات التركيز | الموضوع أو النظام |
WH_DEBUG | 9 | ما إذا كان سيتم تنفيذ خطافات لخطافات أخرى | الموضوع أو النظام |
WH_FOREGROUNDIDLE | 11 | برنامج المقدمة خاملاً | الموضوع أو النظام |
WH_GETMESSAGE | 3 | الرسائل المنشورة في قائمة انتظار الرسائل | الموضوع أو النظام |
WH_JOURNAL PLAYBACK | 1 | تشغيل الرسائل المسجلة | نظام |
WH_JOURNALRECORD | 0 | مراقبة وتسجيل رسائل الإدخال | نظام |
WH_KEYBOARD | 2 | رسائل لوحة المفاتيح | الموضوع أو النظام |
WH_MOUSE | 7 | رسالة الفأرة | الموضوع أو النظام |
WH_MSGFILTER | -1 | أشرطة التمرير القائمة، ورسائل الحوار | الموضوع أو النظام |
WH_SHELL | 10 | رسائل قذيفة | الموضوع أو النظام |
WH_SYSMSGFILTER | 6 | أشرطة تمرير القائمة، ورسائل الحوار لجميع المواضيع | نظام |
2. تنفيذ الخطافات في برمجة VB
(1) تنسيق وظيفة الخطاف (وظيفة الخطاف). وظيفة الخطاف هي في الواقع وظيفة. إذا كانت عبارة عن خطاف نظام، فيجب وضع الوظيفة في مكتبة الارتباط الديناميكي. تحتوي هذه الوظيفة على تنسيق معلمة معين، وهو كما يلي في VB:
وظيفة خاصة HookFunc (ByVal nCode طويل، ByVal wParam طويل، ByVal lParam طويل) |
من بينها، يمثل nCode الموقف الذي يتم فيه إنشاء الخطاف، وهناك مجموعات مختلفة من القيم المحتملة اعتمادًا على الخطاف؛ تتضمن قيم إرجاع المعلمات wParam وlParam محتوى الرسالة المراقبة، والتي تختلف مع نوع الرسالة التي يراقبها الخطاف، ويختلف ذلك حسب قيمة nCode. بالنسبة لوظائف الخطاف المعينة باستخدام VB، يكون نموذج الإطار العام كما يلي:
وظيفة خاصة HookFunc (ByVal nCode طويل، ByVal wParam طويل، ByVal lParam طويل) حدد حالة nCode حالة ncode<0:hookfunc=callnexthookex(hHookFunc, nCode, wParam, lParam) قيمة الحالة 1: المعالجة 1: HookFunc=X1 الحالة 2: عملية المعالجة 2: HookFunc = X1 … حدد النهاية وظيفة النهاية |
القيمة المرجعة للدالة إذا كانت الرسالة ستتم معالجتها، فقم بتمرير 0، وإلا قم بتمرير 1 وتناول الرسالة.
(2) تركيب وتنفيذ الخطافات. يتم استخدام عدة وظائف API لتثبيت الخطافات: يمكنك استخدام وظيفة API SetWindowsHookEx() لتثبيت روتين فرعي للربط محدد بواسطة التطبيق في قائمة الخطاف. تعريف الدالة SetWindowsHookEx() كما يلي:
قم بتعريف الوظيفة SetWindowsHookEx Lib user32 Alias SetWindowsHookExA (ByVal idHook As Long، ByVal lpfn As Long، ByVal hmod As Long، ByVal dwThreadId As Long) |
قيمة idHook هي نوع الرسالة التي يعالجها؛ وقيمة lpfn هي مؤشر عنوان الروتين الفرعي للربط. إذا كانت المعلمة dwThreadId هي 0 أو معرف مؤشر الترابط الذي تم إنشاؤه بواسطة عملية أخرى، فيجب أن يشير lpfn إلى الإجراء الفرعي للربط في ملف DLL. بالإضافة إلى ذلك، يمكن أن يشير lpfn إلى رمز روتين فرعي للعملية الحالية. قيمة hMod هي مؤشر التطبيق، الذي يحدد ملف DLL الذي يحتوي على الروتين الفرعي المشار إليه بواسطة lpfn. إذا قام dwThreadId بتعريف مؤشر ترابط تم إنشاؤه بواسطة العملية الحالية وكان رمز الروتين الفرعي موجودًا في العملية الحالية، فيجب أن تكون قيمة hMod 0. قيمة dwThreadId هي معرف مؤشر الترابط المرتبط بعملية الربط الفرعية المثبتة. إذا كانت 0، فإن عملية الربط الفرعية مرتبطة بجميع سلاسل الرسائل. إذا تم تثبيت الخطاف بنجاح، فسيتم إرجاع مقبض العملية الفرعية للربط، وإذا فشلت، فسيتم إرجاع 0.
بالإضافة إلى ذلك، يجب بشكل عام استدعاء الدالة CallNextHookEx() في الروتين الفرعي للربط لتنفيذ الروتين الفرعي للربط التالي المشار إليه بواسطة قائمة الخطاف، وإلا، لن تتلقى التطبيقات التي تحتوي على خطافات أخرى مثبتة إعلامات للربط، مما يؤدي إلى نتائج غير صحيحة. تعريف الدالة CallNextHookEx() كما يلي:
قم بتعريف وظيفة CallNextHookEx Libuser32 الاسم المستعار CallNextHookEx (ByVal hHook As Long، ByVal ncode As Lonog، ByVal wParam As Long، lParam As Any) As Long |
قيمة hHook هي القيمة المرجعة لـ SetWindowsHookEx()، وnCode وwParam وlParam هي المعلمات الثلاثة في وظيفة Hook. قبل إنهاء البرنامج، يجب استدعاء الدالة UnhookWindowsHookEx() لتحرير موارد النظام المرتبطة بالربط. يتم تعريف الدالة UnhookWindowsEx() كما يلي:
قم بتعريف الوظيفة Unhook WindowsHookEx Lib user32 الاسم المستعار Unhook WindowsHookEx(ByVal hHook As Long) As Long |
hHook هي القيمة المرجعة عند تثبيت الخطاف، أي مقبض عملية الخطاف الفرعية.
(3) المشكلات التي يجب الانتباه إليها عند تثبيت الخطافات في VB. المعلمة lpfn هي عنوان HookFunc. وينص VB على أنه يجب وضع رمز HookFunc في وحدة نمطية .BAS قياسية وتمريرها كعنوان لـ HookFunc. ولا يمكن وضعها في وحدة نمطية للفئة أو إرفاقها بنموذج أعلى. بالنسبة لـ RemoteHook، يجب تضمين HookFunc في مكتبة الارتباط الديناميكي، لذلك إذا كنت تستخدم RemoteHook في VB، فستحتاج أيضًا إلى استخدام وظيفتين لواجهة برمجة التطبيقات: GetModuleHandle() وGetProcAddress()، وتكون إعلاناتهما كما يلي:
قم بتعريف الدالة GetModuleHandle Libkernel32 الاسم المستعار GetModuleHandleA(ByVal lpModuleName كسلسلة) طالما قم بتعريف الوظيفة GetProcAddress Lib kernel32 الاسم المستعار GetProcAddress (ByVal hModule As Long، ByVal lpProcName as String) طالما |
قيمة hmod هي مؤشر اسم الوحدة النمطية الذي يحتوي على عملية الربط. إذا كانت LocalHook، فيمكن أن تكون القيمة Null (يتم تمرير 0 في VB)، وإذا كانت RemoteHook، فيمكنك استخدام GetModuleHandle (name.dll) لتمريرها. .