📜 ⬆️ ⬇️

How to make Linux kernels from Windows?

Practical experience in the development of protective equipment applied

We are starting to publish a series of practical articles on the particular issues of the implementation of the imposed remedies, namely, embedding in software systems. On the example of the Linux kernel, the methods and tools used to modify, extend and supplement its functionality will be discussed.

The first article will be introductory with a brief overview of key embedding methods. Next, we take a closer look at the individual methods of embedding, paying attention to technical details.


Approaches to building remedies


In accordance with common practice, a model including categories of confidentiality, integrity and availability is used as a standard model of information security. At the same time, protected systems are systems that are assigned the functions of implementing this model. Being the basic element of such a system, the core of the operating system (OS) plays a crucial role in the process of ensuring the protection of information; therefore, the issue of enhancing its security is of paramount importance.
')
There are two approaches to building remedies: built-in tools and cash-on tools. Built-in tools are characterized by the initial presence in the protected system, while the imposed funds are introduced into the protected system during its operation, prior to its operation.

Each approach has its strengths and weaknesses that define the limits of applicability. Often the forte of one approach is a weak point of the other. So, the advantages of the built-in protection include the absence of the need to verify the authenticity of the protected system; the same is a lack of funds imposed - how to determine what is protected authentic? On the other hand, the integration of the built-in protection into the protected system carries with it a restriction on the choice of the supplier of the operating system components and the protection itself. This problem is particularly acute in the Russian market, where the certification of systems plays an important role, and the built-in protection tools do not always meet the requirements determined by regulators (see the requirements of the FSTEC of Russia).

Goals and objectives of embedding in software systems


Like any software system, the core of an operating system is a set of interrelated software modules (components) that make up a common computing system. The implementation of the imposed means of protecting the OS kernel, and in particular the Linux kernel, implies the need to be embedded in the mechanisms of its subsystems. At the same time, embedding refers to the process of introducing additional (third-party) program elements, carried out in such a way that, on the one hand, the functioning of the system itself remains, and on the other, its functionality is expanded or changed.

Speaking of embedding, we will consider the following practical problem. Let there be some target component of the software system, functioning in accordance with a given (basic) algorithm. It is necessary to modify the operation of this component so as to be able to make specific changes to this basic algorithm.

Thus, the main purpose of embedding is to obtain the ability to control, modify and expand the functions of the components of the software system, whereas the main task of embedding is to ensure implementation into the existing software system while maintaining its functionality. Successfully performed embedding is characterized by the preservation of the functioning of the software system in the presence of a new component in its composition.
Being a central part of modern software systems, the OS kernel acts as an intermediary between applications and devices that perform data processing at the hardware level. In this case, its main task is the effective management of resources.

About embedding in the Linux kernel


By its architecture, the Linux kernel is a monolithic kernel with support for the possibility of extending functionality through modules that are loaded as needed in the process. Given this feature, there is an opportunity for the Linux kernel to develop extensions that, being actually part of the kernel, can redefine / supplement its various functions, i.e. actually change the order of its subsystems.

Considering the components of the software systems as various kinds of application and system programs running on the corresponding hardware, it is possible to establish a link between embedding and obtaining the possibility of intercepting control during the execution of sections of these programs. In this case, the program code that handles such situations is called an intercept code or, more simply, a hook. The terms interception (control) and embedding are considered to be similar and, if this is not specified separately, are used to denote the same. However, one should keep in mind the existing distinction between them: embedding is an implementation process in a general sense, while interception rather points to a specific methodical technique.

A distinctive feature of dynamic embedding methods is that there is no need to reboot the target system in order for the expected changes to take effect. As a rule, interception objects are functions - elements of the kernel code that implement one or another algorithm. Less commonly, embedding occurs in such system mechanisms as exception handlers and, in particular, the system call manager.

Intercepting kernel functions is a basic method that allows you to redefine / supplement its various mechanisms. Based on the fact that the Linux kernel is written almost entirely in C, with the exception of small architecture-specific parts, it can be argued that to implement embedding in most of the kernel components, it is enough to be able to intercept the corresponding functions.

Exception handling underlies the functioning of a variety of system mechanisms. As a result, intercepting exception handlers of the Linux kernel allows you to increase the degree of control over the system, while intercepting the system call manager allows you to regulate application software requests to Linux kernel services.

Traditional methods of embedding are based on patching (eng., Patching), a technique for making changes to a code or data that allows you to modify the behavior of the target algorithm as required. Technically, the result of the patch is to change the contents of the cells in the RAM. However, code modification, in contrast to data modification, has its own characteristics, related primarily to the fundamental difference between code and data.
The implementation of interception using the patching technique requires qualification, as well as an understanding of the principles of operation not only of the kernel itself, but also of the features of the used hardware platform. When modifying the code, it is worth paying special attention to the correctness of embedding in the case of multiprocessor systems, because as a result of the changes the coherence should not be violated. In addition, it is necessary to take into account the need to bypass the mechanisms for protecting the kernel code from modification, as well as the features of searching and using hidden and non-exported characters. Anyway, in most cases, patching allows you to solve the problem of embedding.

The lack of patching can be considered a necessary violation of the integrity of the components of the target system. Making changes to the code can easily be detected, which in some contexts is a fundamental limitation. An example of such restrictions is, in particular, the Windows kernel protection mechanism - Kernel Patch Protection , better known as PatchGuard. One of its features is the implementation of integrity monitoring of key components of the OS kernel, which negates most standard embedding methods based on code modification. In this case, disabling this tool to install the overlay is an extreme option, since in the absence of redundant functionality in an embedded security feature, the overall security of the system is obviously reduced.

To implement embedding while preserving the integrity of the target components, methods should be used that are free from such restrictions. As a rule, some of these methods use the hardware capabilities of the platform (for example, hardware breakpoints), which in principle cannot be universal, considering at least the limitations on the number of interceptions to be installed. On the other hand, it is always possible to use all sorts of virtual functions and other dynamically replaceable pointers that allow you to redefine the behavior of the system within certain limits. The latter, in particular, is common for intercepting operations carried out within the virtual file system ( VFS ), when virtual object tables are used for operations with objects, which can be replaced without modifying the code. However, this approach also has a number of limitations, the most important of which is that there is no possibility to control the control of which is not provided.

Conclusion


Thus, there are ways for embedding in the OS kernel, the use of which for a specific task is more or less expedient. Patching is a basic method of embedding and can be applicable if there are no restrictions on the preservation of integrity (code). Otherwise, depending on the situation, architecture-specific solutions (such as using hardware breakpoints), overloading of virtual functions, and other methods can be applied.

Anyway, the implementation of embedding into the core allows modifying the logic of its components, and at the same time increasing the degree of its protection by embedding the mezhanizm intended for this.

In the next article, we will examine in detail one of the most common methods of embedding - the method of intercepting kernel functions.

Source: https://habr.com/ru/post/230697/


All Articles