New to Windows Kernel 3-hook keusermodecallback
1. Introduction
In Windows, there are several methods to call a function in R3 from r0, one of which is keusermodecallback. The process of this function is as follows:
NT! Keusermodecallback-> NT! Kicallusermode-> NT! Kiserviceexit-> NTDLL! Kiusercallbackdispatcher-> callback function-> int2b-> NT! Kicallbackreturn-> NT! Keusermodecallback (after the call) is a process of ring0-> ring3-> ring0. After the stack preparation is complete, the power of kiserviceexit is used to return to ring3, whose landing point is kiusercallbackdispatcher, then kiusercallbackdispatcher is taken from peb
The base address of kernelcallbacktable. Then, use apiindex as the index to find the corresponding callback function in this table and call it. After the call, int2b triggers nt! Kicallbackreturn enters the kernel again. After the stack is corrected, it jumps back to keusermodecallback to complete the call.
All system message hook Callbacks are completed using keusermodecallback. Therefore, you can use the hook keusermodecallback to filter hook calls.
1.1 Inline hooks
Keusermodecallback does not have the corresponding R3 call interface, so it does not appear in ssdt shadow. You need to hook it in another way. The Inline Hook can be used, that is, add a JMP command (machine code E9) in the function header to jump into the proxy function, and then filter it to determine whether to call the real keusermodecallback function. The hook process is as follows:
Ulong starthookkeyusermodecallback () { Ulong TMP; Memset (ori_func, 0x90,100); // NOP Ori_func [50] = 0xe9; TMP = (ulong) proxyfunc-(ulong) keusermodecallback-5; Memcpy (jmp_bytes + 1, & TMP, 4 ); Headlen = getpatchsize (keusermodecallback, 5 ); Memcpy (ori_func, (pvoid) keusermodecallback, headlen); // original bytes // Skip TMP = (ulong) keusermodecallback + headlen-(ulong) (& ori_func [50])-5; Memcpy (& ori_func [51], & TMP, 4 ); // Remove memory Protection _ ASM { CLI MoV eax, Cr0 And eax, not 10000 h MoV Cr0, eax } Memcpy (keusermodecallback, jmp_bytes, 5 ); // Restore memory Protection _ ASM { MoV eax, Cr0 Or eax, 10000 h MoV Cr0, eax STI } Return true; } |
Code 1 hook keusermodecallback
The proxyfunc code of the proxy function is as follows:
_ Declspec (naked) void proxyfunc (void) { _ ASM { MoV eax, ESP Pushad Push [eax + 4*5] Push [eax + 4*4] Push [eax + 4*3] Push [eax + 4*2] Push [eax + 4] Lea eax, mykeusermodecallback Call eax Test eax, eax JZ continue_exe // return STATUS_SUCCESS Popad Retn 0x14 Continue_exe: Popad Lea eax, ori_func // jump back to the original function JMP eax } } |
Code 2 proxy function proxyfunc
First, call the custom filter function mykeusermodecallback, and then determine whether the returned value is STATUS_SUCCESS. If yes, call the real keusermodecallback. Otherwise, the system returns the result directly and rejects the call back function of R3.
1.2
Mykeusermodecallback
The following sections describe how mykeusermodecallback filters hooks. Many undisclosed technologies are involved, and the code is obtained through reverse engineering.
1.2.1 filter wh_keyboard_ll hooks
In a Windows operating system, the wh_keyboard_ll hook function is called before pressing a message to reach a specific window message queue. You can use this hook to intercept keyboard input. Pseudocode is shown in code 3.
Determine whether apinumber is kbd_ll_hook_api_num Convert inputbuffer to pfnhkinlpkbdllhookstructmsg Fill in the sys_event_struct structure and notify the R3 control program to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 3 wh_keyboard_ll Filter
In the process of filtering wh_keyboard_ll, special processing is needed. Nowadays, many software uses the wh_keyboard_ll hook for secure input control, instead of the traditional Edit Control. Therefore, you need to correct the false keys generated by the virtual keyboard to the real keys when returning the data.
1.2.2 filter wh_keyboard hooks
In a Windows operating system, the wh_keyboard hook function is called before a message arrives at a specific window message queue. You can use this hook to intercept keyboard input. The filtered pseudo code is shown in code 4.
Determine whether apinumber is kbd_hook_api_num Convert inputbuffer into pfnhkinlpkbdllhookstructmsg Structure Determine whether the ncode value of the generalhookheader member in the pfnhkinlpkbdllhookstructmsg structure is 0x20000 If yes, it is a wh_keyboard hook. Fill in the sys_event_struct structure and notify the R3 control program to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 4 wh_keyboard hook Filtering
The wh_keyboard hook shares an apinumber with some other Callbacks. Further judgment is required here, and the global wh_keyboard hook must be loadlibrary in other processes.
Similar to the wh_keyboard_ll hook, some programs use the wh_keyboard hook as a security input control. When returning the hook, you must correct the false keys generated by the virtual keyboard to the real ones.
1.2.3 wh_debug hook Filtering
In Windows, the wh_debug hook function is called first before other types of hook functions are called for Hook debugging. Malicious programs can use the wh_debug hook to obtain keyboard input. Shows Code 5 that filters out pseudo code.
Determine whether apinumber is debug_hook_api_num Determine whether the hook type in the debug information contains the keyboard input information If it contains, the sys_event_struct structure is filled and the R3 control program is notified to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 5 wh_debug hook Filtering
Similar to the wh_keyboard_ll wh_keyboard hook, some programs use the wh_debug hook to implement the security input control. When returning the hook, you need to correct the false buttons generated by the virtual keyboard to the real buttons.
1.2.4 ke_loadlibrary Filtering
In Windows, except the wh_keyboard_ll hook, other types of global message hooks require DLL to be loaded into the target process (the wh_keyboard_ll hook is only a thread switch, for more information, see msdn ). Therefore, filtering ke_loadlibrary can block most of the message hooks (in fact, currently all password protection programs use this method to filter message hooks to protect passwords, however, this method is invalid for wh_keyboard_ll hooks ). Shows Code 6 that filters out pseudo code.
Determine whether apinumber is load_library_api_num If yes, obtain the parameter information (including the dll path) Fill in the sys_event_struct structure and notify the R3 control program to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 6 ke_loadlibrary Filtering
1.2.5 wh_journalrecord Filtering
In Windows, wh_journalrecord is designed to record and play back messages. However, malicious programs can use this type of hook to obtain keyboard input messages to record passwords. Shows code 7.
Determine whether apinumber is event_msg_hook_api_num Further judge whether the message type is a key message Fill in the sys_event_struct structure and notify the R3 control program to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 7 wh_journalrecord Filtering
New to Windows Kernel 3-hook keusermodecallback
1. Introduction
In Windows, there are several methods to call a function in R3 from r0, one of which is keusermodecallback. The process of this function is as follows:
NT! Keusermodecallback-> NT! Kicallusermode-> NT! Kiserviceexit-> NTDLL! Kiusercallbackdispatcher-> callback function-> int2b-> NT! Kicallbackreturn-> NT! Keusermodecallback (after the call) is a process of ring0-> ring3-> ring0. After the stack preparation is complete, the power of kiserviceexit is used to return to ring3, whose landing point is kiusercallbackdispatcher, then kiusercallbackdispatcher is taken from peb
The base address of kernelcallbacktable. Then, use apiindex as the index to find the corresponding callback function in this table and call it. After the call, int2b triggers nt! Kicallbackreturn enters the kernel again. After the stack is corrected, it jumps back to keusermodecallback to complete the call.
All system message hook Callbacks are completed using keusermodecallback. Therefore, you can use the hook keusermodecallback to filter hook calls.
1.1 Inline hooks
Keusermodecallback does not have the corresponding R3 call interface, so it does not appear in ssdt shadow. You need to hook it in another way. The Inline Hook can be used, that is, add a JMP command (machine code E9) in the function header to jump into the proxy function, and then filter it to determine whether to call the real keusermodecallback function. The hook process is as follows:
Ulong starthookkeyusermodecallback () { Ulong TMP; Memset (ori_func, 0x90,100); // NOP Ori_func [50] = 0xe9; TMP = (ulong) proxyfunc-(ulong) keusermodecallback-5; Memcpy (jmp_bytes + 1, & TMP, 4 ); Headlen = getpatchsize (keusermodecallback, 5 ); Memcpy (ori_func, (pvoid) keusermodecallback, headlen); // original bytes // Skip TMP = (ulong) keusermodecallback + headlen-(ulong) (& ori_func [50])-5; Memcpy (& ori_func [51], & TMP, 4 ); // Remove memory Protection _ ASM { CLI MoV eax, Cr0 And eax, not 10000 h MoV Cr0, eax } Memcpy (keusermodecallback, jmp_bytes, 5 ); // Restore memory Protection _ ASM { MoV eax, Cr0 Or eax, 10000 h MoV Cr0, eax STI } Return true; } |
Code 1 hook keusermodecallback
The proxyfunc code of the proxy function is as follows:
_ Declspec (naked) void proxyfunc (void) { _ ASM { MoV eax, ESP Pushad Push [eax + 4*5] Push [eax + 4*4] Push [eax + 4*3] Push [eax + 4*2] Push [eax + 4] Lea eax, mykeusermodecallback Call eax Test eax, eax JZ continue_exe // return STATUS_SUCCESS Popad Retn 0x14 Continue_exe: Popad Lea eax, ori_func // jump back to the original function JMP eax } } |
Code 2 proxy function proxyfunc
First, call the custom filter function mykeusermodecallback, and then determine whether the returned value is STATUS_SUCCESS. If yes, call the real keusermodecallback. Otherwise, the system returns the result directly and rejects the call back function of R3.
1.2
Mykeusermodecallback
The following sections describe how mykeusermodecallback filters hooks. Many undisclosed technologies are involved, and the code is obtained through reverse engineering.
1.2.1 filter wh_keyboard_ll hooks
In a Windows operating system, the wh_keyboard_ll hook function is called before pressing a message to reach a specific window message queue. You can use this hook to intercept keyboard input. Pseudocode is shown in code 3.
Determine whether apinumber is kbd_ll_hook_api_num Convert inputbuffer to pfnhkinlpkbdllhookstructmsg Fill in the sys_event_struct structure and notify the R3 control program to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 3 wh_keyboard_ll Filter
In the process of filtering wh_keyboard_ll, special processing is needed. Nowadays, many software uses the wh_keyboard_ll hook for secure input control, instead of the traditional Edit Control. Therefore, you need to correct the false keys generated by the virtual keyboard to the real keys when returning the data.
1.2.2 filter wh_keyboard hooks
In a Windows operating system, the wh_keyboard hook function is called before a message arrives at a specific window message queue. You can use this hook to intercept keyboard input. The filtered pseudo code is shown in code 4.
Determine whether apinumber is kbd_hook_api_num Convert inputbuffer into pfnhkinlpkbdllhookstructmsg Structure Determine whether the ncode value of the generalhookheader member in the pfnhkinlpkbdllhookstructmsg structure is 0x20000 If yes, it is a wh_keyboard hook. Fill in the sys_event_struct structure and notify the R3 control program to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 4 wh_keyboard hook Filtering
The wh_keyboard hook shares an apinumber with some other Callbacks. Further judgment is required here, and the global wh_keyboard hook must be loadlibrary in other processes.
Similar to the wh_keyboard_ll hook, some programs use the wh_keyboard hook as a security input control. When returning the hook, you must correct the false keys generated by the virtual keyboard to the real ones.
1.2.3 wh_debug hook Filtering
In Windows, the wh_debug hook function is called first before other types of hook functions are called for Hook debugging. Malicious programs can use the wh_debug hook to obtain keyboard input. Shows Code 5 that filters out pseudo code.
Determine whether apinumber is debug_hook_api_num Determine whether the hook type in the debug information contains the keyboard input information If it contains, the sys_event_struct structure is filled and the R3 control program is notified to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 5 wh_debug hook Filtering
Similar to the wh_keyboard_ll wh_keyboard hook, some programs use the wh_debug hook to implement the security input control. When returning the hook, you need to correct the false buttons generated by the virtual keyboard to the real buttons.
1.2.4 ke_loadlibrary Filtering
In Windows, except the wh_keyboard_ll hook, other types of global message hooks require DLL to be loaded into the target process (the wh_keyboard_ll hook is only a thread switch, for more information, see msdn ). Therefore, filtering ke_loadlibrary can block most of the message hooks (in fact, currently all password protection programs use this method to filter message hooks to protect passwords, however, this method is invalid for wh_keyboard_ll hooks ). Shows Code 6 that filters out pseudo code.
Determine whether apinumber is load_library_api_num If yes, obtain the parameter information (including the dll path) Fill in the sys_event_struct structure and notify the R3 control program to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 6 ke_loadlibrary Filtering
1.2.5 wh_journalrecord Filtering
In Windows, wh_journalrecord is designed to record and play back messages. However, malicious programs can use this type of hook to obtain keyboard input messages to record passwords. Shows code 7.
Determine whether apinumber is event_msg_hook_api_num Further judge whether the message type is a key message Fill in the sys_event_struct structure and notify the R3 control program to make a judgment. If you allow this call, STATUS_SUCCESS is returned. Otherwise, status_unsuccessful is returned. |
Pseudocode 7 wh_journalrecord Filtering