Call Hooking
Call hooking is popular because it is so simple. Programs make subroutine calls as a matter of course. In machine language, these calls translate to variations of call or jump instructions. They pass arguments to the target function using a stack or CPU registers. The instruction always takes an address in memory. The memory location is the starting address of the subroutine code. When the subroutine is finished, the original code location is restored and execution continues normally.
The trick behind call hooking is to alter the address that the call jumps to. In this way an alternative function can replace the original. Sometimes this is called trampolining. Call hooking can be applied in several places: in internal function calls within a program, at calls into DLLs, or even to OS-supplied system calls. A call hook can emulate the behavior of the original call (usually by eventually calling the real function) so it will not be detected. Note that the call hook can apply special logic to the original call. For example, if the call is supposed to return the list of currently running processes, the call hook can hide certain processes from view. This kind of technique is standard practice when inserting backdoors into systems. Utility packages that provide call hooks are standard issue with many rootkits.
Hiding a Process
We must control what user-mode programs get in response to system calls. If we can control system calls, we can control what the task manager is able to find out about the system through standard queries. This includes controlling access to the process list.
Hooking a System Call
Our call hooking routine is very simple:
[View full size image]
We save the old pointer to ZwQuerySystemInformation. We replace the pointer in the call table with a pointer to our own function, NewZwQuerySystemInformation. When we actually overwrite the function pointer, we disable interrupts temporarily. We do this so we don't collide with another thread. Once we reenable the interrupts, the system call hook is in place and will immediately start to receive calls.
Structure of Our Basic Call Hook
This is the generic call hook. It does nothing other than call the original function and return the results. So, in effect, it does nothing at all. The computer continues to function normally (with an unnoticeable slowdown for the redirection):
[View full size image]
Removing a Process Record
If our goal is to hide a process, we must add some code to our call hook. Our new process hiding call hook looks like this:
[View full size image]
Figure 8-1 illustrates the way process records are stored in an array.
The code that removes an entry from the process list follows:
[View full size image]
Once we have "snipped" the entry, we return from the function call. The task manager gets the modified structure and skips the process record. We are now hiding the process.
We have illustrated that on Windows NT a device driver can easily hook any system call. The standard format for a device driver includes a DriverEntry function (the equivalent of main() ). From here, any call hooks can be installed.
The driver load routine takes pointers to the original functions. These are stored globally for use. Interrupts are disabled on the Intel x86 chip using the __asm cli/sti instructions. During the time that interrupts are disabled, the function addresses are replaced with the Trojan versions in the service table. We use a handy #define to find the correct offsets in the table. Once all replacements are complete, we can safely reenable interrupts. When unloading, we follow the same procedure as before, only we put back the original function pointers.
Process Injection Alternative
Another method for hiding a subversive program is to attach the subversive code to a process that is already running. For example, we can create a remote thread in an existing process. The remote thread runs the subversive program code. Once again, the process list remains unaffected. This method is completely effective from user mode and does not require kernel access. The fact that this trick was used by the popular Back Orifice 2000 program demonstrates its utility.
|
No comments:
Post a Comment