Reversing : The Hacker's Guide to Reverse Engineering

(ff) #1

Viewing objects from user mode, as most applications do, gives them a
somewhat mysterious aura. It is important to understand that under the hood
all of these objects are merely data structures—they are typically stored in non-
paged pool kernel memory. All objects use a standard object header that
describes the basic object properties such as its type, reference count, name,
and so on. The object manager is not aware of any object-specific data struc-
tures, only of the generic header.
Kernel code typically accesses objects using direct pointers to the object data
structures, but application programs obviously can’t do that. Instead, applica-
tions use handlesfor accessing individual objects. A handle is a process specific
numeric identifier which is essentially an index into the process’s private han-
dle table. Each entry in the handle table contains a pointer to the underlying
object, which is how the system associates handles with objects. Along with
the object pointer, each handle entry also contains an access mask that deter-
mines which types of operations that can be performed on the object using this
specific handle. Figure 3.2 demonstrates how process each have their own
handle tables and how they point to the actual objects in kernel memory.
The object’s access mask is a 32-bit integer that is divided into two 16-bit
access flag words. The upper word contains generic access flags such as
GENERIC_READand GENERIC_WRITE. The lower word contains object spe-
cific flags such as PROCESS_TERMINATE, which allows you to terminate a
process using its handle, or KEY_ENUMERATE_SUB_KEYS, which allows you
to enumerate the subkeys of an open registry key. All access rights constants
are defined in WinNT.Hin the Microsoft Platform SDK.
For every object, the kernel maintains two reference counts: a kernel refer-
ence count and a handle count. Objects are only deleted once they have zero
kernel references and zero handles.


Named objects


Some kernel objects can be named, which provides a way to uniquely identify
them throughout the system. Suppose, for example, that two processes are
interested in synchronizing a certain operation between them. A typical
approach is to use a mutex object, but how can they both know that they are
dealing with the same mutex? The kernel supports object names as a means of
identification for individual objects. In our example both processes could try
to create a mutex named MyMutex. Whoever does that first will actually cre-
ate the MyMutex object, and the second program will just open a new handle
to the object. The important thing is that using a common name effectively
guarantees that both processes are dealing with the same object. When an
object creation API such as CreateMutexis called for an object that already
exists, the kernel automatically locates that object in the global table and
returns a handle to it.


Windows Fundamentals 81
Free download pdf