├── README.md
├── img
├── SL2logo.png
└── confirm_flow.png
├── src
├── api_hook.cpp
├── callback_linux.cpp
├── callback_windows.cpp
├── code_coop_linux.cpp
├── code_coop_windows.cpp
├── convention.cpp
├── cppeh.cpp
├── data_symbl.cpp
├── delay_load.cpp
├── fptr.cpp
├── inc.cpp
├── inc.h
├── jit.cpp
├── load_time_dynlnk_linux.cpp
├── load_time_dynlnk_windows.cpp
├── mem.cpp
├── multithreading_linux32.cpp
├── multithreading_linux64.cpp
├── multithreading_windows.cpp
├── ret.cpp
├── run_time_dynlnk.cpp
├── seh.cpp
├── setup.cpp
├── setup.h
├── signal.cpp
├── switch.cpp
├── tail_call.cpp
├── tls_callback.cpp
├── unmatched_pair.cpp
├── veh.cpp
└── vtbl_call.cpp
└── xu19-confirm.pdf
/README.md:
--------------------------------------------------------------------------------
1 |
2 |
3 | # ConFIRM
4 | ConFIRM (Control-Flow Integrity Relevance Metrics) is a new evaluation methodology and microbenchmarking suite for assessing compatibility, applicability, and relevance of *control-flow integrity* (CFI) protections for preserving the intended semantics of software while protecting it from abuse.
5 |
6 | ## Compatibility Metrics
7 | To measure compatibility of CFI mechanisms, we propose a set of metrics that each includes one or more code features from either C/C++ source code or compiled assembly code. We derived this feature set by attempting to apply many CFI solutions to large software products, then manually testing the functionalities of the resulting hardened software for correctness, and finally debugging each broken functionality step-wise at the assembly level to determine what caused the hardened code to fail. Since many failures manifest as subtle
8 | forms of register or memory corruption that only cause the program to crash or malfunction long after the failed operation completes, this debugging constitutes many hundreds of person-hours amassed over several years of development experience involving CFI-protected software.
9 |
10 |
11 | **Table 1: ConFIRM compatibility metrics**
12 |
13 | | Compatibility metric | Real-world software examples |
14 | |----------------------------- |-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
15 | | Function Pointers | 7-Zip, Adobe Reader, Apache, Calculator, Chrome, Dropbox, Firefox, JVM, Notepad, MS Paint, MS PowerPoint, PotPlayer, PowerShell, PuTTY, Skype, TeXstudio, UPX, Visual Studio, Windows Defender, WinSCP |
16 | | Callbacks | 7-Zip, Adobe Reader, Apache, Calculator, Chrome, Dropbox, Firefox, JVM, Notepad, MS Paint, MS PowerPoint, PotPlayer, PowerShell, PuTTY, TeXstudio, Visual Studio, Windows Defender, WinSCP |
17 | | Dynamic Linking | 7-Zip, Adobe Reader, Apache, Calculator, Chrome, Dropbox, Firefox, JVM, Notepad, MS Paint, MS PowerPoint, PotPlayer, PowerShell, PuTTY, Skype, TeXstudio, UPX, Visual Studio, Windows Defender, WinSCP |
18 | | Delay-Loading | Adobe Reader, Calculator, Chrome, Firefox, JVM, MS Paint, MS PowerPoint, PotPlayer, Visual Studio, WinSCP |
19 | | Exporting/Importing Data | 7-Zip, Apache, Calculator, Chrome, Dropbox, Firefox, MS Paint, MS PowerPoint, PowerShell, TeXstudio, UPX, Visual Studio |
20 | | Virtual Functions | 7-Zip, Adobe Reader, Calculator, Chrome, Dropbox, Firefox, JVM, Notepad, MS Paint, MS PowerPoint, PotPlayer, PowerShell, PuTTY, TeXstudio, Visual Studio, Windows Defender, WinSCP |
21 | | CODE-COOP Attack | Programs built on GTK+ or Microsoft COM can pass objects to trusted modules as arguments. |
22 | | Tail Calls | Mainstream compilers provide options for tail call optimization. e.g. /O2 in MSVC, -O2 in GCC, and -O2 in LLVM. |
23 | | Switch-Case Statements | 7-Zip, Adobe Reader, Apache, Calculator, Chrome, Dropbox, Firefox, JVM, MS Paint, MS PowerPoint, PotPlayer, PuTTY, TeXstudio, Visual Studio, WinSCP |
24 | | Returns | Every benign program has returns. |
25 | | Unmatched Call/Return Pairs | Adobe Reader, Apache, Chrome, Firefox, JVM, MS PowerPoint, Visual Studio |
26 | | Exceptions | 7-Zip, Adobe Reader, Apache, Calculator, Chrome, Dropbox, Firefox, JVM, MS Paint, MS PowerPoint, PotPlayer, PowerShell, PuTTY, Skype, TeXstudio, Visual Studio, Windows Defender, WinSCP |
27 | | Calling Conventions | Every program adopts one or more calling convention. |
28 | | Multithreading | 7-Zip, Adobe Reader, Apache, Calculator, Chrome, Dropbox, Firefox, JVM, Notepad, MS Paint, MS PowerPoint, PotPlayer, PowerShell, PuTTY, Skype, TeXstudio, UPX, Visual Studio, Windows Defender, WinSCP |
29 | | TLS Callbacks | Adobe Reader, Chrome, Firefox, MS Paint, TeXstudio, UPX |
30 | | Position-Independent Code | 7-Zip, Adobe Reader, Apache, Calculator, Chrome, Dropbox, Firefox, JVM, Notepad, MS Paint, MS PowerPoint, PotPlayer, PowerShell, PuTTY, Skype, TeXstudio, UPX, Visual Studio, Windows Defender, WinSCP |
31 | | Memory Protection | 7-Zip, Adobe Reader, Apache, Chrome, Dropbox, Firefox, MS PowerPoint, PotPlayer, TeXstudio, Visual Studio, Windows Defender, WinSCP |
32 | | JIT Compiler | Adobe Flash, Chrome, Dropbox, Firefox, JVM, MS PowerPoint, PotPlayer, PowerShell, Skype, Visual Studio, WinSCP |
33 | | self-Unpacking | Programs decompressed by self-extractors (e.g., UPX, NSIS). |
34 | | Windows API Hooking | Microsoft Office family software, including MS Excel, MS PowerPoint, etc. |
35 |
36 | Table 1 presents the resulting list of code features organized into one row for each root cause of failure. Column two additionally lists some widely available, commodity software products where each of these features can be observed in nonmalicious software in the wild. This demonstrates that each feature is representative of real-world software functionalities that must be preserved by CFI implementations in order for their protections to be usable and relevant in contexts that deploy these and similar products.
37 |
38 | ### 1. Indirect Branches
39 | We first discuss compatibility metrics related to the code feature of greatest relevance to most CFI works: indirect branches. Indirect branches are control-flow transfers whose destination addresses are computed at runtime—via pointer arithmetic and/or memory-reads. Such transfers tend to be of high interest to attackers, since computed destinations are more prone to manipulation. CFI defenses therefore guard indirect branches to ensure that they target permissible destinations at runtime. Indirect branches are commonly categorized into three classes: indirect calls, indirect jumps, and returns.
40 |
41 | **Table 2: Source code compiled to indirect call**
42 |
43 | | | Source code | | Assembly code |
44 | |--------------- |------------------------ |--- |--------------- |
45 | | 1 | void foo() { return; } | | |
46 | | 2 | void bar() { return; } | | |
47 | | 3 | void main() { | | |
48 | | 4 | void (*fptr)(); | 1 | ... |
49 | | 5 | int n = input(); | 2 | call _input |
50 | | 6 | if (n) | 3 | test eax, eax |
51 | | 7 | fptr = foo; | 4 | mov edx, offset_foo |
52 | | 8 | else | 5 | mov ecx, offset_bar |
53 | | 9 | fptr = bar; | 6 | cmovnz ecx, edx |
54 | | 10 | fptr(); | 7 | call ecx |
55 | | 11 | } | 8 | ... |
56 |
57 | Table 2 shows a simple example of source code being compiled to an indirect call. The function called at source line 5 depends on user input. This prevents the compiler from generating a direct branch that targets a fixed memory address at compile time. Instead, the compiler generates a registerindirect call (assembly line 7) whose target is computed at runtime. While this is one common example of how indirect branches arise, in practice they are a result of many different programming idioms, discussed below.
58 |
59 | **Function Pointers.** Calls through function pointers typically compile to indirect calls. For example, using gcc with the `-O2` option generates register-indirect calls for function pointers, and MSVC does so by default.
60 |
61 | **Callbacks.** Event-driven programs frequently pass function pointers to external modules or the OS, which the receiving code later dereferences and calls in response to an event. These callback pointers are generally implemented by using function pointers in C, or as method references in C++. Callbacks can pose special problems for CFI, since the call site is not within the module that generated the pointer. If the call site is within a module that cannot easily be modified (e.g., the OS kernel), it must be protected in some other way, such as by sanitizing and securing the pointer before it is passed.
62 |
63 | **Dynamic Linking.** Dynamically linked shared libraries reduce program size and improve locality. But dynamic linking has been a challenge for CFI compatibility because CFG edges that span modules may be unavailable statically.
64 |
65 | In Windows, *dynamically linked libraries* (DLLs) can be loaded into memory at load time or runtime. In load-time dynamic linking, a function call from a module to an exported DLL function is usually compiled to a memory-indirect call targeting an address stored in the module’s *import address table* (IAT). But if this function is called more than once, the compiler first moves the target address to a register, and then generates register-indirect calls to improve execution performance. In run-time dynamic linking, a module calls APIs, such as `LoadLibrary()`, to load the DLL at runtime. When loaded into memory, the module calls the `GetProcAddress()` API to retrieve the address of the exported function, and then calls the exported function using the function pointer returned by `GetProcAddress()`.
66 |
67 | Additionally, MSVC (since version 6.0) provides linker support for delay-loaded DLLs using the `/DELAYLOAD` linker option. These DLLs are not loaded into memory until one of their exported functions is invoked.
68 |
69 | In Linux, a module calls functions exported by a shared library by calling a stub in its *procedure linkage table* (PLT). Each stub contains a memory-indirect jump whose target depends on the writable, lazy-bound *global offset table* (GOT). As in Windows, an application can also load a module at runtime using function `dlopen()`, and retrieve an exported symbol using function `dlsym()`.
70 |
71 | Supporting dynamic and delay-load linkage is further complicated by the fact that shared libraries can also export data pointers within their export tables in both Linux and Windows. CFI solutions that modify export tables must usually treat code and data pointers differently, and must therefore somehow distinguish the two types to avoid data corruptions.
72 |
73 | **Virtual Functions.** Polymorphism is a key feature of OOP languages, such as C++. Virtual functions are used to support runtime polymorphism, and are implemented by C++ compilers using a form of late binding embodied as *virtual tables* (vtables). The tables are populated by code pointers to virtual function bodies. When an object calls a virtual function, it indexes its vtable by a function-specific constant, and flows control to the memory address read from the table. At the assembly level, this manifests as a memory-indirect call. The ubiquity and complexity of this process has made vtable hijacking a favorite exploit strategy of attackers.
74 |
75 | Some CFI and vtable protections address vtable hijacking threats by guarding call sites that read vtables, thereby detecting potential vtable corruption at time-of-use. Others seek to protect vtable integrity directly by guarding writes to them. However, both strategies are potentially susceptible to COOP and CODE-COOP attacks, which replace one vtable with another that is legal but is not the one the original code intended to call. The defense problem is further complicated by the fact that many large classes of software
76 | (e.g., GTK+ and Microsoft COM) rely upon dynamically generated vtables. CFI solutions that write-protect vtables or whose guards check against a static list of permitted vtables are incompatible with such software.
77 |
78 | **Tail Calls.** Modern C/C++ compilers can optimize tail-calls by replacing them with jumps. Row 8 of Table 1 lists relevant compiler options. With these options, callees can return directly to ancestors of their callers in the call graph, rather than to their callers. These mismatched call/return pairs affect precision of some CFG recovery algorithms.
79 |
80 | **Switch-case Statements.** Many C/C++ compilers optimize switch-case statements via a static dispatch table populated with pointers to case-blocks. When the switch is executed, it calculates a dispatch table index, fetches the indexed code pointer, and jumps to the correct case-block. This introduces memory-indirect jumps that refer to code pointers not contained in any vtable, and that do not point to function boundaries. CFI solutions that compare code pointers to a whitelist of function boundaries can therefore cause the switch-case code to malfunction. Solutions that permit unrestricted indirect jumps within each local function risk unsafety, since large functions can contain abusable gadgets.
81 |
82 | **Returns.** Nearly every benign program has returns. Unlike indirect branches whose target addresses are stored in registers or non-writable data sections, return instructions read their destination addresses from the stack. Since stacks are typically writable, this makes return addresses prime targets for malicious corruption.
83 |
84 | On Intel-based CISC architectures, return instructions have one of the shortest encodings (1 byte), complicating the efforts of source-free solutions to replace them in-line with secured equivalent instruction sequences. Additionally, many hardware architectures heavily optimize the behavior of returns (e.g., via speculative execution powered by shadow stacks for call/return matching). Source-aware CFI solutions that replace returns with some other instruction sequence can therefore face stiff performance penalties by losing these optimization advantages.
85 |
86 | **Unmatched call/return Pairs.** Control-flow transfer mechanisms, including exceptions and setjmp/longjmp, can yield flows in which the relation between executed call instructions and executed return instructions is not one-to-one. For example, exception-handling implementations often pop stack frames from multiple calls, followed by a single return to the parent of the popped call chain. Shadow stack defenses that are implemented based on traditional call/return matching may be incompatible with such mechanisms.
87 |
88 | ### 2. Other Metrics
89 | While indirect branches tend to be the primary code feature of interest to CFI attacks and defenses, there are many other code features that can also pose control-flow security problems, or that can become inadvertently corrupted by CFI code transformation algorithms, and that therefore pose compatibility limitations. Some important examples are discussed below.
90 |
91 | **Multithreading.** With the rise of multicore hardware, multithreading has become a centerpiece of software efficiency. Unfortunately, concurrent code execution poses some serious safety problems for many CFI algorithms.
92 |
93 | For example, in order to take advantage of hardware callreturn optimization, most CFI algorithms produce code containing guarded return instructions. The guards check the return address before executing the return. However, on parallelized architectures with flat memory spaces, this is unsafe because any thread can potentially write to any other (concurrently executing) thread’s return address at any
94 | time. This introduces a TOCTOU vulnerability in which an attacker-manipulated thread corrupts a victim thread’s return address after the victim thread’s guard code has checked it but before the guarded return executes. We term this a cross-thread stack-smashing attack. Since nearly all modern architectures combine concurrency, flat memory spaces, and returns, this leaves almost all CFI solutions either inapplicable, unsafe, or unacceptably inefficient for a large percentage of modern production software.
95 |
96 | **Position-Independent Code.** *Position-independent code* (PIC) is designed to be relocatable after it is statically generated, and is a standard practice in the creation of shared libraries. Unfortunately, the mechanisms that implement PIC often prove brittle to code transformations commonly employed for source-free CFI enforcement. For example, PIC often achieves its position independence by dynamically computing its own virtual memory address (e.g., by performing a call to itself and reading the pushed return address from the stack), and then performing pointer arithmetic to locate other code or data at fixed offsets relative to itself. This procedure
97 | assumes that the relative positions of PIC code and data are invariant even if the base address of the PIC block changes.
98 |
99 | However, CFI transforms typically violate this assumption by introducing guard code that changes the sizes of code blocks, and therefore their relative positions. To solve this, PIC-compatible CFI solutions must detect the introspection and pointer arithmetic operations that implement PIC and adjust them to compute corrected pointer values. Since there are typically an unlimited number of ways to perform these computations at both the source and native code levels, CFI detection of these computations is inevitably heuristic, allowing some PIC instantiations to malfunction.
100 |
101 | **Exceptions.** Exception raising and handling is a mainstay of modern software design, but introduces control-flow patterns that can be problematic for CFI policy inference and enforcement. Object-oriented languages, such as C++, boast first-class exception machinery, whereas standard C programs typically realize exceptional control-flows with gotos, longjumps, and signals. In Linux, compilers (e.g., gcc) implement C++ exception handling in a table-driven approach. The compiler statically generates read-only tables that hold
102 | exception-handling information. For instance, gcc produces a `gcc_except_table` comprised of *language-specific data areas* (LSDAs). Each LSDA contains various exception-related information, including pointers to exception handlers.
103 |
104 | In Windows, *structured exception handling* (SEH) extends the standard C language with first-class support for both hardware and software exceptions. SEH uses stack-based exception nodes, wherein exception handlers form a linked list on the stack, and the list head is stored in the *thread information block* (TIB). Whenever an exception occurs, the OS fetches the list head and walks through the SEH list to find a suitable handler for the thrown exception. Without proper protection, these exception handlers on the stack can potentially be overwritten by an attacker. By triggering an exception, the attacker can then redirect the control-flow to arbitrary code. CFI protection against these SEH attacks is complicated by the fact that code outside the vulnerable module (e.g., in the OS and/or system libraries) uses pointer arithmetic to fetch, decode, and call these pointers during exception handling. Thus, suitable protections must typically span multiple modules, and perhaps the OS kernel.
105 |
106 | From Windows XP onward, applications have additionally leveraged *vectored exception handling* (VEH). Unlike SEH, VEH is not stack-based; applications register a global handler chain for VEH exceptions with the OS, and these handlers are invoked by the OS by interrupting the application’s current execution, no matter where the exception occurs within a frame.
107 |
108 | There are at least two features of VEH that are potentially exploitable by attackers. First, to register a vectored exception handler, the application calls an API `AddVecoredExceptionHandler()` that accepts a callback function pointer parameter that points to the handler code. Securing this pointer requires some form of inter-module callback protection.
109 |
110 | Second, the VEH handler-chain data structure is stored in the application’s writable heap memory, making the handler chain data directly susceptible to data corruption attacks. Windows protects the handlers somewhat by obfuscating them using the `EncodePointer()` API. However, `EncodePointer()` does not implement a cryptographically secure function (since doing so would impose high overhead); it typically returns the XOR of the input pointer with a processspecific secret. This secret is not protected against memory disclosure attacks; it is potentially derivable from disclosure of any encoded pointer with value known to the attacker (since XOR is invertible), and it is stored in the *process environment block* (PEB), which is readable by the process and therefore by an attacker armed with an information disclosure exploit. With this secret, the attacker can overwrite the heap with a properly obfuscated malicious pointer, and thereby take control of the application.
111 |
112 | From a compatibility perspective, CFI protections that do not include first-class support for these various exceptionhandling mechanisms often conservatively block unusual control-flows associated with exceptions. This can break important application functionalities, making the protections unusable for large classes of software that use exceptions.
113 |
114 | **Calling Conventions.** CFI guard code typically instruments call and return sites in the target program. In order to preserve the original program’s functionality, this guard code must therefore respect the various calling conventions that might be implemented by calls and returns. Unfortunately, many solutions to this problem make simplifying assumptions about the potential diversity of calling conventions in order to achieve acceptable performance. For example, a CFI solution whose guard code uses `EDX` as a scratch register might suddenly fail when applied to code whose calling convention passes arguments in `EDX`. Adapting the solution to save and restore `EDX` to support the new calling convention can lead to tens of additional instructions per call, including additional memory accesses, and therefore much higher overhead.
115 |
116 | The C standard calling convention (`cdecl`) is caller-pop, pushes arguments right-to-left onto the stack, and returns primitive values in an architecture-specific register (`EAX` on Intel). Each architecture also specifies a set of caller-save and callee-save registers. Caller-popped calling conventions are important for implementing variadic functions, since callees can remain unaware of argument list lengths.
117 |
118 | Callee-popped conventions include `stdcall`, which is the standard convention of the Win32 API, and `fastcall`, which passes the first two arguments via registers rather than the stack to improve execution speed. In OOP languages, every nonstatic member function has a hidden *this pointer* argument that points to the current object. The `thiscall` convention passes the this pointer in a register (`ECX` on Intel).
119 |
120 | Calling conventions on 64-bit architectures implement several refinements of the 32-bit conventions. Linux and Windows pass up to 14 and 4 parameters, respectively, in registers rather than on the stack. To allow callees to optionally spill these parameters, the caller additionally reserves a *red zone* (Linux) or 32-byte *shadow space* (Windows) for callee temporary storage.
121 |
122 | Highly optimized programs also occasionally adopt nonstandard, undocumented calling conventions, or even blur function boundaries entirely (e.g., by performing various forms of function in-lining). For example, some C compilers support language extensions (e.g., MSVC’s `naked` declaration) that yield binary functions with no prologue or epilogue code, and therefore no standard calling convention. Such code can have subtle dependencies on non-register processor elements, such as requiring that certain Intel status flags be preserved across calls. Many CFI solutions break such code by in-lining call site guards that violate these undocumented conventions.
123 |
124 | **TLS Callbacks.** Multithreaded programs require efficient means to manipulate thread-local data without expensive locking. Using *thread local storage* (TLS), applications export one or more TLS callback functions that are invoked by the OS for thread initialization or termination. These functions form a null-terminated table whose base is stored in the PE header. For compiler-based CFI solutions, the TLS callback functions do not usually need extra protection, since both the PE header and the TLS callback table are in unwritable memory. But source-free solutions must ensure that TLS callbacks constitute policy-permitted control-flows at runtime.
125 |
126 | **Memory Protection.** Modern OSes provide APIs for memory page allocation (e.g., `VirtualAlloc` and `mmap`) and permission changes (e.g., `VirtualProtect` and `mprotect`). However, memory pages changed from writable to executable, or to simultaneously writable and executable, can potentially be abused by attackers to bypass DEP defenses and execute attacker-injected code. Many software applications nevertheless rely upon these APIs for legitimate purposes (see Table 1), so conservatively disallowing access to them introduces many compatibility problems. Relevant CFI mechanisms must therefore carefully enforce memory access policies that permit virtual memory management but block code-injection attacks.
127 |
128 | **Runtime Code Generation.** Most CFI algorithms achieve acceptable overheads by performing code generation strictly statically. The statically generated code includes fixed runtime guards that perform small, optimized computations to validate dynamic control-flows. However, this strategy breaks down when target programs generate new code dynamically and attempt to execute it, since the generated code might not include CFI guards. *Runtime code generation* (RCG) is therefore conservatively disallowed by most CFI solutions, with the expectation that RCG is only common in a few, specialized application domains, which can receive specialized protections.
129 |
130 | Unfortunately, our analysis of commodity software products indicates that RCG is becoming more prevalent than is commonly recognized. In general, we encountered RCG compatibility limitations in at least three main forms across a variety of COTS products:
131 |
132 | 1. Although typically associated with web browsers, *just-in-time* (JIT) compilation has become increasingly relevant as an optimization strategy for many languages, including Python, Java, the Microsoft .NET family of languages (e.g., C#), and Ruby. Software containing any component or module written in any JIT-compiled language frequently cannot be protected with CFI.
133 |
134 | 2. Mobile code is increasingly space-optimized for quick ransport across networks. *Self-unpacking executables* are therefore a widespread source of RCG. At runtime, self-unpacking executables first decompress archived data sections to code, and then map the code into writable and executable memory. This entails a dynamic creation of fresh code bytes. Large, component-driven programs sometimes store rarely used components as self-unpacking code that decompresses into memory whenever needed, and is deallocated after use. For example, NSIS installers pack separate modules supporting different install configurations, and unpack them at runtime as-needed for reduced size. Antivirus defenses hence struggle to distinguish benign NSIS installers from malicious ones.
135 |
136 | 3. Component-driven software also often performs a variety of obscure *API hooking* initializations during component loading and clean-up, which are implemented using RCG. As an example, Microsoft Office software dynamically redirects all calls to certain system API functions within its address space to dynamically generated wrapper functions. This allows it to modify the behaviors of late-loaded components without having to recompile them all each time the main application is updated.
137 |
138 | To hook a function *f* within an imported system DLL (e.g., `ntdll.dll`), it first allocates a fresh memory page *f'* and sets it both writable and executable. It next copies the first five code bytes from *f* to *f'*, and writes an instruction at *f'*+5 that jumps to *f*+5. Finally, it changes *f* to be writable and executable, and overwrites the first five code bytes of *f* with an instruction that jumps to *f'*. All subsequent calls to *f* are thereby redirected to *f'*, where new functionality can later be added dynamically before *f'* jumps to the preserved portion of *f*.
139 |
140 | Such hooking introduces many dangers that are difficult for CFI protections to secure without breaking the application or its components. Memory pages that are simultaneously writable and executable are susceptible to codeinjection attacks, as described previously. The RCG that implements the hooks includes unprotected jumps, which must be secured by CFI guard code. However, the guard code itself must be designed to be rewritable by more hooking, including placing instruction boundaries at addresses expected by the hooking code (*f*+5 in the above example). No known CFI algorithm can presently handle these complexities.
141 |
142 | ### 3. Compositional Defense Evaluation
143 | Some CFI solutions compose CFI controls with other defense layers, such as randomization-based defenses. Randomization defenses can be susceptible to other forms of attack, such as memory disclosure attacks. ConFIRM does not test such attacks, since their implementations are usually specific to each defense and not easy to generalize.
144 |
145 | Evaluation of composed defenses should therefore be conducted by composing other attacks with ConFIRM tests. For example, to test a CFI defense composed with stack canaries, one should first simulate attacks that attempt to steal the canary secret, and then modify any stack-smashing ConFIRM tests to use the stolen secret. Incompatibilities of the evaluated defense generally consist of the union of the incompatibilities of the composed defenses.
146 |
147 | ## Implementation
148 | To facilitate easier evaluation of the compatibility considerations outlined in the Compatibility Metrics Section along with their impact on security and performance, we developed the ConFIRM suite of CFI tests. ConFIRM consists of 24 programs written in C++ totalling about 2,300 lines of code. Each test isolates one of the compatibility metrics of the Compatibility Metrics Section (or in some cases a few closely related metrics) by emulating behaviors of COTS software products. Source-aware solutions can be evaluated by applying CFI code transforms to the source codes, whereas source-free solutions can be applied to native code after compilation with a compatible compiler (e.g., gcc, LLVM, or MSVC). Loop iteration counts are configurable, allowing some tests to be used as microbenchmarks. The tests are described as follows:
149 |
150 | **fptr.** This tests whether function calls through function pointers are suitably guarded or can be hijacked. Overhead is measured by calling a function through a function pointer in an intensive loop.
151 |
152 | **callback.** As discussed in the Compatibility Metrics Section, call sites of callback functions can be either guarded by a CFI mechanism directly, or located in immutable kernel modules that require some form of indirect control-flow protections. We therefore test whether a CFI mechanism can secure callback function calls in both cases. Overhead is measured by calling a function that takes a callback pointer parameter in an intensive loop.
153 |
154 | **load_time_dynlnk.** Load-time dynamic linking tests determine whether function calls to symbols that are exported by a dynamically linked library are suitably protected. Overhead is measured by calling a function that is exported by a dynamically linked library in an intensive loop.
155 |
156 | **run_time_dynlnk.** This tests whether a CFI mechanism supports runtime dynamic linking, whether it supports retrieving symbols from the dynamically linked library at runtime, and whether it guards function calls to the retrieved symbol. Overhead is measured by loading a dynamically linked library at runtime, calling a function exported by the library, and unloading the library in an intensive loop.
157 |
158 | **delay_load** *(Windows only)* **.** CFI compatibility with delayloaded DLLs is tested, including whether function calls to symbols that are exported by the delay-loaded DLLs are protected. Overhead is measured by calling a function that is exported by a delay-loaded DLL in an intensive loop.
159 |
160 | **data_symbl.** Data and function symbol imports and exports are tested, to determine whether any controls preserve their accessibility and operation.
161 |
162 | **vtbl_call.** Virtual function calls are exercised, whose call sites can be directly instrumented. Overhead is measured by calling virtual functions in an intensive loop.
163 |
164 | **code_coop.** This tests whether a CFI mechanism is robust against CODE-COOP attacks. For the object-oriented interfaces required to launch a CODE-COOP attack, we choose Microsoft COM API functions in Windows, and gtkmm API calls that are part of the C++ interface for GTK+ in Linux.
165 |
166 | **tail_call.** Tail call optimizations of indirect jumps are tested. Overhead is measured by tail-calling a function in a loop.
167 |
168 | **switch.** Indirect jumps associated with switch-case control-flow structures are tested, including their supporting data structures. Overhead is measured by executing a switch-case statement in an intensive loop.
169 |
170 | **ret.** Validation of return addresses (e.g., dynamically via shadow stack implementation, or statically by labeling call sites and callees with equivalence classes) is tested. Overhead is measured by calling a function that does nothing but return in an intensive loop.
171 |
172 | **unmatched_pair.** Unmatched call/return pairs resulting from exceptions and setjmp/longjmp are tested.
173 |
174 | **signal.** This test uses signal-handling in C to implement error-handling and exceptional control-flows.
175 |
176 | **cppeh.** C++ exception handling structures and control-flows are exercised.
177 |
178 | **seh** *(Windows only)* **.** SEH-style exception handling is tested for both hardware and software exceptions. This test also checks whether the CFI mechanism protects the exception handlers stored on the stack.
179 |
180 | **veh** *(Windows only)* **.** VEH-style exception handling is tested for both hardware and software exceptions. This test also checks whether the CFI mechanism protects callback function pointers passed to `AddVecoredExceptionHandler()`.
181 |
182 | **convention.** Several different calling conventions are tested, including conventions widely used in C/C++ languages on 32-bit and 64-bit x86 processors.
183 |
184 | **multithreading.** Safety of concurrent thread executions is tested. Specifically, one thread simulates a memory corruption exploit that attempts to smash another thread’s stack and break out of the CFI-enforced sandbox.
185 |
186 | **tls_callback** *(Windows source-free only)* **.** This tests whether static TLS callback table corruption is detected and blocked by the protection mechanism.
187 |
188 | **pic.** Semantic preservation of position-independent code is tested.
189 |
190 | **mem.** This test performs memory management API calls for legitimate and malicious purposes, and tests whether security controls permit the former but block the latter.
191 |
192 | **jit.** This test generates JIT code by first allocating writable memory pages, writing JIT code into those pages, making the pages executable, and then running the JIT code. To emulate behaviors of real-world JIT compilers, the JIT code performs different types of control-flow transfers, including calling back to the code of JIT compiler and calling functions located in other modules.
193 |
194 | **api_hook** *(Windows only)* **.** Dynamic API hooking is performed in the style described in the Compatibility Metrics Section.
195 |
196 | **unpacking** *(source-free only)* **.** Self-unpacking executable code is implemented using RCG.
197 |
--------------------------------------------------------------------------------
/img/SL2logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareLanguagesSecurityLab/ConFIRM/601de444c5e665812778b61fc0fec5c91dbbedbc/img/SL2logo.png
--------------------------------------------------------------------------------
/img/confirm_flow.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareLanguagesSecurityLab/ConFIRM/601de444c5e665812778b61fc0fec5c91dbbedbc/img/confirm_flow.png
--------------------------------------------------------------------------------
/src/api_hook.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | // This micro benchmark emulates a specific Windows API hooking behavior observed in
32 | // various component-driven software, including Microsoft Office software. Please
33 | // see the ConFIRM paper for detailed explanation. This benchmark redirects function
34 | // NtClose to a wrapper function, to show this API hooking behavior.
35 |
36 | #pragma warning( disable : 4005)
37 | #include "setup.h"
38 | #include
39 |
40 | // Make realNtClose a global variable as it's delared in AppvIsvSubsystems32.dll
41 | static FARPROC realNtClose;
42 | // A global randomized integer
43 | static int r;
44 |
45 | void cpyInt(DWORD startAddr, DWORD dwSize);
46 | void hookedNtClose();
47 |
48 | int main(void) {
49 | HANDLE ghSemaphore;
50 | HMODULE hNtdll;
51 | SYSTEM_INFO info;
52 | DWORD dwPageSize;
53 | DWORD oldProtect;
54 | BOOL retVP;
55 | BOOL retCH;
56 | NTSTATUS status;
57 | NTSTATUS(*pNtClose) (HANDLE);
58 |
59 | // Get page size of current system.
60 | GetSystemInfo(&info);
61 | dwPageSize = info.dwPageSize;
62 |
63 | // ntdll.dll should be loaded.
64 | hNtdll = GetModuleHandle(L"ntdll.dll");
65 | if (!hNtdll)
66 | {
67 | printf("ntdll is not loaded");
68 | exit(1);
69 | }
70 |
71 | // Get function pointer to ntdll::NtClose.
72 | // pNtClose -> mov eax, 0c
73 | // pNtClose+5 -> xor ecx, ecx
74 | // ...
75 | pNtClose = (NTSTATUS(*)(HANDLE))GetProcAddress(hNtdll, "NtClose");
76 | if (!pNtClose)
77 | {
78 | printf("GetProcAddress() failed requesting function NtClose()");
79 | exit(1);
80 | }
81 |
82 | // Allocate memory for realNtClose.
83 | realNtClose = (FARPROC)VirtualAlloc(
84 | NULL,
85 | dwPageSize,
86 | MEM_COMMIT | MEM_RESERVE,
87 | PAGE_EXECUTE_READWRITE
88 | );
89 | if (!realNtClose)
90 | {
91 | printf("VirtualAlloc() failed allocating for realNtClose()");
92 | exit(1);
93 | }
94 |
95 | // Fill the allocated page by 0xCC (INT)
96 | cpyInt((DWORD)realNtClose, dwPageSize);
97 |
98 | // Write to realNtClose.
99 | // After writing:
100 | // realNtClose -> mov eax, 0c (same to the first 5 bytes of NtClose)
101 | // realNtClose+5 -> jmp pNtClose+5 (xor ecx, ecx)
102 | // INT (should never executed)
103 | __asm {
104 | // Copy the first 4 bytes from NtClose (in ntdll) to realNtClose.
105 | mov esi, pNtClose
106 | mov edi, realNtClose
107 | mov eax, dword ptr[esi]
108 | mov dword ptr[edi], eax
109 |
110 | // Copy the fifth byte
111 | add esi, 4
112 | add edi, 4
113 | mov al, byte ptr[esi]
114 | mov byte ptr[edi], al
115 |
116 | // Write a jmp instruction at offset 5 of realNtClose.
117 | inc edi
118 | mov byte ptr[edi], 0xe9
119 | mov eax, edi
120 | add eax, 5
121 | inc edi
122 | inc esi
123 | sub esi, eax
124 | mov dword ptr[edi], esi
125 | }
126 |
127 | // Make the first 5 bytes of ntdll::NtClose R+W+X.
128 | retVP = VirtualProtect(pNtClose, 5, PAGE_EXECUTE_READWRITE, &oldProtect);
129 | if (!retVP)
130 | {
131 | printf("VirtualProtect() failed on ntdll::NtClose -> R+W+X");
132 | exit(1);
133 | }
134 |
135 | // Write the fst 5 bytes of ntdll::NtClose to force it jump to hookedNtClose.
136 | // After writing:
137 | // pNtClose -> jmp hookedNtClose
138 | // pNtClose+5 -> xor ecx, ecx
139 | // ...
140 | __asm {
141 | mov edi, pNtClose
142 | mov byte ptr[edi], 0xe9
143 | mov ecx, hookedNtClose
144 | mov eax, edi
145 | inc edi
146 | add eax, 5
147 | sub ecx, eax
148 | mov dword ptr[edi], ecx
149 | }
150 |
151 | // Make the first 5 bytes of ntdll::NtClose E+WriteCopy.
152 | retVP = VirtualProtect(pNtClose, 5, PAGE_EXECUTE_WRITECOPY, &oldProtect);
153 | if (!retVP)
154 | {
155 | printf("VirtualProtect() failed on ntdll::NtClose -> E+WriteCopy");
156 | exit(1);
157 | }
158 |
159 | // Create a semaphore and then close the semaphore handle by calling NtClose().
160 | ghSemaphore = CreateSemaphore(
161 | NULL,
162 | 1,
163 | 1,
164 | NULL);
165 |
166 | // Initialize seed
167 | srand((unsigned int)time(NULL));
168 | // Close sematphore handle
169 | do
170 | {
171 | r = rand();
172 | printf("Trying to close semaphore handle...\n");
173 | status = pNtClose(ghSemaphore);
174 | } while (status != STATUS_SUCCESS);
175 |
176 | printf("Semaphore handle closed.\n");
177 |
178 | return 0;
179 | }
180 |
181 | void cpyInt(DWORD startAddr, DWORD dwSize)
182 | {
183 | __asm {
184 | mov eax, 0xCCCCCCCC
185 | mov edi, startAddr
186 | mov ecx, dwSize
187 | shr ecx, 2
188 | rep stos dword ptr[edi] // this is semanticly equivelent to "rep stosd"
189 | }
190 | }
191 |
192 | // If randomized int r is even -> return STATUS_UNSUCCESSFUL
193 | // r is odd -> jump to realNtClose
194 | __declspec(naked)
195 | void hookedNtClose()
196 | {
197 | if (r % 2 == 0)
198 | {
199 | __asm {
200 | mov eax, 0xC0000001
201 | ret
202 | }
203 | }
204 |
205 | __asm {
206 | jmp realNtClose
207 | }
208 |
209 | printf("Program should not reach here --- impossible!");
210 |
211 | __asm {
212 | ret
213 | }
214 | }
215 |
--------------------------------------------------------------------------------
/src/callback_linux.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | static int count_0 = 0, count_1 = 0, count_2 = 0;
34 | NANOSECOND start_time;
35 | NANOSECOND end_time;
36 | NANOSECOND total_time;
37 |
38 | // Define three callback functions
39 | void *theadProc0(void *);
40 | void *theadProc1(void *);
41 | void *theadProc2(void *);
42 |
43 | int main()
44 | {
45 | pthread_t threads[3];
46 |
47 | // Record starting time
48 | start_time = get_wall_time();
49 |
50 | // int pthread_create(
51 | // pthread_t *thread,
52 | // const pthread_attr_t *attr,
53 | // void *(*start_routine) (void *),
54 | // void *arg);
55 | // pthread_create() (signature above) takes a callback pointer (start_routine)
56 | // that points to a application-defined function to be executed by the new
57 | // created thread.
58 |
59 | // Create threads in an intensive loop.
60 | for (long long int i = 0; i < MAX_LOOP * CALTS; i++)
61 | {
62 | pthread_create(&threads[0], NULL, &theadProc0, NULL);
63 | pthread_create(&threads[1], NULL, &theadProc1, NULL);
64 | pthread_create(&threads[2], NULL, &theadProc2, NULL);
65 | }
66 |
67 | // Record ending time
68 | end_time = get_wall_time();
69 | total_time = end_time - start_time;
70 |
71 | // Print time elapsed in the loop.
72 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
73 |
74 | // Print counts so that a compiler doesn't optimize too much.
75 | printf("%d, %d, %d\n", count_0, count_1, count_2);
76 |
77 | pthread_exit(NULL);
78 | }
79 |
80 | void *theadProc0(void *)
81 | {
82 | count_0++;
83 | pthread_exit(NULL);
84 | }
85 |
86 | void *theadProc1(void *)
87 | {
88 | count_1++;
89 | pthread_exit(NULL);
90 | }
91 |
92 | void *theadProc2(void *)
93 | {
94 | count_2++;
95 | pthread_exit(NULL);
96 | }
97 |
--------------------------------------------------------------------------------
/src/callback_windows.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | static int count_1 = 0, count_2 = 0, count_3 = 0;
34 | NANOSECOND start_time;
35 | NANOSECOND end_time;
36 | NANOSECOND total_time;
37 |
38 | // Define three callback functions
39 | DWORD WINAPI theadProc1(LPVOID lpParam);
40 | DWORD WINAPI theadProc2(LPVOID lpParam);
41 | DWORD WINAPI theadProc3(LPVOID lpParam);
42 |
43 | int main()
44 | {
45 | HANDLE h1 = 0;
46 | HANDLE h2 = 0;
47 | HANDLE h3 = 0;
48 | HANDLE handles[3];
49 |
50 | // Record starting time
51 | start_time = get_wall_time();
52 |
53 | // HANDLE CreateThread(
54 | // LPSECURITY_ATTRIBUTES lpThreadAttributes,
55 | // SIZE_T dwStackSize,
56 | // LPTHREAD_START_ROUTINE lpStartAddress,
57 | // __drv_aliasesMem LPVOID lpParameter,
58 | // DWORD dwCreationFlags,
59 | // LPDWORD lpThreadId
60 | // );
61 | // The CreateThread() API takes a callback pointer (lpStartAddress) that points
62 | // to a napplication-defined function to be executed by the new created thread.
63 |
64 | // Create threads and wait for them to terminate in an intensive loop.
65 | for (long long int i = 0; i < MAX_LOOP * CALTS; i++)
66 | {
67 | h1 = CreateThread(NULL, 0, theadProc1, NULL, 0, NULL);
68 | h2 = CreateThread(NULL, 0, theadProc2, NULL, 0, NULL);
69 | h3 = CreateThread(NULL, 0, theadProc3, NULL, 0, NULL);
70 |
71 | // Wait for the treads to terminate and close handles.
72 | handles[0] = h1;
73 | handles[1] = h2;
74 | handles[2] = h3;
75 | WaitForMultipleObjects(3, handles, TRUE, INFINITE);
76 | CloseHandle(h1);
77 | CloseHandle(h2);
78 | CloseHandle(h3);
79 | }
80 |
81 | // Record ending time
82 | end_time = get_wall_time();
83 | total_time = end_time - start_time;
84 |
85 | // Print time elapsed in the loop.
86 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
87 |
88 | // Print counts so that a compiler doesn't optimize too much.
89 | printf("%d, %d, %d", count_1, count_2, count_3);
90 |
91 | return 0;
92 | }
93 |
94 | DWORD WINAPI theadProc1(LPVOID lpParam)
95 | {
96 | count_1++;
97 | return NULL;
98 | }
99 |
100 | DWORD WINAPI theadProc2(LPVOID lpParam)
101 | {
102 | count_2++;
103 | return NULL;
104 | }
105 |
106 | DWORD WINAPI theadProc3(LPVOID lpParam)
107 | {
108 | count_3++;
109 | return NULL;
110 | }
111 |
--------------------------------------------------------------------------------
/src/code_coop_linux.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | /* For a detailed explanation of CODE-COOP attack, see the following publication:
32 |
33 | Wenhao Wang and Xiaoyang Xu and Kevin W. Hamlen.
34 | "Object Flow Integrity." In Proceedings of the 24th ACM Conference on Computer
35 | and Communications Security (CCS). */
36 |
37 | #include
38 | #include
39 | #include
40 | #include
41 |
42 | // Define a Gtk Window class with one button.
43 | class CODECOOP : public Gtk::Window
44 | {
45 | public:
46 | CODECOOP();
47 | virtual ~CODECOOP();
48 | protected:
49 | // Signal handlers:
50 | void on_button_clicked();
51 | // Member widgets:
52 | Gtk::Button m_button;
53 | };
54 |
55 | CODECOOP::CODECOOP()
56 | : m_button("This is a test for CODE-COOP attack")
57 | {
58 | set_border_width(10);
59 | m_button.signal_clicked().connect(sigc::mem_fun(*this, &CODECOOP::on_button_clicked));
60 | add(m_button);
61 | m_button.show();
62 | }
63 |
64 | CODECOOP::~CODECOOP()
65 | {
66 | }
67 |
68 | void CODECOOP::on_button_clicked()
69 | {
70 | std::cout << "This is a test for CODE-COOP attack" << std::endl;
71 | }
72 |
73 | int main (int argc, char *argv[])
74 | {
75 | auto app = Gtk::Application::create(argc, argv, "");
76 |
77 | CODECOOP codecoop;
78 |
79 | // function call that leads to buffer overflow
80 | char buffer[1];
81 | printf("Any input can lead to buffer overwrite: \n");
82 | scanf("%s", buffer);
83 |
84 | // Shows the window and returns when it is closed.
85 | // In run(), it calls member function of codecoop. The codecoop pointer is stored
86 | // on the stack so that the above buffer overwrite vulnerability can rewrite this
87 | // pointer with one that points to a counterfeit object. Although CFI solutions
88 | // can guarantee that app->run flows to a valid target, the function call to
89 | // other member function of codecoop in trusted module can therefore escape the
90 | // CFI sandbox.
91 | return app->run(codecoop);
92 | }
93 |
--------------------------------------------------------------------------------
/src/code_coop_windows.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | /* For a detailed explanation of CODE-COOP attack, see the following publication:
32 |
33 | Wenhao Wang and Xiaoyang Xu and Kevin W. Hamlen.
34 | "Object Flow Integrity." In Proceedings of the 24th ACM Conference on Computer
35 | and Communications Security (CCS). */
36 |
37 | #include "setup.h"
38 | #include "wininet.h"
39 | #include "winnls.h"
40 | #include "shobjidl.h"
41 | #include "objbase.h"
42 | #include "objidl.h"
43 | #include "shlguid.h"
44 | #include "shlobj.h"
45 |
46 | #pragma warning ( disable : 4789 )
47 |
48 | int main()
49 | {
50 | HRESULT hres;
51 | IShellLink* pad;
52 |
53 | CoInitialize(NULL);
54 |
55 | // CoCreateInstance() obtains an object reference (pad) of ActiveDesktop. And
56 | // later QueryInterface() obtains a new interface (puk) to ActiveDesktop.
57 | hres = CoCreateInstance(
58 | CLSID_ActiveDesktop,
59 | NULL,
60 | CLSCTX_INPROC_SERVER,
61 | IID_IActiveDesktop,
62 | (LPVOID*)&pad
63 | );
64 |
65 | if (SUCCEEDED(hres))
66 | {
67 | // Code containing a data corruption vulnerability
68 | char buffer[1];
69 | printf("Any input can lead to buffer overwrite: \n");
70 | scanf("%s", buffer);
71 |
72 | // CFI solutions guarantee that the following function call targets a valid
73 | // QueryInterface(). Unfortunately, every implementation of QueryInterface()
74 | // calls other virtual functions (e.g. AddRef) by default. With the above
75 | // data corruption vulnerability, an attacker can tailer counterfeit object
76 | // and then redirect control flow to arbitrary code.
77 | IPersistFile* puk;
78 | hres = pad-> QueryInterface(IID_IUnknown, (LPVOID*)&puk);
79 | if (SUCCEEDED(hres))
80 | {
81 | printf("QueryInterface succeed.\n");
82 | }
83 | else
84 | {
85 | printf("QueryInterface failed.\n");
86 | }
87 | }
88 | else
89 | {
90 | printf("CoCreateInstance failed.\n");
91 | }
92 |
93 | CoUninitialize();
94 |
95 | return 0;
96 | }
97 |
--------------------------------------------------------------------------------
/src/convention.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | // Caller-pop, variadic function.
34 | int CDECL variadicSum(int count, ...);
35 |
36 | // Callee-pop function.
37 | int STDCALL listSum(int count, const int * list);
38 |
39 | // Callee-pop FASTCALL function.
40 | // Caller tries to pass first two arguments using registers.
41 | int FASTCALL fastSum(int count, const int * list);
42 |
43 | // Callee-pop THISCALL functions.
44 | // "this" pointer is passed in ecx. Other arguments are pushed onto the stack.
45 | class CMath
46 | {
47 | private:
48 | int * list;
49 | int count;
50 | public:
51 | int THISCALL calculateSum();
52 | int THISCALL calculateAverage();
53 | void THISCALL setList(const int list_count, const int * int_list);
54 | };
55 |
56 | // 64-bit conventions allow up to 14 and 4 parameters passing in registers,
57 | // on Linux and Windows respectively. They both use caller-pop conventions by default.
58 | // int and float arguments are passed using different registers.
59 | int IntSum(int count, ...);
60 | double DoubleSum(int count, ...);
61 |
62 | int main()
63 | {
64 | // Call a CDECL function.
65 | int variadicSum_ans = 0;
66 | variadicSum_ans = variadicSum(5, 1, 2, 3, 4, 5);
67 | if (variadicSum_ans == 15)
68 | {
69 | printf("CDECL passed\n");
70 | }
71 | else
72 | {
73 | printf("CDECL failed!\n");
74 | return -1;
75 | }
76 |
77 | // Call a STDCALL function.
78 | int listSum_ans = 0;
79 | int int_list1[5] = { 1, 3, 5, 7, 9 };
80 | listSum_ans = listSum(sizeof(int_list1) / sizeof(int), int_list1);
81 | if (listSum_ans == 25)
82 | {
83 | printf("STDCALL passed\n");
84 | }
85 | else
86 | {
87 | printf("STDCALL failed!\n");
88 | return -1;
89 | }
90 |
91 | // Call a FASTCALL function
92 | int fastSum_ans = 0;
93 | int int_list2[4] = { 5, 3, 5, 1 };
94 | fastSum_ans = fastSum(sizeof(int_list2) / sizeof(int), int_list2);
95 | if (fastSum_ans == 14)
96 | {
97 | printf("FASTCALL passed\n");
98 | }
99 | else
100 | {
101 | printf("FASTCALL failed!\n");
102 | return -1;
103 | }
104 |
105 | // Call THISCALL functions
106 | CMath * myCMath = new CMath;
107 | int int_list3[6] = { 2, 1, 6, 3, 8, 9 };
108 |
109 | myCMath->setList(sizeof(int_list3) / sizeof(int), int_list3);
110 | int sum = myCMath->calculateSum();
111 | int avg = myCMath->calculateAverage();
112 | if ((sum == 29) && (avg == 4))
113 | {
114 | printf("THISCALL passed\n");
115 | }
116 | else
117 | {
118 | printf("THISCALL failed!\n");
119 | return -1;
120 | }
121 |
122 | // Tests for 64-bit calling conventions.
123 | int intSum_ans = 0;
124 | intSum_ans = IntSum(16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
125 |
126 | double doubleSum_ans = 0.0;
127 | doubleSum_ans = DoubleSum(16, 1.1, 2.2, 3.3, 4.4, 5.5, 6.6, 7.7, 8.8, 9.9, 10.10, 11.11, 12.12, 13.13, 14.14, 15.15, 16.16);
128 |
129 | if ((intSum_ans == 136) && (doubleSum_ans - 141.41 <= 0.000000000001))
130 | {
131 | printf("64bit conventions passed\n");
132 | }
133 | else
134 | {
135 | printf("64bit conventions failed!\n");
136 | return -1;
137 | }
138 |
139 | printf("All conventions passed\n");
140 | return 0;
141 | }
142 |
143 | int THISCALL CMath::calculateAverage()
144 | {
145 | int sum = 0;
146 | int avg = 0;
147 |
148 | sum = this->calculateSum();
149 | avg = sum / this->count;
150 | return avg;
151 | }
152 |
153 | int THISCALL CMath::calculateSum()
154 | {
155 | int sum = 0;
156 | for (int i = 0; i < this->count; i++)
157 | sum += (this->list)[i];
158 |
159 | return sum;
160 | }
161 |
162 | void THISCALL CMath::setList(const int list_count, const int * int_list)
163 | {
164 | this->list = new int[list_count];
165 | this->count = list_count;
166 |
167 | for (int i = 0; i < list_count; i++)
168 | (this->list)[i] = int_list[i];
169 | }
170 |
171 | int FASTCALL fastSum(int count, const int * list)
172 | {
173 | int sum = 0;
174 | int i = 0;
175 |
176 | for (int i = 0; i < count; i++)
177 | sum += list[i];
178 |
179 | return sum;
180 | }
181 |
182 | int STDCALL listSum(int count, const int * list)
183 | {
184 | int sum = 0;
185 | int i = 0;
186 |
187 | for (int i = 0; i < count; i++)
188 | sum += list[i];
189 |
190 | return sum;
191 | }
192 |
193 | int CDECL variadicSum(int count, ...)
194 | {
195 | va_list ap;
196 | int sum = 0;
197 |
198 | va_start(ap, count);
199 | for (int i = 0; i < count; i++)
200 | sum += va_arg(ap, int);
201 | va_end(ap);
202 |
203 | return sum;
204 | }
205 |
206 | int IntSum(int count, ...)
207 | {
208 | va_list ap;
209 | int sum = 0;
210 |
211 | va_start(ap, count);
212 | for (int i = 0; i < count; i++)
213 | sum += va_arg(ap, int);
214 | va_end(ap);
215 |
216 | return sum;
217 | }
218 |
219 | double DoubleSum(int count, ...)
220 | {
221 | va_list ap;
222 | double sum = 0.0;
223 | double next = 0.0;
224 |
225 | va_start(ap, count);
226 | for (int i = 0; i < count; i++)
227 | sum += va_arg(ap, double);
228 | va_end(ap);
229 |
230 | return sum;
231 | }
232 |
--------------------------------------------------------------------------------
/src/cppeh.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | void throwInt();
34 | void throwBool();
35 | static int int_catch_count = 0;
36 | static int bool_catch_count = 0;
37 |
38 | int main()
39 | {
40 | int r;
41 |
42 | // Initialize random seed
43 | srand((unsigned int)time(NULL));
44 |
45 | // Throw and catch C++ exceptions in an intensive loop, to see if a CFI solution
46 | // being tested provides semantic transparency.
47 | for (long long int i = 0; i < MAX_LOOP * CPEHTS; ++i)
48 | {
49 | r = rand();
50 | try
51 | {
52 | if (r % 2 == 0)
53 | throwInt();
54 | else
55 | throwBool();
56 |
57 | }
58 | catch (int e)
59 | {
60 | int_catch_count++;
61 | }
62 | catch (bool e)
63 | {
64 | bool_catch_count++;
65 | }
66 | }
67 |
68 | // Print results
69 | printf("int_catch_count is %d\n", int_catch_count);
70 | printf("bool_catch_count is %d\n", bool_catch_count);
71 | printf("C++ exception test passed.");
72 |
73 | return 0;
74 | }
75 |
76 | void throwInt()
77 | {
78 | try
79 | {
80 | throw 7;
81 | }
82 | catch (bool e)
83 | {
84 | bool_catch_count++;
85 | }
86 | }
87 |
88 | void throwBool()
89 | {
90 | try
91 | {
92 | throw true;
93 | }
94 | catch (int e)
95 | {
96 | int_catch_count++;
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/src/data_symbl.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 | #include "inc.h"
33 |
34 | int main()
35 | {
36 | int imp_null = -1;
37 | DWORD p_exp_null = NULL;
38 |
39 |
40 | imp_null = (int) exp_null;
41 | // After data movement, if imp_null is not NULL, the CFI work being tested must
42 | // have done something wrong.
43 | if (imp_null != 0)
44 | {
45 | printf("imp_null should be NULL (current value: %d).\n", imp_null);
46 | exit(1);
47 | }
48 |
49 | // Check whether an exported symbol can be read correctly via pointer.
50 | p_exp_null = &exp_null;
51 | if (*p_exp_null != 0)
52 | {
53 | printf("*p_exp_null should be NULL (current value: %d).\n", *p_exp_null);
54 | exit(1);
55 | }
56 |
57 | // Check whether the exported symbol can still be read correctly after some weird
58 | // pointer arithmetic.
59 | p_exp_null ++;
60 | p_exp_null += (DWORD)(imp_null * 1024);
61 | p_exp_null --;
62 | if (*p_exp_null != 0)
63 | {
64 | printf("*p_exp_null should be NULL (current value: %d).\n", *p_exp_null);
65 | exit(1);
66 | }
67 |
68 | printf("All tests passed.\n");
69 | return 0;
70 | }
71 |
--------------------------------------------------------------------------------
/src/delay_load.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | // This microbenchmark should be compiled by Microsoft Visual Studio with additional
32 | // linker option /DELAYLOAD:"user32.dll", so that user32.dll would be delay loaded.
33 |
34 | #include "setup.h"
35 |
36 | NANOSECOND start_time;
37 | NANOSECOND end_time;
38 | NANOSECOND total_time;
39 |
40 | int main()
41 | {
42 | HWND hWindow = NULL;
43 |
44 | // Record starting time
45 | start_time = get_wall_time();
46 |
47 | for (long long int i = 0; i < MAX_LOOP * DLTS; ++i)
48 | {
49 | // API GetForegroundWindow() is exported user32.dll. By delay-loading
50 | // user32.dll, it is not loaded into memory until GetForegroundWindow() is
51 | // being called.
52 | hWindow = GetForegroundWindow();
53 | if (!hWindow)
54 | {
55 | printf("GetActiveWindow() failed.\n");
56 | exit(1);
57 | }
58 | hWindow = NULL;
59 | }
60 |
61 | // Record ending time
62 | end_time = get_wall_time();
63 | total_time = end_time - start_time;
64 |
65 | // Print time elapsed in the loop.
66 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
67 | return 0;
68 | }
69 |
--------------------------------------------------------------------------------
/src/fptr.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | static int count_even = 0;
34 | static int count_odd = 0;
35 | NANOSECOND start_time;
36 | NANOSECOND end_time;
37 | NANOSECOND total_time;
38 |
39 | // Declare two functions with same signature.
40 | void printEven(int n);
41 | void printOdd(int n);
42 |
43 | int main()
44 | {
45 | // Declare a function pointer. Each call via this pointer would be a indirect call.
46 | // It can be either a register-indirect call or a memory-indirect call based on
47 | // different compiler options.
48 | void(*fptr) (int n);
49 |
50 | // Initialize random seed
51 | srand((unsigned int)time(NULL));
52 | // Record starting time
53 | start_time = get_wall_time();
54 |
55 | // call functions via a function pointer in an intensive loop.
56 | for (long long int i = 0; i < MAX_LOOP * FPTRTS; i++)
57 | {
58 | // Depending on parity of a randomized number, fptr(r) calls different functions.
59 | int r = rand();
60 | if (r % 2 == 0)
61 | fptr = printEven;
62 | else
63 | fptr = printOdd;
64 | fptr(r);
65 | }
66 |
67 | // Record ending time, and calculate running time elapsed in the loop.
68 | end_time = get_wall_time();
69 | total_time = end_time - start_time;
70 |
71 | // Print time elapsed in the loop.
72 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
73 |
74 | // Print counts so that a compiler doesn't optimize too much.
75 | printf("%d odd numbers\n", count_odd);
76 | printf("%d even numbers\n", count_even);
77 |
78 | return 0;
79 | }
80 |
81 | void printEven(int n)
82 | {
83 | count_even++;
84 | }
85 | void printOdd(int n)
86 | {
87 | count_odd++;
88 | }
89 |
--------------------------------------------------------------------------------
/src/inc.cpp:
--------------------------------------------------------------------------------
1 | #include
2 | #include "inc.h"
3 |
4 | #ifdef _WIN32
5 | #include
6 | #define EXPORTING_DLL
7 |
8 | BOOL APIENTRY DllMain(
9 | HANDLE hModule, // Handle to DLL module
10 | DWORD ul_reason_for_call,
11 | LPVOID lpReserved) // Reserved
12 | {
13 | switch (ul_reason_for_call)
14 | {
15 | case DLL_PROCESS_ATTACH:
16 | // A process is loading the DLL.
17 | break;
18 |
19 | case DLL_THREAD_ATTACH:
20 | // A process is creating a new thread.
21 | break;
22 |
23 | case DLL_THREAD_DETACH:
24 | // A thread exits normally.
25 | break;
26 |
27 | case DLL_PROCESS_DETACH:
28 | // A process unloads the DLL.
29 | break;
30 | }
31 | return TRUE;
32 | }
33 |
34 | #elif __linux__
35 | #include
36 | #include "helper.h"
37 | #endif
38 |
39 | void increment(int &i)
40 | {
41 | if (i < INT_MAX)
42 | {
43 | i++;
44 | }
45 | return;
46 | }
47 |
48 | int exp_null = (int) NULL;
49 |
--------------------------------------------------------------------------------
/src/inc.h:
--------------------------------------------------------------------------------
1 | #pragma once
2 |
3 | #ifdef _WIN32
4 | #ifdef EXPORTING_DLL
5 | extern "C" __declspec(dllexport) void increment(int &i);
6 | extern "C" __declspec(dllexport) int exp_null;
7 | #else
8 | extern "C" __declspec(dllimport) void increment(int &i);
9 | extern "C" __declspec(dllimport) int exp_null;
10 | #endif
11 | #elif __linux__
12 | extern "C" void increment(int &i);
13 | extern "C" int exp_null;
14 | #endif
15 |
--------------------------------------------------------------------------------
/src/jit.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | #if !(defined INTEL_X86 || AMD64)
34 | #error This benchmark contains x86/x64-specific assembly code that may be \
35 | incompatible with the current hardware architecture.
36 | #endif
37 |
38 | void JITCALLBACKPTR();
39 |
40 | typedef void(*CALLBACKPTR)();
41 |
42 | BYTE JIT_code[] = {
43 | // Prologue
44 | 0x55, // push ebp/rbp
45 | 0x48, // dec eax
46 | // if compiled for 32bit otherwise extend ebp and esp to rbp and
47 | // rsp for next ins
48 | 0x8B, 0xEC, // mov ebp, esp
49 | 0x53, // push ebx/rbx
50 | 0x56, // push esi/rsi
51 | 0x57, // push edi/rdi
52 |
53 | // Computed call to a function in the untrusted module
54 | 0x48, // dec eax if compiled for 32bit otherwise extend ebx to rbx
55 | // for next ins
56 | 0xbb, // mov ebx, 0x00000000
57 | 0x00,
58 | 0x00,
59 | 0x00,
60 | 0x00,
61 | 0x90,
62 | 0x90,
63 | 0x90,
64 | 0x90, // 8 bytes of address need to be patched -- NOP is added so
65 | // that it works for both 32-bit and 64-bit machine
66 | 0xff, 0x13, // call ptr [ebx/rbx]
67 |
68 | // Epilogue
69 | 0x5F, // pop edi/rdi
70 | 0x5E, // pop esi/rsi
71 | 0x5b, // pop ebx/rbx
72 | 0x48, // dec eax if compiled for 32bit otherwise extend ebp and esp
73 | // to rbp and rsp for next ins
74 | 0x8B, 0xE5, // mov esp, ebp
75 | 0x5D, // pop ebp/rbp
76 | 0xC3 // retn
77 | };
78 |
79 | int main()
80 | {
81 |
82 | #ifdef _WIN32
83 | SYSTEM_INFO info;
84 | DWORD dwPageSize;
85 | FARPROC pJIT;
86 | BOOL retVF;
87 |
88 | // Get page size of current system
89 | GetSystemInfo(&info);
90 | dwPageSize = info.dwPageSize;
91 |
92 | // Allocate a page of memory (RWX)
93 | pJIT = (FARPROC)VirtualAlloc(
94 | NULL,
95 | dwPageSize,
96 | MEM_COMMIT | MEM_RESERVE,
97 | PAGE_EXECUTE_READWRITE
98 | );
99 |
100 | #elif __linux__
101 | uint8_t *pJIT;
102 | int page_size;
103 | int fd;
104 |
105 | page_size = getpagesize();
106 |
107 | // Allocate a page of memory (RWX)
108 | fd = open("/dev/zero", O_RDONLY);
109 | pJIT = (uint8_t *)mmap(
110 | NULL,
111 | page_size,
112 | PROT_READ | PROT_WRITE | PROT_EXEC,
113 | MAP_PRIVATE,
114 | fd,
115 | 0
116 | );
117 | #endif
118 |
119 | if (!pJIT)
120 | {
121 | printf("Memory allocation failed for pJIT");
122 | exit(1);
123 | }
124 |
125 | // Patch JIT_code
126 | CALLBACKPTR pJITCALLBACKPTR = &JITCALLBACKPTR;
127 | void *ppJITCALLBACKPTR = &pJITCALLBACKPTR;
128 | memcpy(&(JIT_code[9]), &ppJITCALLBACKPTR, sizeof(pJITCALLBACKPTR));
129 |
130 | // Copy JIT_code to pJIT
131 | memcpy(pJIT, JIT_code, sizeof(JIT_code));
132 |
133 | // Call pJIT
134 | ((CALLBACKPTR)pJIT)();
135 |
136 | // Free the page allocated
137 | #ifdef _WIN32
138 | retVF = VirtualFree(pJIT, 0, MEM_RELEASE);
139 | if (!retVF)
140 | {
141 | printf("VirtualFree() failed freeing pJIT");
142 | exit(1);
143 | }
144 | #elif __linux__
145 | munmap(pJIT, page_size);
146 | #endif
147 |
148 | printf("jit test passed.\n");
149 | return 0;
150 | }
151 |
152 | void JITCALLBACKPTR()
153 | {
154 | printf("This is a message in JITCALLBACKPTR()\n");
155 | }
156 |
--------------------------------------------------------------------------------
/src/load_time_dynlnk_linux.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | NANOSECOND start_time;
34 | NANOSECOND end_time;
35 | NANOSECOND total_time;
36 |
37 | int main()
38 | {
39 | char *p;
40 | int page_size;
41 | int fd;
42 |
43 | // Record starting time
44 | start_time = get_wall_time();
45 | page_size = getpagesize();
46 |
47 | // Call functions exported by a dynamically linked library in an intensive loop.
48 | for (long long int i = 0; i < MAX_LOOP * LTTX; ++i)
49 | {
50 | fd = open ("/dev/zero", O_RDONLY);
51 | p = (char *) mmap (
52 | NULL,
53 | page_size,
54 | PROT_READ | PROT_WRITE,
55 | MAP_PRIVATE,
56 | fd,
57 | 0
58 | );
59 | close (fd);
60 |
61 | if (!p) {
62 | perror("Couldn’t malloc(1024)");
63 | exit(errno);
64 | }
65 |
66 | p[123] = 123;
67 |
68 | if (mprotect(p, page_size, PROT_NONE)) {
69 | perror("Couldn’t mprotect");
70 | exit(errno);
71 | }
72 |
73 | munmap(p, page_size);
74 | }
75 |
76 | // Record ending time
77 | end_time = get_wall_time();
78 | total_time = end_time - start_time;
79 |
80 | // Print time elapsed in the loop.
81 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
82 | return 0;
83 | }
84 |
--------------------------------------------------------------------------------
/src/load_time_dynlnk_windows.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | NANOSECOND start_time;
34 | NANOSECOND end_time;
35 | NANOSECOND total_time;
36 |
37 | int main()
38 | {
39 | LPVOID base_addr = NULL;
40 | DWORD dwOldProtect;
41 | BOOL retVP = FALSE;
42 | BOOL retVF = FALSE;
43 | SIZE_T dwSize = 1;
44 |
45 | // Record starting time
46 | start_time = get_wall_time();
47 |
48 | // Call functions exported by a dynamically linked library in an intensive loop.
49 | for (long long int i = 0; i < MAX_LOOP * LTTX; ++i)
50 | {
51 | base_addr = VirtualAlloc(
52 | NULL,
53 | dwSize,
54 | MEM_COMMIT,
55 | PAGE_READWRITE
56 | );
57 |
58 | if (!base_addr)
59 | {
60 | printf("VirtualAlloc() failed...\n");
61 | exit(1);
62 | }
63 |
64 | retVP = VirtualProtect(
65 | base_addr,
66 | dwSize,
67 | PAGE_READONLY,
68 | &dwOldProtect
69 | );
70 |
71 | if (!retVP)
72 | {
73 | printf("VirtualProtect() failed...\n");
74 | exit(1);
75 | }
76 |
77 | retVF = VirtualFree(
78 | base_addr,
79 | 0,
80 | MEM_RELEASE
81 | );
82 |
83 | if (!retVF)
84 | {
85 | printf("VirtualFree() failed...\n");
86 | exit(1);
87 | }
88 | }
89 |
90 | // Record ending time
91 | end_time = get_wall_time();
92 | total_time = end_time - start_time;
93 |
94 | // Print time elapsed in the loop.
95 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
96 | return 0;
97 | }
98 |
--------------------------------------------------------------------------------
/src/mem.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | void callee1();
34 | void callee2();
35 | // min estimated max size of callee1 and callee 2
36 | #define ESTIMATED_FUNC_SIZE 100
37 | static bool flag_1 = FALSE;
38 | static bool flag_2 = FALSE;
39 |
40 | typedef void(*FUNCPTR)();
41 |
42 | int main()
43 | {
44 | SYSTEM_INFO info;
45 | DWORD dwPageSize;
46 | FARPROC caller;
47 | BOOL retVP;
48 | BOOL retVF;
49 | DWORD dummy;
50 | unsigned int size1;
51 | unsigned int size2;
52 |
53 | // Get page size of current system.
54 | GetSystemInfo(&info);
55 | dwPageSize = info.dwPageSize;
56 |
57 | // Allocate a page of memory (RW).
58 | caller = (FARPROC)VirtualAlloc(
59 | NULL,
60 | dwPageSize,
61 | MEM_COMMIT | MEM_RESERVE,
62 | PAGE_READWRITE
63 | );
64 | if (!caller)
65 | {
66 | printf("Memory allocation failed for caller");
67 | exit(1);
68 | }
69 |
70 | size1 = ((((unsigned int)callee1) + (ESTIMATED_FUNC_SIZE - 1)) / dwPageSize + 1) * dwPageSize - ((unsigned int)callee1);
71 |
72 | // Copy code to caller
73 | memcpy(caller, (void *)&callee1, size1);
74 |
75 | // Change memory protection to executable only.
76 | retVP = VirtualProtect(
77 | caller,
78 | dwPageSize,
79 | PAGE_EXECUTE,
80 | &dummy
81 | );
82 | if (!retVP)
83 | {
84 | printf("VirtualProtect failed");
85 | exit(1);
86 | }
87 |
88 | // Invoke caller, in which callee1 is called.
89 | ((FUNCPTR)caller)();
90 |
91 | // Change memory protection to RWX.
92 | retVP = VirtualProtect(
93 | caller,
94 | dwPageSize,
95 | PAGE_EXECUTE_READWRITE,
96 | &dummy
97 | );
98 | if (!retVP)
99 | {
100 | printf("VirtualProtect failed");
101 | exit(1);
102 | }
103 |
104 | size2 = ((((unsigned int)callee2) + (ESTIMATED_FUNC_SIZE - 1)) / dwPageSize + 1) * dwPageSize - ((unsigned int)callee2);
105 |
106 | // Copy code to caller.
107 | memcpy(caller, (void *)&callee2, size2);
108 |
109 | // Invoke caller. This time caller2 is called.
110 | ((FUNCPTR)caller)();
111 |
112 | // Free the page allocated.
113 | retVF = VirtualFree(caller, 0, MEM_RELEASE);
114 | if (!retVF)
115 | {
116 | printf("VirtualFree() failed freeing caller");
117 | exit(1);
118 | }
119 |
120 | if (flag_1 && flag_2)
121 | {
122 | printf("mem test passed\n");
123 | }
124 | else
125 | {
126 | printf("mem test failed\n");
127 | }
128 |
129 | return 0;
130 | }
131 |
132 | void callee1()
133 | {
134 | flag_1 = TRUE;
135 | }
136 |
137 | void callee2()
138 | {
139 | flag_2 = TRUE;
140 | }
141 |
--------------------------------------------------------------------------------
/src/multithreading_linux32.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | #ifdef INTEL_X86
34 | //
35 | #elif AMD64
36 | #error This benchmark is designed for x86 architecture only. For x64, please use \
37 | multithreading_linux64.cpp instead.
38 | #else
39 | #error This benchmark contains x86/x64-specific assembly code that may be \
40 | incompatible with the current hardware architecture.
41 | #endif
42 |
43 | using namespace std;
44 |
45 | static int hChild;
46 | static unsigned long long int trials, hijacktramp_addr;
47 | static volatile int hijacked = 0;
48 |
49 | // This function runs the child thread that attempts to hijack the main thread.
50 | // The retaddr_ptr argument points to the main thread's return address slot.
51 | void *ChildThread(void * retaddr_ptr)
52 | {
53 | printf("Child thread started hijacking.\n");
54 |
55 | // Repeatedly write into the main thread's return address slot.
56 | // The write is attempted times.
57 | asm (
58 | " movq %0, %%rcx\n\t"
59 | "L:"
60 | " movq %1, (%2)\n\t"
61 | " loop L"
62 | : // OutputOperands : A comma-separated list of the C variables modified
63 | : "r" (trials), "r" (hijacktramp_addr), "r" (retaddr_ptr) // InputOperands : A comma-separated list of C expressions read
64 | : "rcx", "memory" // Clobbers : A comma-separated list of registers or other values changed
65 | );
66 |
67 | // 0.1 second sleep for making sure hijacked has changed if it should
68 | usleep(100000);
69 |
70 | // If the hijack was successful, the main thread sets the global "hijacked" variable to 1.
71 | if (!hijacked)
72 | {
73 | printf("All trials complete. Hijack unsuccessful.\n");
74 | exit(0);
75 | }
76 |
77 | return 0;
78 | }
79 |
80 | int main(int argc, char* argv[])
81 | {
82 | unsigned int idChild;
83 | pthread_t thread1;
84 | void * esp_addr;
85 |
86 | printf("Enter number of trials: ");
87 | scanf("%llu", &trials);
88 |
89 | int flag = 0;
90 |
91 | asm (
92 | " leaq HIJACKTRAMP(%%rip), %%rax\n\t"
93 | " movq %%rax, %0\n\t"
94 | " leaq -8(%%rsp), %%rax\n\t" // Store the address of the forthcoming return address in esp_addr.
95 | " movq %%rax, %1\n\t"
96 | "HIJACKTRAMP:"
97 | : "=r" (hijacktramp_addr), "=r" (esp_addr) // OutputOperands : A comma-separated list of the C variables modified
98 | : // InputOperands : A comma-separated list of C expressions read
99 | : "rax", "memory" // Clobbers : A comma-separated list of registers or other values changed
100 | );
101 |
102 | if (flag) {
103 | hijacked = 1;
104 | goto HIJACKED;
105 | }
106 |
107 | flag = 1;
108 |
109 | // Spawn the child (hijacker) thread.
110 | hChild = pthread_create(
111 | &thread1,
112 | NULL,
113 | ChildThread,
114 | esp_addr);
115 |
116 | if (hChild) {
117 | printf("Could not make child thread!\n");
118 | abort();
119 | }
120 |
121 | // Repeat a guarded return in the tightest possible infinite loop.
122 | asm (
123 | " leaq L2(%rip), %rbx\n\t"
124 | "L1:"
125 | " call L3\n\t"
126 | "L2:"
127 | " jmp L1\n\t"
128 | "L3:"
129 | " ret"
130 | );
131 |
132 | printf("Infinite loop ended normally---impossible!\n");
133 | abort();
134 |
135 | // If the hijacker is successful, the "ret" above will jump here.
136 | HIJACKED:
137 |
138 | // The child thread might still be running, so push a dummy return address for it to continue hijacking.
139 | asm (
140 | "push $0"
141 | );
142 |
143 | printf("Hijack successful!\n");
144 |
145 | // Wait for the child thread to terminate normally.
146 | pthread_join(thread1, NULL);
147 |
148 | // Pop the dummy return address.
149 | asm (
150 | "pop %rax"
151 | );
152 |
153 | return 0;
154 | }
155 |
--------------------------------------------------------------------------------
/src/multithreading_linux64.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | #ifdef AMD64
34 | //
35 | #elif INTEL_X86
36 | #error This benchmark is designed for x64 architecture only. For x86, please use \
37 | multithreading_linux32.cpp instead.
38 | #else
39 | #error This benchmark contains x86/x64-specific assembly code that may be \
40 | incompatible with the current hardware architecture.
41 | #endif
42 |
43 | using namespace std;
44 |
45 | static int hChild;
46 | static unsigned long long int trials, hijacktramp_addr;
47 | static volatile int hijacked = 0;
48 |
49 | // This function runs the child thread that attempts to hijack the main thread.
50 | // The retaddr_ptr argument points to the main thread's return address slot.
51 | void *ChildThread(void * retaddr_ptr)
52 | {
53 | printf("Child thread started hijacking.\n");
54 |
55 | // Repeatedly write into the main thread's return address slot.
56 | // The write is attempted times.
57 | asm (
58 | " movq %0, %%rcx\n\t"
59 | "L:"
60 | " movq %1, (%2)\n\t"
61 | " loop L"
62 | : // OutputOperands : A comma-separated list of the C variables modified
63 | : "r" (trials), "r" (hijacktramp_addr), "r" (retaddr_ptr) // InputOperands : A comma-separated list of C expressions read
64 | : "rcx", "memory" // Clobbers : A comma-separated list of registers or other values changed
65 | );
66 |
67 | // 0.1 second sleep for making sure hijacked has changed if it should
68 | usleep(100000);
69 |
70 | // If the hijack was successful, the main thread sets the global "hijacked" variable to 1.
71 | if (!hijacked)
72 | {
73 | printf("All trials complete. Hijack unsuccessful.\n");
74 | exit(0);
75 | }
76 |
77 | return 0;
78 | }
79 |
80 | int main(int argc, char* argv[])
81 | {
82 | unsigned int idChild;
83 | pthread_t thread1;
84 | void * esp_addr;
85 |
86 | printf("Enter number of trials: ");
87 | scanf("%llu", &trials);
88 |
89 | int flag = 0;
90 |
91 | asm (
92 | " leaq HIJACKTRAMP(%%rip), %%rax\n\t"
93 | " movq %%rax, %0\n\t"
94 | " leaq -8(%%rsp), %%rax\n\t" // Store the address of the forthcoming return address in esp_addr.
95 | " movq %%rax, %1\n\t"
96 | "HIJACKTRAMP:"
97 | : "=r" (hijacktramp_addr), "=r" (esp_addr) // OutputOperands : A comma-separated list of the C variables modified
98 | : // InputOperands : A comma-separated list of C expressions read
99 | : "rax", "memory" // Clobbers : A comma-separated list of registers or other values changed
100 | );
101 |
102 | if (flag) {
103 | hijacked = 1;
104 | goto HIJACKED;
105 | }
106 |
107 | flag = 1;
108 |
109 | // Spawn the child (hijacker) thread.
110 | hChild = pthread_create(
111 | &thread1,
112 | NULL,
113 | ChildThread,
114 | esp_addr);
115 |
116 | if (hChild) {
117 | printf("Could not make child thread!\n");
118 | abort();
119 | }
120 |
121 | // Repeat a guarded return in the tightest possible infinite loop.
122 | asm (
123 | " leaq L2(%rip), %rbx\n\t"
124 | "L1:"
125 | " call L3\n\t"
126 | "L2:"
127 | " jmp L1\n\t"
128 | "L3:"
129 | " ret"
130 | );
131 |
132 | printf("Infinite loop ended normally---impossible!\n");
133 | abort();
134 |
135 | // If the hijacker is successful, the "ret" above will jump here.
136 | HIJACKED:
137 |
138 | // The child thread might still be running, so push a dummy return address for it to continue hijacking.
139 | asm (
140 | "push $0"
141 | );
142 |
143 | printf("Hijack successful!\n");
144 |
145 | // Wait for the child thread to terminate normally.
146 | pthread_join(thread1, NULL);
147 |
148 | // Pop the dummy return address.
149 | asm (
150 | "pop %rax"
151 | );
152 |
153 | return 0;
154 | }
155 |
--------------------------------------------------------------------------------
/src/multithreading_windows.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | #ifdef INTEL_X86
34 | //
35 | #elif AMD64
36 | #error This benchmark is designed for x86 architecture only.
37 | #else
38 | #error This benchmark contains x86-specific assembly code that may be incompatible \
39 | with the current hardware architecture.
40 | #endif
41 |
42 | static HANDLE hChild;
43 | static DWORD trials, hijack_addr;
44 | static volatile int hijacked = 0;
45 |
46 | // This function runs the child thread that attempts to hijack the main thread.
47 | // The retaddr_ptr argument points to the main thread's return address slot.
48 | DWORD WINAPI ChildThread(LPVOID retaddr_ptr)
49 | {
50 | // Repeatedly write into the main thread's return address slot.
51 | // The write is attempted times.
52 | _asm {
53 | mov eax, retaddr_ptr
54 | mov ebx, hijack_addr
55 | mov ecx, trials
56 | L : mov [eax], ebx
57 | loop L
58 | }
59 |
60 | // If the hijack was successful, the main thread sets the global "hijacked" variable to 1.
61 | if (!hijacked)
62 | {
63 | printf("All trials complete. Hijack unsuccessful.\n");
64 | // The main thread loops infinitely, so to terminate it, we use ExitProcess.
65 | ExitProcess(0);
66 | }
67 |
68 | return 0;
69 | }
70 |
71 | int main(int argc, char* argv[])
72 | {
73 | DWORD idChild;
74 | LPVOID esp_addr;
75 |
76 | printf("Enter number of trials: ");
77 | scanf_s("%u", &trials);
78 |
79 | _asm {
80 | mov hijack_addr, offset HIJACK // Store the address to which the hijacker should redirect in a global var.
81 | lea eax, [esp - 4] // Store the address of the forthcoming return address in esp_addr.
82 | mov esp_addr, eax
83 | }
84 |
85 | // Spawn the child (hijacker) thread.
86 | hChild = CreateThread(
87 | NULL,
88 | 0,
89 | ChildThread,
90 | esp_addr,
91 | 0,
92 | &idChild);
93 | if (!hChild) abort();
94 |
95 | // Repeat a guarded return in the tightest possible infinite loop.
96 | _asm {
97 | mov eax, offset L2
98 | L1 : call L3
99 | L2 : jmp L1
100 | L3 : mov[esp], eax
101 | ret
102 | }
103 |
104 | printf("Infinite loop ended normally---impossible!\n");
105 | abort();
106 |
107 | // If the hijacker is successful, the "ret" above will jump here.
108 | HIJACK:
109 | hijacked = 1;
110 |
111 | _asm {
112 | push 0 // The child thread might still be running, so push a dummy return address for it to continue hijacking.
113 | }
114 |
115 | printf("Hijack successful!\n");
116 |
117 | // Wait for the child thread to terminate normally.
118 | WaitForSingleObject(hChild, INFINITE);
119 |
120 | // Pop the dummy return address.
121 | _asm { pop eax }
122 |
123 | return 0;
124 | }
125 |
--------------------------------------------------------------------------------
/src/ret.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | NANOSECOND start_time;
34 | NANOSECOND end_time;
35 | NANOSECOND total_time;
36 |
37 | // A function does nothing but return
38 | void retFunc();
39 |
40 | int main()
41 | {
42 | // Record starting time
43 | start_time = get_wall_time();
44 |
45 | // Call a function that does nothing but returns in an intensive loop.
46 | for (long long int i = 0; i < MAX_LOOP * RETTS; i++)
47 | {
48 | retFunc();
49 | }
50 |
51 | // Record ending time
52 | end_time = get_wall_time();
53 | total_time = end_time - start_time;
54 |
55 | // Print time elapsed in the loop.
56 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
57 |
58 | return 0;
59 | }
60 |
61 | #if (defined MSVC_ARCH || GNU_ARCH || CLANG_ARCH)
62 | void retFunc()
63 | {
64 | return;
65 | }
66 | #else
67 | #error This benchmark is designed for processor architectures supported by mainstream \
68 | compilers, including MSVC, GCC, and LLVM. To run this benchmark on other platforms, \
69 | users of ConFIRM can extend this source code as needed.\
70 | #endif
71 |
--------------------------------------------------------------------------------
/src/run_time_dynlnk.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | NANOSECOND start_time;
34 | NANOSECOND end_time;
35 | NANOSECOND total_time;
36 |
37 | // Define a function pointer type for retrieving function pointer
38 | // returned by GetProcAddress()/dlsym().
39 | typedef void(*INC)(int&);
40 |
41 | int main()
42 | {
43 | #ifdef _WIN32
44 | HINSTANCE libHandle = NULL;
45 | BOOL retFree = FALSE;
46 | #elif __linux__
47 | void *libHandle;
48 | char *error;
49 | #endif
50 | INC pInc = NULL;
51 | int count = 0;
52 |
53 | // record starting time
54 | start_time = get_wall_time();
55 |
56 | for (long long int i = 0; i < MAX_LOOP * DYNLTS; ++i)
57 | {
58 | // Load an untrusted module libinc.dll/.so
59 | #ifdef _WIN32
60 | libHandle = LoadLibrary(L"libinc.dll");
61 | #elif __linux__
62 | libHandle = dlopen("./libinc.so", RTLD_LAZY);
63 | #endif
64 | if (!libHandle)
65 | {
66 | printf("Loading library failed.\n");
67 | exit(1);
68 | }
69 |
70 | // Get a function pointer exported by libinc.dll/.so
71 | #ifdef _WIN32
72 | pInc = (INC)GetProcAddress(libHandle, "increment");
73 | #elif __linux__
74 | pInc = (INC) dlsym(libHandle, "increment");
75 | #endif
76 | if (!pInc)
77 | {
78 | printf("Finding symbol failed.\n");
79 | exit(1);
80 | }
81 |
82 | // Call the returned function.
83 | pInc(count);
84 |
85 | // Unload libinc.dll/.so
86 | #ifdef _WIN32
87 | retFree = FreeLibrary(libHandle);
88 | if (!retFree)
89 | {
90 | printf("FreeLibrary() failed.\n");
91 | exit(1);
92 | }
93 | #elif __linux__
94 | dlclose(libHandle);
95 | #endif
96 | }
97 |
98 | // record ending time
99 | end_time = get_wall_time();
100 | total_time = end_time - start_time;
101 |
102 | // print results
103 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
104 | printf("count is %d\n", count);
105 | return 0;
106 | }
107 |
--------------------------------------------------------------------------------
/src/seh.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | // This benchmark is Windows specific.
32 |
33 | #include "setup.h"
34 |
35 | void writeToMem();
36 | static int except_count = 0;
37 | static int finally_count = 0;
38 |
39 | int main()
40 | {
41 | // Throw access violation exception and handle it using SEH in an intensive loop,
42 | // to see if a CFI solution being tested provides semantic transparency.
43 | for (long long int i = 0; i < MAX_LOOP * SEHTS; ++i)
44 | {
45 | __try
46 | {
47 | writeToMem();
48 | }
49 | __except (GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION ?
50 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
51 | {
52 | except_count++;
53 | }
54 | }
55 |
56 | // Print results.
57 | printf("except_count is %d\nfinally_count is %d\n ", except_count++, finally_count);
58 | printf("SEH test passed.");
59 |
60 | return 0;
61 | }
62 |
63 | // A function that writes to invalid address.
64 | void writeToMem()
65 | {
66 | __try
67 | {
68 | __try
69 | {
70 | *(unsigned int*)0x0 = 0;
71 | }
72 | __finally
73 | {
74 | finally_count++;
75 | }
76 | }
77 | __except (GetExceptionCode() == EXCEPTION_FLT_DIVIDE_BY_ZERO ?
78 | EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH)
79 | {
80 | printf("This should not be printed --- impossible!\n");
81 | }
82 | }
83 |
--------------------------------------------------------------------------------
/src/setup.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | #ifdef _WIN32
34 | // In Windows, a time stamp is calculated as the current value of the performance
35 | // counter divided by the frequency of the performance counter.
36 | NANOSECOND get_wall_time()
37 | {
38 | LARGE_INTEGER time, frequency;
39 | QueryPerformanceFrequency(&frequency);
40 | QueryPerformanceCounter(&time);
41 | return (NANOSECOND)(time.QuadPart * BILLION / frequency.QuadPart);
42 | }
43 |
44 | #elif __linux__
45 | // In Linux, elapsed time is calculated as a difference between two monotonic times.
46 | NANOSECOND get_wall_time()
47 | {
48 | struct timespec time;
49 | clock_gettime(CLOCK_MONOTONIC, &time);
50 | return (NANOSECOND)(BILLION * time.tv_sec + time.tv_nsec);
51 | }
52 |
53 | #else
54 | #endif
55 |
--------------------------------------------------------------------------------
/src/setup.h:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | // This is the master configuration file.
32 | // Users of ConFIRM can specialize their own parameters.
33 |
34 | #pragma once
35 |
36 | // Benchmarks in Windows and Linux require different header files
37 | #ifdef _WIN32
38 | #include
39 | #include
40 | #include
41 | #include
42 |
43 | #elif __linux__
44 | #include
45 | #include
46 | #include
47 | #include
48 | #include
49 | #include
50 | #include
51 | #include
52 | #include
53 | #include
54 | #include
55 | #include
56 | #include
57 | #define FALSE false
58 | #define BYTE unsigned char
59 |
60 | #else
61 | #endif
62 |
63 | // Loop iteration counts for different benchmarks.
64 | // With the current counts, each benchmark runs around 2 min.
65 | #define MAX_LOOP 1024L //base loop count
66 | #define CPEHTS 5 //cppeh
67 | #define SEHTS 5 //seh
68 | #define VEHTS 5 //veh
69 | #define DYNLTS 0.3 //run_time_dynlnk
70 | #define FPTRTS 500 //fptr
71 | //#define IMPDTS 6500 //data_symbl
72 | #define INDCTS 360 //tail_call
73 | #define JITCTS 2500
74 | #define CALTS 0.4 //callback
75 | #define LHWXTS 20 //signal
76 | #define LTTX 1.2 //load_time_dynlnk
77 | #define RETTS 5700 //ret
78 | #define SWTCTS 590 //switch
79 | #define VTABTS 460 //vtbl_call
80 | #define DLTS 500
81 |
82 | // Macros for different calling conventions in Windows and Linux
83 | #ifdef _WIN32
84 | #define CDECL __cdecl
85 | #define STDCALL __stdcall
86 | #define FASTCALL __fastcall
87 | #define THISCALL __thiscall
88 |
89 | #elif __linux__
90 | #define CDECL __attribute__((cdecl))
91 | #define STDCALL
92 | #define FASTCALL __attribute__((fastcall))
93 | #define THISCALL __attribute__((thiscall))
94 |
95 | #else
96 | #endif
97 |
98 | // A helper function that can be used to calculate elapsed time in nanosecond.
99 | #define NANOSECOND uint64_t
100 | #define BILLION 1000000000L
101 | extern NANOSECOND get_wall_time();
102 |
103 | // Pre-defined compiler macros for x86/x64
104 | #if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64)
105 | #define AMD64
106 | #endif
107 |
108 | #if defined(i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__i386) || defined(__IA32__) || defined(_M_IX86) || defined(__X86__) || defined(_X86_) || defined(__I86__) || defined(__INTEL__) || defined(__386) || defined(__THW_INTEL__)
109 | #define INTEL_X86
110 | #endif
111 |
112 | // Pre-defined compiler macros for processor architectures supported by different compilers.
113 | #if defined(_M_ALPHA) || defined(_M_AMD64) || defined(_M_X64) || defined(_M_ARM) || defined(_M_ARMT) || defined(_M_I86) || defined(_M_IX86) || defined(_M_IA64) || defined(_M_PPC)
114 | #define MSVC_ARCH
115 | #endif
116 |
117 | #if defined(__alpha__) || defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(__arm__) || defined(__thumb__) || defined(__aarch64__) || defined(__bfin) || defined(__BFIN__) || defined(__convex__) || defined(__hppa__) || defined(i386) || defined(__i386) || defined(__i386__) || defined(__i486__) || defined(__i586__) || defined(__i686__) || defined(__ia64__) || defined(_IA64) || defined(__IA64__) || defined(__m68k__) || defined(__mips__) || defined(mips) || defined(__mips) || defined(__powerpc) || defined(__powerpc__) || defined(__powerpc64__) || defined(__POWERPC__) || defined(__ppc__) || defined(__ppc64__) || defined(__PPC__) || defined(__PPC64__) || defined(_ARCH_PPC) || defined(_ARCH_PPC64) || defined(__sparc__) || defined(__sparc_v8__) || defined(__sparc_v9__) || defined(__sh__) || defined(__s390__) || defined(__s390x__)
118 | #define GNU_ARCH
119 | #endif
120 |
121 | #if defined(__zarch__) || defined(__x86_64__) || defined(__ARM_ARCH) || defined(__arm__) || defined(__aarch64__)
122 | #define CLANG_ARCH
123 | #endif
124 |
--------------------------------------------------------------------------------
/src/signal.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include
32 | #include
33 | #include
34 | #include "setup.h"
35 |
36 | sigjmp_buf mark;
37 |
38 | // Define a hanlder that restores the environment saved by sigsetjmp.
39 | void myhandler(int signo) {
40 | siglongjmp(mark, -1);
41 | }
42 |
43 | // A function that writes to invalid address.
44 | void exception_loop(void) {
45 | char *p = NULL;
46 | *p = 5;
47 | }
48 |
49 | int main(void) {
50 | // Set up a signal handler that handles invalid memory reference (SIGSEGV).
51 | struct sigaction myhandle;
52 | myhandle.sa_handler = myhandler;
53 | sigemptyset(&myhandle.sa_mask);
54 | myhandle.sa_flags = SA_NODEFER;
55 | sigaction(SIGSEGV, &myhandle, NULL);
56 |
57 | // Write to invalid address in an intensive loop, to see if a CFI solution being tested
58 | // provides semantic transparency.
59 | long long int i = 0;
60 | sigsetjmp(mark, 0);
61 | if (i++ < MAX_LOOP * LHWXTS)
62 | exception_loop();
63 |
64 | printf("signal test passed.\n");
65 |
66 | return 0;
67 | }
68 |
--------------------------------------------------------------------------------
/src/switch.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | static int zero_count = 0;
34 | static int one_count = 0;
35 | static int two_count = 0;
36 | static int three_count = 0;
37 | const int divisor = 4;
38 |
39 | NANOSECOND start_time;
40 | NANOSECOND end_time;
41 | NANOSECOND total_time;
42 |
43 | int main()
44 | {
45 | int dividend = 0;
46 | int remainder = 0;
47 |
48 | // Initialize random seed
49 | srand((unsigned int)time(NULL));
50 | // Record starting time
51 | start_time = get_wall_time();
52 |
53 | // Execute a switch-case statement in an intensive loop.
54 | for (long long int i = 0; i < MAX_LOOP * SWTCTS; i++)
55 | {
56 | dividend = rand();
57 | remainder = dividend % divisor;
58 |
59 | switch (remainder)
60 | {
61 | case 0:
62 | zero_count += 1;
63 | break;
64 | case 1:
65 | one_count += 1;
66 | break;
67 | case 2:
68 | two_count += 1;
69 | break;
70 | case 3:
71 | three_count += 1;
72 | break;
73 | default:
74 | printf("should not reach here -- impossible!");
75 | }
76 | }
77 |
78 | // Record ending time
79 | end_time = get_wall_time();
80 | total_time = end_time - start_time;
81 |
82 | // Print time elapsed in the loop.
83 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
84 |
85 | // Print counts so that a compiler doesn't optimize too much.
86 | printf("%d numbers have remainder of zero modulo %d.\n", zero_count, divisor);
87 | printf("%d numbers have remainder of one modulo %d.\n", one_count, divisor);
88 | printf("%d numbers have remainder of two modulo %d.\n", two_count, divisor);
89 | printf("%d numbers have remainder of three modulo %d.\n", three_count, divisor);
90 |
91 | return 0;
92 | }
93 |
--------------------------------------------------------------------------------
/src/tail_call.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | static int zero_count = 0;
34 | static int one_count = 0;
35 | static int two_count = 0;
36 | static int three_count = 0;
37 | const int divisor = 4;
38 |
39 | NANOSECOND start_time;
40 | NANOSECOND end_time;
41 | NANOSECOND total_time;
42 |
43 | void helper();
44 | void case0();
45 | void case1();
46 | void case2();
47 | void case3();
48 |
49 | int main()
50 | {
51 | // Initialize random seed
52 | srand((unsigned int)time(NULL));
53 | // Record starting time
54 | start_time = get_wall_time();
55 |
56 | // Call a function that ends with a tail-call in an intensive loop.
57 | for (long long int i = 0; i < MAX_LOOP * INDCTS; i++)
58 | {
59 | helper();
60 | }
61 |
62 | // Record ending time
63 | end_time = get_wall_time();
64 | total_time = end_time - start_time;
65 |
66 | // Print time elapsed in the loop.
67 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
68 |
69 | // Print counts so that a compiler doesn't optimize too much.
70 | printf("%d numbers have remainder of zero modulo %d.\n", zero_count, divisor);
71 | printf("%d numbers have remainder of one modulo %d.\n", one_count, divisor);
72 | printf("%d numbers have remainder of two modulo %d.\n", two_count, divisor);
73 | printf("%d numbers have remainder of three modulo %d.\n", three_count, divisor);
74 | }
75 |
76 | void helper()
77 | {
78 | void(*fptr) ();
79 | int r = rand();
80 | int remainder = r % divisor;
81 |
82 | if (remainder == 0)
83 | fptr = case0;
84 | if (remainder == 1)
85 | fptr = case1;
86 | if (remainder == 2)
87 | fptr = case2;
88 | if (remainder == 3)
89 | fptr = case3;
90 |
91 | // Tail-call using a function pointer.
92 | fptr();
93 | }
94 |
95 | void case0()
96 | {
97 | zero_count += 1;
98 | }
99 |
100 | void case1()
101 | {
102 | one_count += 1;
103 | }
104 |
105 | void case2()
106 | {
107 | two_count += 1;
108 | }
109 |
110 | void case3()
111 | {
112 | three_count += 1;
113 | }
114 |
--------------------------------------------------------------------------------
/src/tls_callback.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | void NTAPI TLSEntry(PVOID DllHandle, DWORD dwReason, PVOID);
34 | DWORD WINAPI ThreadProc(CONST LPVOID lpParam);
35 |
36 | // Linker spec for using TLS callback
37 | #ifdef _WIN32
38 | #pragma comment (linker, "/INCLUDE:__tls_used")
39 | #pragma comment (linker, "/INCLUDE:_tls_callback")
40 | #else
41 | #pragma comment (linker, "/INCLUDE:_tls_used")
42 | #pragma comment (linker, "/INCLUDE:tls_callback")
43 | #endif
44 | #ifdef _WIN32
45 | #pragma data_seg(".CRT$XLF")
46 | EXTERN_C
47 | #else
48 | #pragma const_seg(".CRT$XLF")
49 | EXTERN_C const
50 | #endif
51 | PIMAGE_TLS_CALLBACK tls_callback = TLSEntry;
52 | #ifdef _WIN32
53 | #pragma data_seg()
54 | #else
55 | #pragma const_seg()
56 | #endif
57 |
58 | int main()
59 | {
60 | const int thread_count = 10;
61 | HANDLE handles[thread_count];
62 |
63 | // Creating/terminating new thread invokes a TLS callback.
64 | for (int i = 0; i < thread_count; i++)
65 | {
66 | handles[i] = CreateThread(NULL, 0, &ThreadProc, 0, 0, NULL);
67 | }
68 | // Wairing for thread to terminate.
69 | WaitForMultipleObjects(thread_count, handles, TRUE, INFINITE);
70 |
71 | for (int i = 0; i < thread_count; i++)
72 | {
73 | CloseHandle(handles[i]);
74 | }
75 |
76 | printf("TLS callback test passed.\n");
77 |
78 | return 0;
79 | }
80 |
81 | DWORD WINAPI ThreadProc(CONST LPVOID lpParam)
82 | {
83 | ExitThread(0);
84 | }
85 |
86 | void NTAPI TLSEntry(PVOID DllHandle, DWORD dwReason, PVOID)
87 | {
88 | if (dwReason == DLL_THREAD_ATTACH)
89 | {
90 | printf("DLL_THREAD_ATTACH\n");
91 | }
92 |
93 | if (dwReason == DLL_THREAD_DETACH)
94 | {
95 | printf("DLL_THREAD_DETACH\n");
96 | }
97 |
98 | if (dwReason == DLL_PROCESS_ATTACH)
99 | {
100 | printf("DLL_PROCESS_ATTACH\n");
101 | }
102 |
103 | if (dwReason == DLL_PROCESS_DETACH)
104 | {
105 | printf("DLL_PROCESS_DETACH\n");
106 | }
107 | }
108 |
--------------------------------------------------------------------------------
/src/unmatched_pair.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 | #include
33 |
34 | void exception_test();
35 | void exception_callee1();
36 | void exception_callee2();
37 |
38 | jmp_buf buf;
39 | void longjmp_test();
40 | void longjmp_callee1();
41 | void longjmp_callee2();
42 |
43 | int main()
44 | {
45 | // Check if a CFI solution can handle unmatched call/return pair due to exception.
46 | exception_test();
47 | printf("exception_test passed\n\n");
48 |
49 | // Check if a CFI solution can handle unmatched call/return pair due to longjmp.
50 | longjmp_test();
51 | printf("longjmp_test passed\n");
52 |
53 | return 0;
54 | }
55 |
56 | void exception_test()
57 | {
58 | try
59 | {
60 | printf("1. a message in exception_test try block\n");
61 | exception_callee1();
62 | }
63 | catch (int e)
64 | {
65 | printf("4. a message in exception_test catch block\n");
66 | }
67 | }
68 |
69 | void exception_callee1()
70 | {
71 | printf("2. a message in exception_callee1\n");
72 | exception_callee2();
73 | }
74 |
75 | void exception_callee2()
76 | {
77 | printf("3. a message in exception_callee2\n");
78 |
79 | // This exception being caught by the catch block in exception_test(), results in
80 | // popping stack frames from multiple calls, followed by a return at the end of
81 | // exception_test(). Shadow stack defenses that are implemented based on
82 | // call/return matching may be problematic.
83 | throw 7;
84 | }
85 |
86 | void longjmp_test()
87 | {
88 | printf("5. a message in longjmp_test\n");
89 | // setjmp() returns 0 when called directly, so control flows to the else block.
90 | // The if block is executed as the jump target of longjmp().
91 | if (setjmp(buf))
92 | printf("8. a message after longjmp\n");
93 | else
94 | longjmp_callee1();
95 | }
96 |
97 | void longjmp_callee1()
98 | {
99 | printf("6. a message in longjmp_callee1\n");
100 | longjmp_callee2();
101 | }
102 |
103 | void longjmp_callee2()
104 | {
105 | printf("7. a message in longjmp_callee2\n");
106 |
107 | // This longjmp to longjmp_test() leads to an unmatched call/return pair,
108 | // followed by a return from longjmp_test to main.
109 | longjmp(buf, 1);
110 | printf("-1, oops, should never reach this!\n");
111 | }
112 |
--------------------------------------------------------------------------------
/src/veh.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | // This benchmark is Windows specific.
32 |
33 | #include "setup.h"
34 |
35 | // Define a vectored exception handler.
36 | LONG WINAPI VectoredHandlerSkip(struct _EXCEPTION_POINTERS *ExceptionInfo);
37 |
38 | int main()
39 | {
40 | PVOID pv = NULL;
41 |
42 | // Register a vectored exception handler.
43 | pv = AddVectoredExceptionHandler(0, VectoredHandlerSkip);
44 |
45 | // Trigger a hardware exception by writing to DS:[0] in a loop, to check whether
46 | // a CFI solution being tested provides semantic transparency.
47 | for (long long int i = 0; i < MAX_LOOP * SEHTS; ++i)
48 | {
49 | *(unsigned int*)0x0 = 0;
50 | }
51 |
52 | // Remove the vectored exception handler.
53 | RemoveVectoredExceptionHandler(pv);
54 |
55 | // Print results
56 | printf("VEH test passed\n");
57 | return 0;
58 | }
59 |
60 | LONG WINAPI VectoredHandlerSkip(struct _EXCEPTION_POINTERS *ExceptionInfo)
61 | {
62 | PCONTEXT Context;
63 | Context = ExceptionInfo->ContextRecord;
64 |
65 | // Add program counter by 1
66 | #ifdef AMD64
67 | Context->Rip = Context->Rip + 1;
68 | #elif defined INTEL_X86
69 | Context->Eip = Context->Eip + 1;
70 | #else
71 | #error This benchmark contains x86/x64-specific assembly code that may be \
72 | incompatible with the current hardware architecture.
73 | #endif
74 |
75 | // Continue execution with the new EIP value.
76 | return EXCEPTION_CONTINUE_EXECUTION;
77 | }
78 |
--------------------------------------------------------------------------------
/src/vtbl_call.cpp:
--------------------------------------------------------------------------------
1 | /*************************************************************************************
2 | * Copyright (c) 2019 Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, and Kevin Hamlen *
3 | * The University of Texas at Dallas *
4 | * *
5 | * Permission is hereby granted, free of charge, to any person obtaining a copy of *
6 | * this software and associated documentation files (the "Software"), to deal in *
7 | * the Software without restriction, including without limitation the rights to *
8 | * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of *
9 | * the Software, and to permit persons to whom the Software is furnished to do so, *
10 | * subject to the following conditions: *
11 | * *
12 | * The above copyright notice and this permission notice shall be included in all *
13 | * copies or substantial portions of the Software. *
14 | * *
15 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR *
16 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS *
17 | * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR *
18 | * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER *
19 | * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN *
20 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
21 | *************************************************************************************/
22 |
23 | /* This file is part of the ConFIRM test suite, whose initial documentation can be
24 | found in the following publication:
25 |
26 | Xiaoyang Xu, Masoud Ghaffarinia, Wenhao Wang, Kevin W. Hamlen, and Zhiqiang Lin.
27 | "ConFIRM: Evaluating Compatibility and Relevance of Control-flow Integrity
28 | Protections for Modern Software." In Proceedings of the 28th USENIX Security
29 | Symposium, August 2019. */
30 |
31 | #include "setup.h"
32 |
33 | // Base class
34 | class base
35 | {
36 | public:
37 | int count_even = 0;
38 | int count_odd = 0;
39 |
40 | virtual int random() { return 0; };
41 | virtual void accEven() {};
42 | virtual void accOdd() {};
43 | virtual bool isOdd(int) { return FALSE; };
44 | };
45 |
46 | // Derived class
47 | class derived: public base
48 | {
49 | public:
50 | int random()
51 | {
52 | return rand();
53 | }
54 |
55 | void accEven()
56 | {
57 | count_even++;
58 | }
59 |
60 | void accOdd()
61 | {
62 | count_odd++;
63 | }
64 |
65 | bool isOdd(int n)
66 | {
67 | return (n % 2);
68 | }
69 | };
70 |
71 | NANOSECOND start_time;
72 | NANOSECOND end_time;
73 | NANOSECOND total_time;
74 |
75 | int main()
76 | {
77 | // Define a derived class instance and a pointer that has type of base class
78 | derived p;
79 | base *pn = &p;
80 | int n;
81 |
82 | // Initialize random seed
83 | srand((unsigned int)time(NULL));
84 | // Record starting time
85 | start_time = get_wall_time();
86 |
87 | // Call virtual functions in an intensive loop
88 | for (long long int i = 0; i < MAX_LOOP * VTABTS; ++i)
89 | {
90 | n = pn->random();
91 | if (pn->isOdd(n))
92 | {
93 | pn->accOdd();
94 | }
95 | else
96 | {
97 | pn->accEven();
98 | }
99 | }
100 |
101 | // Record ending time
102 | end_time = get_wall_time();
103 | total_time = end_time - start_time;
104 |
105 | // Print time elapsed in the loop.
106 | printf("total time in nanoseconds is %llu\n", (long long unsigned int) total_time);
107 |
108 | // Print counts so that a compiler doesn't optimize too much.
109 | printf("%d odd numbers\n", pn->count_odd);
110 | printf("%d even numbers\n", pn->count_even);
111 |
112 | return 0;
113 | }
114 |
--------------------------------------------------------------------------------
/xu19-confirm.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/SoftwareLanguagesSecurityLab/ConFIRM/601de444c5e665812778b61fc0fec5c91dbbedbc/xu19-confirm.pdf
--------------------------------------------------------------------------------