├── DISCLAIMER.md ├── LICENSE.md ├── README.md ├── code ├── ld-linux-x86-64.so.2 ├── libc.so.6 ├── ls ├── stack-functionptr ├── stack-functionptr.c ├── stack-return └── stack-return.c └── paper └── Hardware Control Flow Integrity for an IT Ecosystem.pdf /DISCLAIMER.md: -------------------------------------------------------------------------------- 1 | ## Disclaimer of Warranty 2 | This Work is provided "as is." Any express or implied warranties, including but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the United States Government be liable for any direct, indirect, incidental, special, exemplary or consequential damages (including, but not limited to, procurement of substitute goods or services, loss of use, data or profits, or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this Guidance, even if advised of the possibility of such damage. 3 | 4 | The User of this Work agrees to hold harmless and indemnify the United States Government, its agents and employees from every claim or liability (whether in tort or in contract), including attorneys' fees, court costs, and expenses, arising in direct consequence of Recipient's use of the item, including, but not limited to, claims or liabilities made for injury to or death of personnel of User or third parties, damage to or destruction of property of User or third parties, and infringement or other violations of intellectual property or technical data rights. 5 | 6 | Nothing in this Work is intended to constitute an endorsement, explicit or implied, by the United States Government of any particular manufacturer's product or service. 7 | 8 | ## Disclaimer of Endorsement 9 | Reference herein to any specific commercial product, process, or service by trade name, trademark, manufacturer, or otherwise, in this Work does not constitute an endorsement, recommendation, or favoring by the United States Government and shall not be used for advertising or product endorsement purposes. -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | This Work was prepared by a United States Government employee and, therefore, is excluded from copyright by Section 105 of the Copyright Act of 1976. 2 | 3 | Copyright and Related Rights in the Work worldwide are waived through the [CC0 1.0](https://creativecommons.org/publicdomain/zero/1.0/) [Universal license](https://creativecommons.org/publicdomain/zero/1.0/legalcode). 4 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Control Flow Integrity 2 | 3 | This project captures research to effectively fix the lack of underlying control flow enforcement that would prevent memory corruption exploitation. This mechanism does not exist today but could be implemented in the future by the IT industry. 4 | 5 | ## Hardware Control Flow Integrity (CFI) for an IT Ecosystem 6 | This paper is a brief introduction to the problem of memory corruption and a description of one way to prevent control flow hijacking. It also includes a discussion on the issues that may be encountered in the IT ecosystem when an architectural change like this is introduced. 7 | 8 | * [Download PDF](https://github.com/iadgov/Control-Flow-Integrity/raw/master/paper/Hardware%20Control%20Flow%20Integrity%20for%20an%20IT%20Ecosystem.pdf) 9 | * [View PDF on GitHub](https://github.com/iadgov/Control-Flow-Integrity/blob/master/paper/Hardware%20Control%20Flow%20Integrity%20for%20an%20IT%20Ecosystem.pdf) 10 | 11 | Additionally, Intel recently disclosed an x86 instruction specification called Control-flow Enforcement Technology (CET) that closely resembles Landhere. 12 | 13 | * [View spec at Intel](https://software.intel.com/en-us/isa-extensions/cet-preview) 14 | 15 | Questions or comments can be sent to control-flow-integrity@nsa.gov or [submitted](https://github.com/iadgov/Control-Flow-Integrity/issues/new) to [our GitHub issue tracker](https://github.com/iadgov/Control-Flow-Integrity/issues). 16 | 17 | ## Code 18 | 19 | The [code folder](https://github.com/iadgov/Control-Flow-Integrity/tree/master/code) has examples of software that would leverage the hardware described in the paper. It is hoped that researchers can learn more about the effect and strength of the proposal by reverse engineering and performing static analysis on them. Perhaps demonstrate a way to bypass the mitigation and report via mechanisms described above. The files are: 20 | 21 | * 2 source files that have a buffer overflow of either a return address or a function pointer (i.e. stack-return.c and stack-functionptr.c). 22 | * 2 Linux binaries of the overflow source files instrumented with new landing point opcodes (i.e. stack-return and stack-functionptr). 23 | * 2 instrumented Linux libraries that were linked to the example buffer overflow binaries (ld-linux-x86-64.so.2 and libc.so.6). 24 | * 1 binary of ls, just as a typical Linux utility that has been instrumented with landing point opcodes. 25 | 26 | These simple examples should allow one to explore the impact of the CFI countermeasure in a process address space. The binaries should run on any x86 Linux machine. The opcodes will work as NOP's. The landing point opcodes are as follows: 27 | 28 | * CLP: 0x0f,1f,40,aa 29 | * JLP: 0x0f,1f,40,bb 30 | * RLP: 0x0f,1f,40,cc 31 | 32 | The binaries contain no fine grained label checks. They only have a corresponding Landing Point instruction to any indirect branch as a label, which is coarse grained. If other binaries are desired, we can produce them, if source is provided. 33 | 34 | One can extract the gadgets (as defined on line 271/2 in the paper) from the binaries and attempt to chain them together. Note: RLP gadgets are of no semantic use due to the (imaginary) shadow stack. So gadget chains can only contain CLP and JLP based gadgets. To test validity of a claim, one can use gdb to "run" a gadget chain. First one can manually change the memory as an exploit might do by setting a breakpoint at the appropriate place and performing the overwrite(s). Then continue using single stepping. As a substitute for the HW enforcement, whenever an indirect branch occurs one can visually validate it lands on a landing point. If it reaches the goal (e.g. exec("Your string")) without crashing the application, you win and this form of CFI loses. There is no secret right answer. 35 | 36 | We believe it's not possible or extremely unreliable to bypass the minimal CFI design (line 116 in the paper) with these code samples (and others like them). Unfortunately, this is the best dynamic tool we can offer for now to allow independent validation. 37 | 38 | ## Other Research 39 | 40 | Galois has taken the time and effort to implement a full Linux build of Landhere+ShadowStack concept. This includes instrumented binaries and a VM to create Landhere binaries on one's own. See http://landhere.galois.com/ for more information. Also at the Galois site is a fully instrumented landing point Linux file system that we have used as an exemplar for gadget analysis. 41 | 42 | ## Gadgets 43 | As a convenience, we have extracted all gadgets from the Galois file system and made them available as an [attachment](https://github.com/iadgov/Control-Flow-Integrity/releases/download/v1.0.0/lp-gadgets.tar.gz) to a [release](https://github.com/iadgov/Control-Flow-Integrity/releases/latest). The resulting gadgets are 50 instructions or less and contain 5 or less pre-conditions (e.g. conditional branches). 44 | 45 | A gadget is effectively a trace as it would happen if certain conditions were true. Each gadget is represented as a textual assembly listing. There can be multiple traces from a single landing point. If there's a gadget with an indirect function in the middle, that branch is treated as a stub and the trace falls through to the subsequent instruction, an RLP. Gadgets can have nested function calls/flows. 46 | 47 | The [tarball](https://github.com/iadgov/Control-Flow-Integrity/releases/download/v1.0.0/lp-gadgets.tar.gz) contains two main subdirectories, **exes** and **libs** which reflect the executables and libraries from the Galois set. Each executable is further broken down into raw and filtered. The files in the **raw** folder contain all possible gadgets. The files in the **filtered** folder are de-duped (logical and binary) and are labeled for their chaining purpose (return, link, prestitch, poststitch, dispatch loop, atomic). 48 | 49 | Return is a gadget that "returns", typically it's a real function. It's intended to be used with the dispatch loop but can also be substituted for a call\*. 50 | 51 | Dispatch loop is a quasi gadget that is used to chain multiple return gadgets (i.e. "functions"). 52 | 53 | Link is a forward flowing gadget that does not return (gadget block exit is either a call\* or jmp\*). 54 | 55 | Pre and post stitch gadgets are a sub-genre of link gadgets that can be combined if the stack pointer change is neutral to the shadow stack. 56 | 57 | Atomic is the minimal size gadget for a particular free branch. Namely it is the flow from closest preceding landing point. There may be several Atomic gadgets that flow to the same free branch given any pre-conditions. However, because the maximum size is up to 50 instructions, a gadget might also flow through multiple landing points before encountering a free branch. These nested gadgets are included (but aren’t labeled as atomic) to illustrate side effects that might, or might not, be useful since one is not restricted to branching to the nearest landing point from a free branch. Atomic serves to bound the smallest theoretical flows. 58 | 59 | ## License 60 | See [LICENSE](LICENSE.md). 61 | 62 | ## Disclaimer 63 | See [DISCLAIMER](DISCLAIMER.md). 64 | -------------------------------------------------------------------------------- /code/ld-linux-x86-64.so.2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsacyber/Control-Flow-Integrity/08041f00a5b7056c565a624d6d67304f67a0e859/code/ld-linux-x86-64.so.2 -------------------------------------------------------------------------------- /code/libc.so.6: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsacyber/Control-Flow-Integrity/08041f00a5b7056c565a624d6d67304f67a0e859/code/libc.so.6 -------------------------------------------------------------------------------- /code/ls: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsacyber/Control-Flow-Integrity/08041f00a5b7056c565a624d6d67304f67a0e859/code/ls -------------------------------------------------------------------------------- /code/stack-functionptr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsacyber/Control-Flow-Integrity/08041f00a5b7056c565a624d6d67304f67a0e859/code/stack-functionptr -------------------------------------------------------------------------------- /code/stack-functionptr.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void foo(); 6 | 7 | int main(int argc, char *argv[]) { 8 | void (*fptr)(); 9 | char localbuf[16]; 10 | 11 | if (argc != 3) { 12 | printf("Usage: %s length data\n", argv[0]); 13 | exit (-1); 14 | } 15 | /* corrupt main() stack frame */ 16 | fptr = foo; 17 | memcpy(localbuf, argv[2], atoi(argv[1])); 18 | (*fptr)(); 19 | } 20 | 21 | void foo() { 22 | printf("you are in foo\n"); 23 | } 24 | -------------------------------------------------------------------------------- /code/stack-return: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsacyber/Control-Flow-Integrity/08041f00a5b7056c565a624d6d67304f67a0e859/code/stack-return -------------------------------------------------------------------------------- /code/stack-return.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void foo(); 6 | 7 | int main(int argc, char *argv[]) { 8 | void (*fptr)(); 9 | char localbuf[16]; 10 | 11 | if (argc != 3) { 12 | printf("Usage: %s length data\n", argv[0]); 13 | exit (-1); 14 | } 15 | /* corrupt main() stack frame */ 16 | memcpy(localbuf, argv[2], atoi(argv[1])); 17 | } 18 | 19 | -------------------------------------------------------------------------------- /paper/Hardware Control Flow Integrity for an IT Ecosystem.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nsacyber/Control-Flow-Integrity/08041f00a5b7056c565a624d6d67304f67a0e859/paper/Hardware Control Flow Integrity for an IT Ecosystem.pdf --------------------------------------------------------------------------------