Computer networks and the devices and services that reside on them are often the subject of attacks by parties that are attempting to improperly access information and resources or to introduce malicious code to the networks. Branch-oriented programming (BOP) relies on short runs of code already present and executable in a target program's address space. One type of BOP attack is based on return oriented programming (ROP), wherein attackers use the call stack and a function return primitive to link or chain together short runs of code already present in a program's address space in order to gain control of programs without relying on code injection. Another form of BOP attack is jump-oriented programming (JOP), in which an attacker links code together by providing a program control flow routine (commonly called a dispatcher) combined with a series of pointers to short runs of code that form the JOP program.
According to one aspect of the present invention, examples of a method, a system, and a persistent computer media having instructions for detecting branch oriented program code are shown involving searching the pages of memory to identify a list of code pointers and, for each code pointer in the list of code pointers, disassembling a segment or block of code corresponding to the code pointer, determining whether the segment of code terminates in a branch instruction, and removing the segment or block of code from the list if it does not terminate in a branch instruction. The method also involves, for each remaining code pointer in the list of code pointers, searching a window of code to determine whether the branch instruction and the target address of the branch instruction both fall within the window and removing the segment of code from the list if the branch instruction and target address are not both within the window.
In one refinement of the method, the search of the pages of memory includes searching the pages of memory based on each possible pointer or address alignment for an architecture corresponding to the code in the pages of memory.
In another refinement of the method, the method further involves, for each remaining code pointer in the list of code pointers, determining whether the branch instruction in the segment of code pointed to terminates in any type of branch instruction, and if so, flagging the code pointer as a gadget pointer.
In still another refinement of the method, the method further involves, for each remaining code pointer in the list of code pointers, determining whether the identified branch instruction which ends the gadget occurs before the appearance of any instruction which is invalid or invalid in context, or the appearance of any offset at which nothing exists (i.e. the beginning of uncommitted memory), or a number of otherwise valid instructions representing a gadget size threshold, and, if so, flagging the code segment as a likely BOP gadget.
Various embodiments in accordance with the present disclosure will be described with reference to the drawings, in which:
Note that the same numbers are used throughout the disclosure and figures to reference like components and features.
The subject matter of embodiments of the present invention is described here with specificity to meet statutory requirements, but this description is not necessarily intended to limit the scope of the claims. The claimed subject matter may be embodied in other ways, may include different elements or steps, and may be used in conjunction with other existing or future technologies. This description should not be interpreted as implying any particular order or arrangement among or between various steps or elements except when the order of individual steps or arrangement of elements is explicitly described.
Examples of methods and systems are shown for detecting BOP exploit code as described below.
A new class of code-reuse attack, called branch-oriented programming (BOP), which includes jump-oriented programming (JOP) and return-oriented programming (ROP), has emerged that exploits short runs of code already present and executable in a target program's address space to form a BOP program. In both cases, BOP code is composed of short runs of code already present and executable in a target program's address space. In the case of ROP, the attacker links code together by utilizing the call stack and a function return primitive (such as a RET instruction on x86). In the case of JOP, the attacker links code together by providing a program control flow routine (commonly called a dispatcher) combined with a series of pointers to the short runs of code forming the JOP program. In both cases parameters may also be present in some form, whether or not inline. Both of these techniques enable attackers to overcome certain mitigation techniques and gain control of exploitable programs without executing attacker-introduced code.
Return-oriented programming (ROP) is an effective code-reuse attack in which short code sequences ending in a ret instruction are found within existing binaries and executed in arbitrary order by taking control of the call stack. This allows for Turing-complete behavior in the target program without the need for injecting attack code, thus significantly negating current code injection defense efforts (e.g., W⊕X). On the other hand, its inherent characteristics, such as the reliance on the stack and the consecutive execution of return oriented gadgets, have prompted a variety of defenses to detect or prevent it from happening.
For an example of JOP, see Bletsch et al., “Jump-Oriented Programming: A New Class of Code-Reuse Attack,” Proceedings of the 6th ACM Symposium on Information, Computer and Communications Security, 2011. The JOP based attack eliminates the reliance on the stack and return instructions seen in return-oriented programming, but, like ROP, builds and chains functional gadgets, e.g. small segments of functional code, each performing certain primitive operations, except that the JOP gadgets end in an indirect branch rather than a return as in ROP. Without the use of the return instruction to unify the gadgets, a JOP attack relies on a dispatcher gadget to dispatch and execute the functional gadgets.
Many instruction set architectures, including x86, have variable-length instructions. The function of an instruction in a variable-length instruction set depends to varying degrees on an entire instruction. The function of an instruction can be significantly changed by removing one or more bytes from the beginning of the instruction. This is particularly true in cases where an instruction contains a mandatory prefix byte that is an escape byte or in cases where a prefix is used to modify the length of a parameter to the instruction, among others. It is also likely that changing the initial offset will change the function of subsequent instructions because each subsequent instruction begins immediately following the last byte of the preceding one.
It is occasionally possible for an attacker to branch execution to offsets in the middle of an instruction, resulting in modified behavior. This serves two functions: obfuscation of the function of an attack payload and the ability to transform the function of existing bytecode. Legitimate programs typically follow their own blockgraph and rarely split instructions. An example of an exception is LOCK prefix splitting in x86 architectures. Instruction splitting is, therefore, a strong indicator of malicious code execution. The correct alignment of an instruction can be determined by parsing the section of bytecode in which it falls by starting from a known-good offset. Exported symbols and a program's entry point are examples of known-good offsets. Each subsequent offset at which a new instruction starts can then also be considered to be a known-good offset. Branches to offsets other than known-good offsets are not part of normal program operation and are highly likely to be the result of exploitation of software vulnerabilities provided that the unaligned offsets do, in fact, produce a series of executable instructions with a different function.
Additionally, because the instructions in most microarchitectures are considerably more basic than the logical components of a programmer's intentions, merely removing the initial part of a programmer's function and rearranging the order of execution without splitting instructions (or in a fixed-instruction-width microarchitecture) is also able to substantially change the function of a program. Accordingly, for the purposes of detecting jump-oriented programming, branches to offsets in code blocks that would not normally be branched to in the course of program execution, e.g. branches to the middle of a program rather than an entry point, may be treated the same way as branches to the middle of instructions, i.e. instruction splitting.
In certain embodiments of the present invention, detecting these jumps involves disassembly of the program under test to determine a control flow graph and the individual basic blocks of the program. In this context, a basic block begins at the first offset into a block of code, such as the address of a symbol representing a function to be called, the entry point of a program, or the destination address of a branch instruction residing in a known legitimate portion of code. The basic block ends at any instruction that would cause execution to cease or to branch, which includes instructions that are likely to generate a CPU exception, any branch instruction (such as RET in x86 architectures), and any invalid instruction. For the purposes of this determination, a conditional jump instruction or a call instruction cause the start of a basic block to be at both the destination and the following instruction. A return instruction does not introduce another basic block and is treated as terminal for the purposes of disassembly. The nodes of the blockgraph are used here for JOP detection rather than the edges of the graph.
A BOP program, as a malicious payload, generally has several defining characteristics regardless of the specifics of its dispatcher or the method in which it was injected. For example, it will typically occupy a contiguous and limited area of memory, and contain the addresses of the gadgets it uses. The property of contiguity is not essential, except that it implies the addresses contained in the payload will be tightly clustered. There will also typically be a finite number of addresses in a BOP program. These and similar properties may be used to filter out the noise introduced by interpreting every stream of bytes encountered that appears to include an address as such, and refine a list of possible BOP attacks into a set of instructions that has a high probability of being a BOP chain. However, while it is normally a constraint for BOP attacks to have a finite number of gadget addresses, it is not necessarily the case that the addresses will be contiguous. Another characteristic is that the BOP chain normally exists within read/write memory, since the attacker must have some way to inject it into process memory, and the computer must be able to read and execute the BOP chain.
In certain embodiments of the present method, the method involves searching each page of memory from each alignment (there are 4 possible alignments in 32-bit systems and 8 in 64-bit systems) for sequences which appear to be code pointers (that is, numbers which correspond to an address which is within the program blockgraph) to build an unrefined list of potential gadget pointers. This list may then be refined by detecting whether these addresses actually point at a gadget-like sequence of code, and refined still further by determining their proximity to other such pointers in memory.
One refinement detects whether a BOP gadget is present at an address by disassembling from that address for some set number of instructions. This parameter will generally be selected to reflect the longest gadget that is expected to be found. In practice, gadgets tend to be short because they are intended to be building blocks for arbitrary functionality and must thus be somewhat nonspecific, which generally implies shortness. If the resulting disassembly ends in a branch instruction, then it is possible for the referenced code to be a gadget. If it does not, the code segment is excluded and the address is removed from the list possible BOP gadgets.
A second refinement considers the proximity of each address in the refined list to other such addresses. A sliding window search may be made, where the window size and, optionally, a threshold, e.g. minimum number of gadget addresses to be contained within the window, may be fixed or adjustable parameters. If a branch instruction and the target address to which it branches are found within the sliding window, then it is inferred that a BOP program's jump table or call stack resides near that location in memory and an attempt to exploit the application under analysis using a BOP exploit is evident.
In one example, a search of the pages of memory includes searching the pages of memory based on each possible address alignment for an architecture corresponding to the code in the pages of memory. For example, if the architecture address word length is 4 bytes, each of the page offset, the page offset plus one, the page offset plus two, and the page offset plus three would be used as starting offsets to search the page. Similarly, if it is two bytes (as in a 16-bit architecture), the page offset and the page offset plus one will be used for starting offsets. If the architecture uses 24-bit (3 byte) addresses and 32-bit (4 byte) data words, the +0, +1, and +2 alignments would be searched. This relies upon an underlying assumption that a jump table containing gadget addresses is likely to be a series of consecutive addresses in memory (beginning at an offset aligned to one of the start offsets), so that they can be accessed using a scale-index-base type mechanism. Additional JOP dispatcher complexity would be required to avoid this assumption, and payload complexity is undesirable to an attacker because it decreases reliability of the JOP dispatcher while generally increasing detectability of the attack. Similarly, a ROP chain is typically simple.
At step 320, a check is performed for the last instruction alignment. If the alignment used is not the last possible instruction alignment, then control branches to step 322 to determine the next alignment and control branches to step 306 to search the memory page for possible BOP gadgets using the new instruction alignment. Control will cycle through steps 306, 310, 320 and 322 until the page has been searched for all possible alignments, e.g. four alignments in 32-bit systems, eight alignments in 64-bit systems.
When the memory page has been analyzed for all alignments, control branches to step 330 to determine whether the memory page analyzed was the last page to be considered.
If the memory page just analyzed is not the last page, then control branches to step 334 to obtain the next page to be analyzed and analysis proceeds from step 304 as described above. If this was the final page, control branches to step 332 and creation of an unrefined list of potential BOP code segments or gadgets.
One aspect of the present invention involves disassembly from the original entry point and the starting offsets of all exports of a program to generate a list of aligned offsets in a program, and the offsets of legitimate code branch destinations, for the purpose of determining the maliciousness of a branch destination address. Another aspect is the transformation of a list of arbitrary and possibly unaligned pointers to fragments of program text by cross-referencing them with the original program text interpreted as a context-free byte stream and, in turn, the transformation of these program fragments into a list of blocks of program text (original or synthetic as the result of instruction splitting) that may be gadgets used by an attacker.
An aspect of the present invention is inferring the existence of a BOP program where a certain number of proximal addresses of gadgets exist. In this example, if the segment is found to terminate with a branch instruction at step 410, then control flows to step 412 where a sliding window is used to search for proximal gadget pointers to the pointer dereferenced in step 404. The window size may, for example, be predetermined or adjusted and reflects the characteristic of JOP exploits that the jump table is usually small (i.e. the elements of the jump table forming the JOP program are co-proximal) and, similarly, that a ROP chain is relatively small and closely packed. If no proximal gadget pointers are detected at step 412, then control branches at step 420 to step 422 to remove the item from the list. Process 400 continues until the end of the list is encountered at step 430, at which point the process is completed having identified or not identified a BOP program or produced a refined list of BOP exploits 432. At this point, the process 400 has produced output that is useful for analysis of BOP exploits without proceeding to process 500 described below.
Still another aspect of the present invention is the use of gadget size as a heuristic, which may be adjustable, to ascertain the likelihood that a block of executable code starting from an unaligned offset is in fact of some use to an attacker. In this example, control branches to step 510 where the size of the code block segment is checked against a predetermined or adjustable gadget size, which reflects the characteristic of BOP gadgets to typically consist of small segments of code. Note that step 510 may be combined with step 410 of
In an alternative example, the process 500 of
Various embodiments may take different approaches utilizing this heuristic. In one example, for each remaining code pointer in the list of code pointers, determine whether the size of the segment of code is less than a gadget size threshold and if so, flagging the code segment as a likely BOP gadget. In another example, for each remaining code pointer in the list of code pointers, given a disassembly of the program from known intended entry points, determine whether the offset of the code pointed to is aligned with the normal program flow (i.e. is not a split instruction) or splits an instruction only in a manner commonly done in the microarchitecture in use (e.g. splitting away the LOCK prefix in x86), and if it is not and does not, indicating that a BOP gadget that splits instructions was found, and programmatically assign an increased degree of confidence that the address is in fact a jump or return offset related to a BOP exploit. In an additional example, given the list of likely BOP gadgets that are referenced by an apparent jump table or ROP chain, determine whether those gadgets and the jump table in the aggregate represent evidence of a branch-oriented programming exploit or exploitation attempt with regard to certain properties thereof including, but not limited to, contiguity, beginning offset, metadata (e.g. heap allocation information; busy/free; writeability; adjacent corruption) pertaining to the location, and length of the alleged JOP table or ROP chain, and the confidence with which the addresses within the alleged JOP table or ROP chain are believed to reference BOP gadgets.
In accordance with at least one embodiment of the invention, the system, apparatus, methods, processes and/or operations described herein may be wholly or partially implemented in the form of a set of instructions executed by one or more programmed computer processors, such as a central processing unit (CPU) or microprocessor. Such processors may be incorporated in an apparatus, server, client or other computing device operated by, or in communication with, other components of the system. In accordance with another embodiment of the invention, the system, apparatus, methods, processes and/or operations described herein may be wholly or partially implemented in the form of a set of processor executable instructions stored on persistent storage media.
It should be understood that the present invention as described above can be implemented in the form of control logic using computer software in a modular or integrated manner. Based on the disclosure and teachings provided herein, a person of ordinary skill in the art will know and appreciate other ways and/or methods to implement the present invention using hardware and a combination of hardware and software.
Any of the software components, processes or functions described in this application may be implemented as software code to be executed by a processor using any suitable computer language such as, for example, Java, C++ or Perl or using, for example, conventional or object-oriented techniques. The software code may be stored as a series of instructions, or commands on a computer readable medium, such as a random access memory (RAM), a read only memory (ROM), a magnetic medium such as a hard-drive or a floppy disk, or an optical medium such as a CD-ROM, where the code is persistently stored sufficient for a processing device to access and execute the code at least once. Any such computer readable medium may reside on or within a single computational apparatus, and may be present on or within different computational apparatuses within a system or network.
All references, including publications, patent applications, and patents, cited herein are hereby incorporated by reference to the same extent as if each reference were individually and specifically indicated to be incorporated by reference and/or were set forth in its entirety herein.
The use of the terms “a” and “an” and “the” and similar referents in the specification and in the following claims are to be construed to cover both the singular and the plural, unless otherwise indicated herein or clearly contradicted by context. The terms “having,” “including,” “containing” and similar referents in the specification and in the following claims are to be construed as open-ended terms (e.g., meaning “including, but not limited to,”) unless otherwise noted. Recitation of ranges of values herein are merely indented to serve as a shorthand method of referring individually to each separate value inclusively falling within the range, unless otherwise indicated herein, and each separate value is incorporated into the specification as if it were individually recited herein. All methods described herein can be performed in any suitable order unless otherwise indicated herein or clearly contradicted by context. The use of any and all examples, or exemplary language (e.g., “such as”) provided herein, is intended merely to better illuminate embodiments of the invention and does not pose a limitation to the scope of the invention unless otherwise claimed. No language in the specification should be construed as indicating any non-claimed element as essential to each embodiment of the present invention.
Different arrangements of the components or steps depicted in the drawings or described above, as well as components and steps not shown or described, are possible without departing from the scope of the invention. Similarly, some features and subcombinations are useful and may be employed without reference to other features and subcombinations. Embodiments of the invention have been described for illustrative and not restrictive purposes, and alternative embodiments will be apparent to one of ordinary skill in the art. Accordingly, the present invention is not limited to the embodiments described above or depicted in the drawings, and various embodiments and modifications can be made without departing from the scope of the invention.
This application claims the benefit of U.S. Provisional Patent Appl. No. 62/022050 for “System and Method for Detecting Branch Oriented Programming Anomalies” filed Jul. 8, 2014, herein incorporated by reference in its entirety for all purposes.
This invention was made with government support under FA8750-12-C-0161 awarded by the United States Air Force. The government has certain rights in this invention.
Number | Date | Country | |
---|---|---|---|
62022050 | Jul 2014 | US |