Читаем Windows® Internals, Sixth Edition, Part 1 полностью

You can duplicate the same lookup performed by the kernel when dealing with a system call ID to figure out which function is responsible for handling it and how many arguments it takes

The KeServiceDescriptorTable and KeServiceDescriptorTableShadow tables both point to the same array of pointers (or offsets, on 64-bit) for kernel system calls, called KiServiceTable, and the same array of stack bytes, called KiArgumentTable. On a 32-bit system, you can use the kernel debugger command dds to dump the data along with symbolic information. The debugger attempts to match each pointer with a symbol. Here’s a partial output:lkd> dds KiServiceTable 820807d0 821be2e5 nt!NtAcceptConnectPort 820807d4 820659a6 nt!NtAccessCheck 820807d8 8224a953 nt!NtAccessCheckAndAuditAlarm 820807dc 820659dd nt!NtAccessCheckByType 820807e0 8224a992 nt!NtAccessCheckByTypeAndAuditAlarm 820807e4 82065a18 nt!NtAccessCheckByTypeResultList 820807e8 8224a9db nt!NtAccessCheckByTypeResultListAndAuditAlarm 820807ec 8224aa24 nt!NtAccessCheckByTypeResultListAndAuditAlarmByHandle 820807f0 822892af nt!NtAddAtom

As described earlier, 64-bit Windows organizes the system call table differently and uses relative pointers (an offset) to system calls instead of the absolute addresses used by 32-bit Windows. The base of the pointer is the KiServiceTable itself, so you’ll have to dump the data in its raw format with the dq command. Here’s an example of output from a 64-bit system:lkd> dq nt!KiServiceTable fffff800'01a73b00 02f6f000'04106900 031a0105'fff72d00

Instead of dumping the entire table, you can also look up a specific number. On 32-bit Windows, because each system call number is an index into the table and because each element is 4 bytes, you can use the following calculation: Handler = KiServiceTable + Number * 4. Let’s use the number 0x102, obtained during our description of the NtReadFile stub code in Ntdll.dll.lkd> ln poi(KiServiceTable + 102 * 4) (82193023) nt!NtReadFile

On 64-bit Windows, each offset can be mapped to each function with the ln command, by shifting right by 4 bits (used as described earlier) and adding the remaining value to the base of KiServiceTable itself, as shown here:lkd> ln @@c++(((int*)@@(nt!KiServiceTable))[3] >> 4) + nt!KiServiceTable (fffff800'01d9cb10) nt!NtReadFile | (fffff800'01d9d24c) nt!NtOpenFile Exact matches: nt!NtReadFile =

Because drivers, including kernel-mode rootkits, are able to patch this table on 32-bit versions of Windows, which is something the operating system does not support, you can use dds to dump the entire table and look for any values outside the range of valid kernel addresses (dds will also make this clear by not being able to look up a symbol for the function). On 64-bit Windows, Kernel Patch Protection monitors the system service tables and crashes the system when it detects modifications.

EXPERIMENT: Viewing System Service Activity

You can monitor system service activity by watching the System Calls/Sec performance counter in the System object. Run the Performance Monitor, click on Performance Monitor under Monitoring Tools, and click the Add button to add a counter to the chart. Select the System object, select the System Calls/Sec counter, and then click the Add button to add the counter to the chart.

Object Manager

As mentioned in Chapter 2, Windows implements an object model to provide consistent and secure access to the various internal services implemented in the executive. This section describes the Windows object manager, the executive component responsible for creating, deleting, protecting, and tracking objects. The object manager centralizes resource control operations that otherwise would be scattered throughout the operating system. It was designed to meet the goals listed on the next page.

EXPERIMENT: Exploring the Object Manager

Throughout this section, you’ll find experiments that show you how to peer into the object manager database. These experiments use the following tools, which you should become familiar with if you aren’t already:

WinObj (available from Sysinternals) displays the internal object manager’s namespace and information about objects (such as the reference count, the number of open handles, security descriptors, and so forth).

Process Explorer and Handle from Sysinternals, as well as Resource Monitor (introduced in Chapter 1) display the open handles for a process.

The Openfiles /query command displays the open file handles for a process, but it requires a global flag to be set in order to operate.

The kernel debugger !handle command displays the open handles for a process.

Перейти на страницу:

Похожие книги