The present invention relates generally to computer security and, in particular, to the reduction of buffer overflow exploits by computer viruses.
A run-time stack (also called a call-stack, execution stack, control stack or function stack, for example) in a computer is commonly used to store information about active subroutines of a program being executed on the computer. The main purpose of the run-time stack is to store the program address to which each active subroutine should return control when it finishes executing. This is called the return address. However, a typical stack may also include the calling arguments of the subroutine, the frame pointer of the subroutine caller, local variables of the subroutine being called together with a data buffer associated with the subroutine being called. A run-time stack is usually arranged as one or more frames, each frame corresponding to a subroutine.
Some computer viruses will deliberately cause a subroutine executing on a computer to overflow its data buffer on the run-time stack in hope of overwriting the subroutine return address with an address of code within the virus. Upon exiting the subroutine, the computer will then branch to the virus's code instead of returning to the calling program, thus giving execution control to the virus. A variation of this is to overwrite the return address with an address to existing code such that this code, trusting the caller, inadvertently gives control to the virus. Once the virus programmer discovers a buffer overflow exploit that works, that exploit can be used to attack all similar computers.
One common solution is to add code that ensures no subroutine will ever overflow its buffers. This adds cost by making subroutines larger and by requiring more execution time to check every buffer access.
Another prior solution is to separate the runtime stack into two stacks, one only for dynamic data allocation (i.e. buffers), and one only for subroutine linkage (i.e. return addresses). This adds cost by requiring changes to the CPU architecture to support two stacks. This means changes in the computer instruction set and consequently, a change in its software development tools.
Another solution, disclosed in EP1662379A1, is to add hardware to catch any write accesses to the return address on the stack. This doesn't affect the instruction set but does require an amount of hardware that is proportional to the maximum number of return addresses that may be on the stack at any time.
Another proposed solution, disclosed in US2003/0172293A1, is to encode application data when it is written using a technique unique to the “storage area”. The data would then be decoded using the inverse technique, again based on the storage area. Thus, any data overflow from one storage area into another would result in the overflow data being misinterpreted as nonsense when it is later decoded by a program that is using the proper decoding for the violated storage area. In this solution, return addresses are not encoded or decoded so buffer overflows would also be interpreted as nonsense. This solution requires changes to the CPU architecture so the encoding/decoding of application data happens automatically. This requires instruction set changes with the resulting changes to the software development tools. It can even require changes to the “pointer” data type so data passed by reference will know which storage area is associated with the current pointer value.
The accompanying figures, in which like reference numerals refer to identical or functionally similar elements throughout the separate views and which together with the detailed description below are incorporated in and form part of the specification, serve to further illustrate various embodiments and to explain various principles and advantages all in accordance with the present invention.
Skilled artisans will appreciate that elements in the figures are illustrated for simplicity and clarity and have not necessarily been drawn to scale. For example, the dimensions of some of the elements in the figures may be exaggerated relative to other elements to help to improve understanding of embodiments of the present invention.
Before describing in detail embodiments that are in accordance with the present invention, it should be observed that the embodiments reside primarily in combinations of method steps and apparatus components related to reducing buffer overflow exploits by computer viruses. Accordingly, the apparatus components and method steps have been represented where appropriate by conventional symbols in the drawings, showing only those specific details that are pertinent to understanding the embodiments of the present invention so as not to obscure the disclosure with details that will be readily apparent to those of ordinary skill in the art having the benefit of the description herein.
In this document, relational terms such as first and second, top and bottom, and the like may be used solely to distinguish one entity or action from another entity or action without necessarily requiring or implying any actual such relationship or order between such entities or actions. The terms “comprises,” “comprising,” or any other variation thereof, are intended to cover a non-exclusive inclusion, such that a process, method, article, or apparatus that comprises a list of elements does not include only those elements but may include other elements not expressly listed or inherent to such process, method, article, or apparatus. An element that is preceded by “comprises . . . a” does not, without more constraints, preclude the existence of additional identical elements in the process, method, article, or apparatus that comprises the element.
It will be appreciated that embodiments of the invention described herein may comprise one or more conventional processors and unique stored program instructions that control the one or more processors to implement some, most, or all of the functions associated with reducing buffer overflow exploits by computer viruses described herein. As such, these functions may be interpreted as a method to reduce buffer overflow exploits by computer viruses. Alternatively, some or all functions could be implemented by a state machine that has no stored program instructions, or in one or more application specific integrated circuits (ASICs), in which each function or some combinations of certain of the functions are implemented as custom logic. Of course, a combination of the two approaches could be used. Thus, methods and means for these functions have been described herein. Further, it is expected that one of ordinary skill, notwithstanding possibly significant effort and many design choices motivated by, for example, available time, current technology, and economic considerations, when guided by the concepts and principles disclosed herein will be readily capable of generating such software instructions and programs and ICs with minimal experimentation.
New stack elements are added to the top of the stack (denoted by SP (stack pointer) in the figure). Commonly, the top of the stack is at a lower memory address than the bottom of the stack. Further, buffers are written from a low address to a high address. This creates a possibility that elements previously stored on the stack may be overwritten accidentally if the space allocated in a memory buffer is too small. In particular, an element, such as an array or string, written to a particular stack address may overwrite the return address stored in the frame. When the subroutine is exited, the return address will be incorrect and program control will branch to the wrong address.
This error may be exploited by a programmer, who can overwrite the return address with an address of his or her choosing, and so gain control of the computer. This technique is called a buffer overflow exploit.
In
The present invention relates to a method that encodes the subroutine linkage information, such as a return address and/or a frame pointer, during a subroutine call. The encoding technique can be any reversible mapping that is unique (1) to the construction of the system, (2) to the initialization of the system, (3) to the context of the current process, or (4) to the specific subroutine call. Upon returning from a subroutine, the linkage information is decoded appropriately. If the linkage information has been overwritten by a buffer overflow, it will result in information that is, for intents and purposes, random addresses. This will make it statistically unlikely for a virus to guess the correct encoding.
In some embodiments, the codec 304 utilizes a code value 308. The code value may be unique (1) to the construction of the system, (2) to the initialization of the system, (3) to the context of the current process, or (4) to the specific subroutine call.
Upon exit from the subroutine, the encoded linkage information 306 is decoded by the decoder of codec 304 to recover the original linkage information. If the stack 110 has been corrupted by a buffer overflow, the new value at the return address location will be modified by the decoding procedure before control branches. The resulting branch will be incorrect if the stack is corrupted, but the branch cannot be controlled by a malicious programmer.
Even if the correct encoding were discovered, it is unlikely that the next system/process/subroutine would have the same encoding.
This method can be applied to existing central processing unit (CPU) architecture, with no changes needed to existing application software. Subroutine linkage information is not normally accessible to application programs, so the encoding will have no impact on existing programs. In addition, this method does not require changing the instruction set of a CPU, so no changes to software development tools are needed.
The method may require some additional hardware to select an encoding technique, presumably a register, as well as hardware to do the encoding/decoding of the linkage information during subroutine calls and returns. If the encoding technique is chosen during system construction, no further changes are needed. If the encoding is dependent the initialization of the system, the context of the current process, or the specific subroutine call, then minor changes to the operating system may be needed.
If the encoded linkage information has been overwritten with, for example, the starting address of a virus code, the starting address is treated as if it was encoded data and is passed through the decoder. This alters the value, so control is not passed to the virus code.
Data written to the stack is not encoded (or is encoded using a different code value). Thus, a virus address in an over-sized data buffer will not be encoded, and will altered by the decoding process.
The method may be utilized by a variety of computers, including general purpose computers, network routers, network file servers, network client devices as well as portable embedded systems such as cellular telephones, personal digital assistants (PDA's), etc. Other applications will be apparent to those of ordinary skill in the art.
In the foregoing specification, specific embodiments of the present invention have been described. However, one of ordinary skill in the art appreciates that various modifications and changes can be made without departing from the scope of the present invention as set forth in the claims below. Accordingly, the specification and figures are to be regarded in an illustrative rather than a restrictive sense, and all such modifications are intended to be included within the scope of the present invention. The benefits, advantages, solutions to problems, and any element(s) that may cause any benefit, advantage, or solution to occur or become more pronounced are not to be construed as a critical, required, or essential features or elements of any or all the claims. The invention is defined solely by the appended claims including any amendments made during the pendency of this application and all equivalents of those claims as issued.