Chapter 5 Monitoring Native API Call
Translation: kendiv (fcczj@263.net)
Update: Tuesday, April 19, 2005
Disclaimer: Please indicate the source and guarantee the integrity of the article, and all rights to the translation.
Control API Hooks in user mode
The SPY client running in the user mode can control the API Hook mechanism and its generated protocol through a set of IOCTL functions. The name of this set of functions begins with spy_io_hook_, in Chapter 4, has been introduced, and the memory SPY function of W2k_spy.sys is discussed in Chapter 4 (see List 4-7 and Table 4-2).
Table 5-3 below again gives the part related to Table 4-2. Listing 5-10 is an excerpt from the list 4-7, which demonstrates how the Hook management function is assigned (Dispatch). These management functions will be repeated later.
Table 5-3. SPY Device Support IOCTL HOOK Management Function
Function Name IdiocTL Code Description SPY_IO_HOOK_INFO110X
8000602C
Returns the Native API Hook related information SPY_IO_HOOK_INSTALL120x8000E030 install Native API HookSPY_IO_HOOK_REMOVE130x8000 E034 remove Native API HookSPY_IO_HOOK_PAUSE140x8000 E038 pause / resume Hook agreement SPY_IO_HOOK_FILTER150x8000 E
03C
Allow / prohibit HOOK protocol filter spy_io_hook_reset160x8000 E040 Clear Hook Protocol SPY_IO_HOOK_READ170X80006044 Read data from the Hook protocol SPY_IO_HOOK_WRITE180X8000E048 Write data to the Hook protocol
NTSTATUS SpyDispatcher (PDevice_Context PDeviceContext,
DWORD DCODE,
PVOID PINPUT,
DWORD DINPUT,
Pvoid Poutput,
DWORD DOUTPUT,
PDWORD PDINFO)
{
SPY_MEMORY_BLOCK SMB;
SPY_PAGE_ENTRY SPE;
SPY_CALL_INPUT SCI;
Physical_address Pa;
DWORD DVALUE, DCOUNT;
Bool Fresh, FPAUSE, FFILTER, FLINE
PVOID PADDRESS;
PBYTE PBNAME;
Handle hobject;
NTSTATUS NS = Status_INVALID_PARAMETER;
Mutex_wait (PDeviceContext-> kmdispatch);
* PDINFO = 0;
Switch (dcode)
{
Case SPY_IO_VERSION_INFO:
{
NS = SPYOUTPUTVERSIONFO (Poutput, Doutput, PDINFO);
Break;
}
Case SPY_IO_OS_INFO:
{
NS = SPYOUTPUTOSINFO (Poutput, Doutput, PDINFO);
Break;
}
Case spy_io_segment:
{
IF ((ns = spyinputdword (& DValue,
PINPUT, DINPUT))
== status_success) {
NS = SPYOUTPUTSEGMENT (DVALUE,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_ITERRUPT:
{
IF ((ns = spyinputdword (& DValue,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTINTERRUPT (DVALUE,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_PHYSICAL:
{
IF ((ns = spyinputpointpointer (& paddress,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
PA = MmgetPhysicalAddRess (Paddress);
NS = SPYOUTPUTBINARY (& pa, physical_address_,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_CPU_INFO:
{
NS = SPYOUTPUTCPUINFO (Poutput, Doutput, PDINFO);
Break;
}
Case spy_io_pde_Array:
{
ns = spyoutputbinary (x86_pde_array, spy_pde_array_,
Poutput, doutput, pdinfo;
Break;
}
CASE SPY_IO_PAGE_ENTRY:
{
IF ((ns = spyinputpointpointer (& paddress,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
SpyMemoryPagentry (Paddress, & Spe);
NS = SPYOUTPUTBINARY (& spe, spy_page_entry_,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_MEMORY_DATA:
{
IF ((ns = spyinputmemory (& sm,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTMEMORY (& SMB,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_MEMORY_BLOCK:
{
IF ((ns = spyinputmemory (& sm,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTBLOCK (& SMB,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_HANDLE_INFO:
{
IF ((ns = spyinputhandle (& hobject,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
ns = spyoutputhandleinfo (HOBJECT,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_HOOK_INFO:
{
NS = SPYOUTPUTHOKINFO (Poutput, Doutput, PDINFO);
Break;
}
Case SPY_IO_HOOK_INSTALL: {
IF (((ns = spyinputbool (& FRESET,
PINPUT, DINPUT))
== STATUS_SUCCESS)
&&&&
((ns = spyhookinstall (fresh, & dcount))
== STATUS_SUCCESS))))))
{
ns = SPYOUTPUTDWORD (DCOUNT,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_HOOK_REMOVE:
{
IF (((ns = spyinputbool (& FRESET,
PINPUT, DINPUT))
== STATUS_SUCCESS)
&&&&
((ns = spyhookremove (FRESET, & DCOUNT))
== STATUS_SUCCESS))))))
{
ns = SPYOUTPUTDWORD (DCOUNT,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_HOOK_PAUSE:
{
IF ((ns = spyinputbool (& fpause,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
FPAUSE = SPYHOOKPAUSE (FPAUSE);
NS = SPYOUTPUTBOOL (FPAUSE,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_HOOK_FILTER:
{
IF ((ns = spyinputbool (& ffilter,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
Ffilter = spyhookfilter (ffilter);
NS = SPYOUTPUTBOOL (Ffilter,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_HOOK_RESET:
{
Spyhookreset ();
NS = status_success;
Break;
}
Case SPY_IO_HOOK_READ:
{
IF ((ns = spyinputbool (& fline,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTHOKREAD (FLINE,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_HOOK_WRITE:
{
SpyhookWrite (pinput, dinput);
NS = status_success;
Break;
}
Case SPY_IO_MODULE_INFO:
{
IF ((ns = spyinputpocointer (& pbname)
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTMODULEINFO (PBNAME,
Poutput, doutput, pdinfo;
}
Break;
}
Case spy_io_pe_header:
{
IF ((ns = spyinputpointpointer (& paddress,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTPEHEADER (Paddress, Poutput, Doutput, PDINFO);
}
Break;
}
Case SPY_IO_PE_EXPORT:
{
IF ((ns = spyinputpointpointer (& paddress,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTPEEXPORT (Paddress,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_PE_SYMBOL:
{
IF ((ns = spyinputpocointer (& pbname)
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTPESYMBOL (PBNAME,
Poutput, doutput, pdinfo;
}
Break;
}
Case SPY_IO_CALL:
{
IF ((ns = spyinputbinary (& sci, spy_call_input_,
PINPUT, DINPUT))
== STATUS_SUCCESS)
{
NS = SPYOUTPUTCALL (& sci,
Poutput, doutput, pdinfo;
}
Break;
}
}
Mutex_release (PDeviceContext-> kmdispatch);
Return ns;
}
Listing 5-10. SPY Driver's Hook Command Dispatcher
IOCTL function spy_io_hook_info
The IOCTL function spy_io_hook_info uses the current information of the HOOK mechanism to populate a spy_hook_info structure, which is similar to the SDT of the system. SPY_HOOK_INFO Structure (Listing 5-11) References multiple previously described structures:
l Service_descriptor_table structure, defined in list 5-1
l spy_call and spy_hook_entry structure, defined in list 5-2
l Spy_header and spy_protocol structure, defined in list 5-9
Typedef struct _sspy_hook_info
{
SPY_HEADER SH;
PSPY_CALL PSC;
PSPY_PROTOCOL PSP;
PSERVICE_DEScriptor_table psdt;
Service_descriptor_table sdt;
DWORD serviceLIMIT;
NTProc ServiceTable [SDT_SYMBOLS_MAX];
BYTE argumenttable [sdt_symbols_max];
SPY_HOOK_ENTRY SPYHOOKS [SDT_SYMBOLS_MAX];
}
Spy_hook_info, * pspy_hook_info, ** PPSPY_HOOK_INFO;
#define spy_hook_info_ sizeof (spy_hook_info)
Listing 5-11. SPY_HOOK_INFO structure definition
Be careful when calculating the value of the member. The pointer in some members point to the memory block in kernel mode, which cannot be accessed in user mode. However, you can use the Spy_IO_MEMORY_DATA function of the SPY device to check the data in these memory blocks. IOCTL function spy_io_hook_install
SPY_IO_HOOK_INSTALL functions use the Hook entry point (hook entry point) stored in the global aspyhooks [] array (HOOK Entry Point) to modify the service table in the system SDT. This global array is built by SpyHOKInitialize () (List 5-5) and SpyHOKInitializeex () when the driver is initialized. Each valid element in an AspyHooks [] array includes a hook entry point and the corresponding format string address. SpyDispatcher () calls the auxiliary function spiokinstall () (see List 5-12) to install the HOOK. SpyhookExchange () using spyhookstall () is also included in Listing 5-12.
DWORD Spyhookexchange (Void)
{
PNTProc serviceable;
BOOL FPAUSE;
DWORD I;
DWORD N = 0;
FPAUSE = SPYHOOKPAUSE (TRUE);
ServiceTable = keserviceDescriptive-> ntoskrnl.serviceTable;
For (i = 0; i { IF (AspyHooks [i] .pbformat! = null) { Aspyhook [i] .handler = (ntproc) InterlocKedexchange ((Plong) ServiceTable i, (Long) aspyhook [i] .handler); N ; } } GfspyhookState =! gfssyhookstate; Spyhookpause (FPAUSE); Return n; } / / -------------------------------------------------------------------------------------------- ----------------- NTSTATUS SpyhookStall (Bool Freset, PDWORD PDCOUNT) { DWORD N = 0; NTSTATUS NS = Status_INVALID_DEVICE_STATE IF (! gfsspyhookstate) { GHSPYHOKTHREAD = psgetcurrentthreadid (); n = spyhookedExchange (); IF (FRESET) spyhookreset (); NS = status_success; } * pdcount = n; Return ns; } Listing 5-12. Patch The System's API Service Table A spyhookexchange () function needs to be used when installing and removing hooks, which is just a simple exchange system API service table and the contents of the AspyHooks [] array. Therefore, if you call both spyhookexchange (), the initial state of the service table and array can be restored. SpyhooKexChange () Traversed aspyhook [] array to find array elements that contain format string pointers. The format string here is to specify the API function to be monitored. In this case, the InterlocKedexChange () function in ntoskrnl.exe will switch the Handler member of the API function pointer in the service table and the Handler member of the AspyHooks [] element, using the interlocKedexchange () function to ensure that there is no other thread to interfere with this operation. . The protocol mechanism will be temporarily stopped in this process until the end of the modification of the service table. SpyhookStall () is only a outsourcing function of SpyhooKexChange (), which is to perform some additional operations: l If the global flag GFSPYHOOKSTATE indicates that Hooks is still installed, the Access Table is disabled. l The caller's thread ID will be written to GHSPYHOOKTHREAD. The Hook Dispatch in the SpyHOKInitializeEx () function will shield the API call from the thread of the variable. To avoid interference from the HOOK protocol. l According to the client's request, the protocol will be reset. This means that all buffers will be emptied, and the handle directory will also be reinitialized. SPY_IO_HOOK_INSTALL receives a logical parameter incorporated by the caller. If true, the protocol will be reset after the Hooks installation is complete. This is a common option. If you are False, the protocol will continue from the end of the previous HOOK session. The return value of this function represents the number of items modified in the service table. If you are Windows 2000, spy_io_hook_install returns 44, this value is the size of the format string array APDTSDTFORMATS [] given by List 5-6. Under Windows NT 4.0, there is only 42 hooks installed because the API function ntnotifychangemultipleKeys () and ntQueryOpenSubkeys () are not supported by NT 4.0. …………to be continued…………..