Hooks ในระบบ Windows มีฟังก์ชันที่ทรงพลังมาก ด้วยเทคโนโลยีนี้ ข้อความเกือบทั้งหมดในระบบ Windows จึงสามารถดักจับ ตรวจสอบ และประมวลผลได้ เทคโนโลยีนี้สามารถนำมาใช้กันอย่างแพร่หลายในซอฟต์แวร์ต่างๆ โดยเฉพาะซอฟต์แวร์ที่ต้องมีการตรวจสอบ การบันทึกอัตโนมัติ และฟังก์ชันการตรวจสอบระบบอื่นๆ บทความนี้กล่าวถึงหัวข้อนี้โดยหวังว่าจะใช้เป็นข้อมูลอ้างอิงสำหรับผู้อ่าน
1. กลไกและประเภทของตะขอ
แอปพลิเคชัน Windows ทั้งหมดขับเคลื่อนด้วยข้อความ และการทำงานของแอปพลิเคชันขึ้นอยู่กับประเภทและเนื้อหาของข้อความที่ได้รับ Hooks คล้ายกับกลไกการประมวลผลการสกัดกั้น Dos Interrupt Hook เป็นแพลตฟอร์มของกลไกการประมวลผลข้อความของ Windows ด้วยการติดตั้ง hooks ต่างๆ แอปพลิเคชันสามารถตั้งค่ารูทีนย่อยเพื่อตรวจสอบข้อความบางอย่างในหน้าต่างที่ระบุและประมวลผลข้อความก่อนที่จะถึงหน้าต่างเป้าหมาย
ใน Windows มี hook อยู่สองประเภท ประเภทแรกคือ hook ของระบบ (RemoteHook) ซึ่งตรวจสอบข้อความภายในทั้งระบบ และอีกประเภทคือ thread hook (LocalHook) ซึ่งจะดักจับข้อความภายในกระบวนการเท่านั้น สำหรับ hooks ของระบบ ควรใช้ฟังก์ชัน hook (HookFunction) ในไลบรารีลิงก์แบบไดนามิก (DLL) ของระบบ Windows สำหรับ thread hooks ฟังก์ชัน hook สามารถนำไปใช้ใน DLL หรือในแอปพลิเคชันที่เกี่ยวข้อง เนื่องจากเมื่อนักพัฒนาสร้าง hook อันดับแรก Windows จะสร้างโครงสร้างข้อมูลในหน่วยความจำระบบ ซึ่งมีข้อมูลเกี่ยวกับ hook จากนั้นจึงเพิ่มโครงสร้างลงในรายการ hook ที่มีอยู่ และ Hooks ใหม่จะถูกจัดเรียงด้านหน้าของรุ่นเก่า ตะขอ เมื่อมีเหตุการณ์เกิดขึ้น หากมีการติดตั้ง hook ภายในเครื่อง ฟังก์ชัน hook ในกระบวนการปัจจุบันจะถูกเรียก หากเป็น hook ระยะไกล ระบบจะต้องแทรกฟังก์ชัน hook ลงในพื้นที่ที่อยู่ของกระบวนการอื่น เมื่อต้องการทำเช่นนี้ ฟังก์ชัน hook จะต้องอยู่ในไลบรารีลิงก์แบบไดนามิก ดังนั้นหากคุณต้องการใช้ hook ระยะไกล คุณต้องใส่ hook ใส่ฟังก์ชันลงในไลบรารีลิงก์แบบไดนามิก สำหรับประเภทข้อความที่ตรวจสอบโดย hooks Windows จะมีประเภททั้งหมดดังต่อไปนี้: ดังแสดงในตารางที่ 1:
ตารางที่ 1. ชนิดข้อความ Windows
ตัวระบุคงที่ประเภทข้อความ | ค่า | ประเภทข้อความ | ขอบเขตการใช้งาน |
WH_CALLWNDPROC | 4 | ข้อความไปที่หน้าต่าง | เธรดหรือระบบ |
WH_CALLWNDPROCRET | 12 | ข้อความที่ส่งกลับมาทางหน้าต่าง | เธรดหรือระบบ |
WH_CBT | 5 | ข้อความ เช่น การเปลี่ยนหน้าต่างและการตั้งค่าโฟกัส | เธรดหรือระบบ |
WH_DEBUG | 9 | ไม่ว่าจะดำเนินการ Hooks ของ Hooks อื่น ๆ หรือไม่ | เธรดหรือระบบ |
WH_เบื้องหน้า IDLE | 11 | โปรแกรมเบื้องหน้าไม่ได้ใช้งาน | เธรดหรือระบบ |
WH_GETMESSAGE | 3 | ข้อความที่โพสต์ลงในคิวข้อความ | เธรดหรือระบบ |
WH_การเล่นวารสาร | 1 | เล่นข้อความที่บันทึกไว้ | ระบบ |
WH_บันทึกประจำวัน | 0 | ตรวจสอบและบันทึกข้อความที่ป้อน | ระบบ |
WH_คีย์บอร์ด | 2 | ข้อความแป้นพิมพ์ | เธรดหรือระบบ |
WH_เมาส์ | 7 | ข้อความเมาส์ | เธรดหรือระบบ |
WH_MSGFILTER | -1 | แถบเลื่อนเมนู ข้อความโต้ตอบ | เธรดหรือระบบ |
WH_SHELL | 10 | ข้อความเชลล์ | เธรดหรือระบบ |
WH_SYSMSGFILTER | 6 | แถบเลื่อนเมนู ข้อความโต้ตอบสำหรับกระทู้ทั้งหมด | ระบบ |
2. การใช้ hooks ในการเขียนโปรแกรม VB
(1) รูปแบบของฟังก์ชัน hook (ฟังก์ชัน HOOK) ฟังก์ชัน Hook นั้นเป็นฟังก์ชันจริงๆ หากเป็นฟังก์ชัน hook จะต้องวางฟังก์ชันไว้ในไดนามิกลิงก์ไลบรารี ฟังก์ชั่นนี้มีรูปแบบพารามิเตอร์บางอย่างซึ่งมีดังต่อไปนี้ใน VB:
ฟังก์ชั่นส่วนตัว HookFunc (ByVal nCode ตราบใดที่ ByVal wParam ตราบใดที่ ByVal lParam ตราบใดที่) ตราบใดที่ |
ในหมู่พวกเขา nCode แสดงถึงสถานการณ์ที่สร้าง hook และมีชุดค่าที่เป็นไปได้ที่แตกต่างกันขึ้นอยู่กับ hook พารามิเตอร์ค่าส่งคืนของ wParam และ lParam จะรวมเนื้อหาของข้อความที่ได้รับการตรวจสอบซึ่งจะแตกต่างกันไป ด้วยประเภทของข้อความที่ Hook ตรวจสอบจะแตกต่างกันไปขึ้นอยู่กับค่าของ nCode สำหรับฟังก์ชัน hook ที่ตั้งค่าด้วย 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 หลายอย่างในการติดตั้ง hooks: คุณสามารถใช้ฟังก์ชัน API SetWindowsHookEx() เพื่อติดตั้งรูทีนย่อย hook ที่กำหนดโดยแอปพลิเคชันลงในรายการ hook การประกาศฟังก์ชันSetWindowsHookEx()จะเป็นดังนี้:
ประกาศฟังก์ชัน SetWindowsHookEx Lib user32 Alias SetWindowsHookExA (ByVal idHook As Long, ByVal lpfn As Long, ByVal hmod As Long, ByVal dwThreadId As Long) As Long |
ค่า idHook คือประเภทข้อความที่จัดการ ค่า lpfn คือตัวชี้ที่อยู่ของรูทีนย่อย hook ถ้าพารามิเตอร์ dwThreadId เป็น 0 หรือตัวระบุของเธรดที่สร้างโดยกระบวนการอื่น lpfn ต้องชี้ไปที่รูทีนย่อย hook ใน DLL นอกจากนี้ lpfn ยังสามารถชี้ไปที่โค้ดรูทีนย่อย hook ของกระบวนการปัจจุบัน ค่า hMod คือหมายเลขอ้างอิงของแอปพลิเคชัน ซึ่งระบุ DLL ที่มีรูทีนย่อยที่ชี้โดย lpfn ถ้า dwThreadId ระบุเธรดที่สร้างโดยกระบวนการปัจจุบัน และโค้ดรูทีนย่อยอยู่ในกระบวนการปัจจุบัน hMod ต้องเป็น 0 ค่า dwThreadId คือตัวระบุของเธรดที่เกี่ยวข้องกับกระบวนการย่อยของ hook ที่ติดตั้ง ถ้าเป็น 0 กระบวนการย่อยของ hook จะเชื่อมโยงกับเธรดทั้งหมด หากติดตั้ง hook สำเร็จ หมายเลขอ้างอิงของกระบวนการย่อยของ hook จะถูกส่งกลับ หากล้มเหลว 0 จะถูกส่งกลับ
นอกจากนี้ โดยทั่วไปแล้วฟังก์ชัน CallNextHookEx() ควรถูกเรียกในรูทีนย่อยของ hook เพื่อดำเนินการรูทีนย่อยของ hook ถัดไปที่ชี้ไปโดยรายการ hook มิฉะนั้น แอปพลิเคชันที่ติดตั้ง hooks อื่น ๆ จะไม่ได้รับการแจ้งเตือนของ hook ส่งผลให้เกิดผลลัพธ์ที่ไม่ถูกต้อง การประกาศฟังก์ชันCallNextHookEx()จะเป็นดังนี้:
ประกาศฟังก์ชัน CallNextHookEx Libuser32 Alias CallNextHookEx (ByVal hHook As Long, ByVal ncode As Lonog, ByVal wParam As Long, lParam As Any) ตราบเท่าที่ |
ค่าhHookเป็นค่าตอบแทนของSetWindowsHookEx() และnCode, wParam และlParamมีพารามิเตอร์ที่สามในฟังก์ชัน Hook ก่อนที่โปรแกรมจะยุติการทำงาน จะต้องเรียกฟังก์ชัน UnhookWindowsHookEx() เพื่อปล่อยทรัพยากรระบบที่เกี่ยวข้องกับ hook ฟังก์ชัน UnhookWindowsEx() ได้รับการประกาศดังนี้:
ประกาศฟังก์ชัน ปลดตะขอ WindowsHookEx Lib user32 นามแฝง ปลดตะขอ WindowsHookEx (ByVal hHook As Long) ตราบใดที่ |
hHook คือค่าที่ส่งคืนเมื่อติดตั้ง hook นั่นคือหมายเลขอ้างอิงของกระบวนการย่อยของ hook
(3) ปัญหาที่ควรคำนึงถึงเมื่อติดตั้ง hooks ใน VB พารามิเตอร์ lpfn คือที่อยู่ของ HookFunc กำหนดว่าโค้ด HookFunc จะต้องวางในโมดูล .BAS มาตรฐาน และส่งผ่านเป็น Address Of HookFunc ไม่สามารถวางในโมดูลคลาสหรือแนบกับแบบฟอร์มที่เหนือกว่าได้ สำหรับ RemoteHook ควรรวม HookFunc ไว้ในไลบรารีลิงก์แบบไดนามิก ดังนั้นหากคุณใช้ RemoteHook ใน VB คุณจะต้องใช้ฟังก์ชัน API สองรายการด้วย: GetModuleHandle() และ GetProcAddress()
ประกาศฟังก์ชัน GetModuleHandle Libkernel32 นามแฝง GetModuleHandleA (ByVal lpModuleName As String) ตราบใดที่ ประกาศฟังก์ชัน GetProcAddress Lib kernel32 นามแฝง GetProcAddress (ByVal hModule ตราบใดที่ ByVal lpProcName As String) ตราบใดที่ |
ค่า hmod คือตัวจัดการชื่อโมดูลที่มีกระบวนการ hook หากเป็น LocalHook ค่าอาจเป็น Null (0 ถูกส่งผ่านใน VB) และหากเป็น RemoteHook คุณสามารถใช้ GetModuleHandle (name.dll) เพื่อส่งผ่านเข้าไป .