When you need to create, open, and operate various kernel objects, the system needs to create and operate several types of kernel objects, such as access symbol object, event object, file object, file ing object, I/O completed port object, job object, mailbox object, mutex object, pipeline object, process object, Beacon object thread object and wait timer object. These objects are created by calling functions. For example, the createfilemapping function allows the system to create a file ing object.
Each kernel object is only a memory block allocated by the kernel. And can only be accessed by this kernel. The memory block is a data structure, and its memory is responsible for maintaining various information about the object. Some data members (such as security descriptors and counters) are the same in all object types, but most data members belong to specific object types. For example, a process object has a process ID, a basic priority, and an exit code, while a file object has a byte displacement, a sharing mode, and an open mode.
Ms stipulates that kernel objects can only be accessed by the kernel, so the program cannot find the data structure in the memory and directly change their content. The objective is to ensure the consistency of the kernel object structure. This restriction allows you to add, delete, and modify data members in these structures without disrupting any applications.
We cannot modify it directly, but we need to modify it again. The object handle appears. When a kernel object is created, a handle is returned. This is an opaque value. You only need to know that it can mark the object you created. When you need to modify the kernel object, you only need to pass the handle to the API provided by MS for you. This API naturally knows which object you need to modify. It is worth noting that these handle values are closely related to processes. That is to say, the handle created by process a can only be used in its own process and all its threads. If other processes attempt to access this handle, the call will fail. Of course, Ms also provides several methods for sharing kernel objects between processes.
The kernel object has a reference count that indicates how many times your kernel object has been referenced. Because the kernel objects are all in the kernel, the kernel must know when external objects do not need to be used. The reference count is for this purpose. When a kernel object is created for the first time, it is counted as 1. When another process accesses it, it will add 1. When a process calls closehandle and passes in its handle, its reference count is reduced by 1. When the kernel detects that the reference count is 0, it finds a proper time to release the object. It is worth noting that even if closehandle is not called, the kernel will release this object when all processes that use this kernel object exit. Therefore, make sure that no kernel object is retained in the system when no process references this object. Of course, if it is not released, it may cause a large amount of memory usage during the program running.
For kernel objects, we should also focus on their security descriptors in addition to their handles, although this security descriptor is used in common applications (such as common small software and client applications) is not used. But for some occasions, such as servers. Or in applications that require user identity. It indicates the permission to access this application.
When you create a kernel object, a psecurity_attributes parameter is input, for example:
Handle createfilemapping (
Handle hfile,
Psecurity_attributes PSA,
DWORD flprotect,
DWORD dwmaximumsizehigh,
DWORD dwmaximumsizelow,
Pctstr pszname );
Most applications pass null to PSA, so that any member in the Object Management Group has the same full access permissions as the object creator.
Psecurity_attributes is defined as follows:
Typedef struct _ psecurity_attributes {
DWORD nlength
Lpvoid lpsecuritydescriptor; // security descriptor.
Bool binherithandle;
} Psecurity_attributes;
For Object Security descriptions, only the second member lpsecuritydescriptor is useful. For example, if you want to open a file ing, you can perform the following operations.
Handle hmapping = openfilemapping (file_map_read, FASE, "myfilemapping ");
The input file_map_read indicates that you need to open the file and read it after it is opened. At this time, the kernel will perform a security check to check whether you have the permission to read the ing file. This check is determined by the security descriptor passed in when you previously created the file ing.