Position-independent Code Reuse: On the Effectiveness of ASLR in the Absence ofInformation Disclosure
Enes Göktaş∗ , Benjamin Kollenda† , Philipp Koppe† , Erik Bosman∗ ,Georgios Portokalidis‡ , Thorsten Holz† , Herbert Bos∗ and Cristiano Giuffrida∗∗ Computer Science Institute, Vrije Universiteit Amsterdam, The Netherlands

Email: e.goktas@vu.nl, erik@minemu.org, herbertb@cs.vu.nl, giuffrida@cs.vu.nl† Horst Görtz Institut for IT-Security (HGI), Ruhr-Universität Bochum, Germany
Email: benjamin.kollenda@rub.de, philipp.koppe@rub.de, thorsten.holz@rub.de‡ Department of Computer Science, Stevens Institute of Technology
Email: gportoka@stevens.edu
Abstract—Address-space layout randomization is a wellestablished defense against code-reuse attacks. However, it canbe completely bypassed by just-in-time code-reuse attacks that
rely on information disclosure of code addresses via memory or
side-channel exposure. To address this fundamental weakness,much recent research has focused on detecting and mitigating
information disclosure. The assumption being that if we perfectsuch techniques, we will not only maintain layout secrecy but
also stop code reuse.
In this paper, we demonstrate that an advanced attacker
can mount practical code-reuse attacks even in the complete
absence of information disclosure. To this end, we present
Position-Independent Code-Reuse Attacks, a new class of codereuse attacks relying on the relative rather than absolute
location of code gadgets in memory. By means of memory massaging, the attacker first makes the victim program generate arudimentary ROP payload (for instance, containing code pointers that target instructions “close” to relevant gadgets). Afterwards, the addresses in this payload are patched with small
offsets via relative memory writes. To establish the practicalityof such attacks, we present multiple Position-Independent ROP
exploits against real-world software. After showing that we canbypass ASLR in current systems without requiring information
disclosures, we evaluate the impact of our technique on otherdefenses, such as fine-grained ASLR, multi-variant execution,
execute-only memory and re-randomization. We conclude by
discussing potential mitigations.

1. Introduction
No longer able to execute shellcode directly, today’s exploits depend on reusing code from the original program tobuild a malicious payload. Code-reuse attacks (CRAs) chain
existing code together by positioning the addresses of carefully selected code fragments, called gadgets, in memory. A
hijacked code pointer is used to redirect execution to the firstgadget, which uses one of the prepared address to executethe next gadget through an indirect call, jump, or return
instruction, and so on. Address space layout randomization(ASLR) [1], and newer randomization techniques proposedin literature [2]–[14], mitigate CRAs by introducing uncertainty on the location of gadgets during exploitation.
In response, modern exploits rely primarily on information disclosure vulnerabilities [15], [16] to exfiltrate code
addresses, while other avenues of attack include using sidechannels to reduce entropy [17], [18] and brute-forcing [19].
As a result, some of the most recent proposals have focusedon preventing information disclosures altogether. Examples
include execute-only memory [20]–[25], destructive code
reads [26], [27], and multi-variant execution [28]–[30]. Others have focused on mitigating the effects of leaks throughcontinuous code re-randomization [12], [31]–[36].
With all the recent work on defeating information disclosure, this paper attempts to answer the question: Is it
possible to perform code-reuse attacks even without information disclosure? More specifically, is it possible toconstruct position-independent payloads that are resilient to
ASLR and do not rely on side-channels? The answer, basedon our work, is yes. We show that, while harder, it is inpractice possible to construct payloads without ever learninga single code address—an approach that we term positionindependent code reuse.
In current CRAs, the attacker needs to locate all thecode fragments that will be part of his payload, prepare thepayload in memory, and hijack the control flow to execute
it. Not surprisingly, most advanced defenses today target
the attackers’ ability to locate gadgets. Approaches focusing
on execute-only memory [20]–[25] and destructive code
reads [26], [27] aim to prevent leaking pointers containedin code [15] and the on-the-fly disassembling of code to locate appropriate gadgets [16]. Multi-variant execution [28]–[30] aims to detect pointer leakage, while constant rerandomization [12], [31]–[36] of code aims to limit the “lifespan” of leaked pointers. Fine-grained randomization [7],[23], occurring at the function- or basic block-level, also
aim to limit the usefulness of leaked pointers by introducing more entropy. How would these defenses fare against
position-independent code reuse? We show that approaches
based on execute-only memory, destructive code-reads, andmulti-variant execution would fail to stop it. On the other
hand, improved randomization techniques, even though notbulletproof, fare better at preventing this new type of code
reuse.
The main contribution of this paper is the introductionof a new type of code-reuse attack that does not depend
on information leaks. To define this new attack, we firstchallenge the concept that the attacker needs to explicitly
control a region of memory, where a pre-constructed payload
will be placed. In contrast, we show that careful memory
massaging allows an attacker to make the victim program
generate a rudimentary ROP payload “skeleton” for us. For
instance, we are able to make the program call (and perhaps
return from), a set of functions with return addresses thatremain intact on the stack, possibly in stale function frames.
Second, we utilize partial pointer overwrites to “bump”
the pointers in the massaged area, changing their leastsignificant bits. The partial overwrite enables us to redirect
pointers to gadgets in the vicinity of the previously stored
pointer, leaving the most significant bits untouched, which
are usually the ones that change due to randomization techniques. This technique is inspired by past work on partial
EIP overwrites [37], and notably partial pointer overwrites
appeared in recent attacks in the wild [38].
With these extra degrees of freedom, interesting new
attack possibilities arise. Specifically, if the program generates the code pointers in the ROP chain for us, we do notneed to know the code addresses ourselves—we can just use
them. If not, using partial pointer overwrites we may modify,
say, the least significant byte of a code pointer, and target
gadgets at an offset of up to 256 bytes relative to the indirect
branch’s original target. The resulting payload constitutes a
position-independent ROP attack (PIROP) and works evenin the absence of information disclosure capabilities.
To demonstrate that PIROP works against real-world
applications, we present several proof-of-concept (PoC) attacks that completely bypass ASLR. Specifically, we introduce several PIROP exploits against Asterisk, a popularserver which provides telephone communication services,
and Mozilla Firefox to show the practical viability of the
proposed technique. While these attacks are sophisticatedand may only be available when the right vulnerability ispresent, they demonstrate that information leaks are not an
indispensable component for CRAs against complex applications.
In addition, we evaluate the impact of PIROP on moreadvanced defenses such as fine-grained ASLR, multi-variant
execution, execute-only memory, and re-randomization. We
find that while some can be completely bypassed, others
may still be effective, even if weaker than originally thought.
For instance, our findings indicate that function-level randomization is not very effective against PIROP, unlike basic
block-level randomization.
In summary, our contributions are the following:• We introduce Position-Independent Code-Reuse Attacks, a novel technique that does not require information disclosure to bypass ASLR, ignoring defenses
that focus on code readability and leakage prevention.

We develop several Position-Independent ROP (PIROP)
exploits against both servers (Asterisk) and browsers(Firefox) to demonstrate the practical feasibility of ourtechnique. Recordings of PIROP exploits can be found
at: https://www.vusec.net/projects/pirop.
• We evaluate the expressiveness of PIROP on several
real-world programs and analyze how various CRA
defenses fair against PIROP.
•

2. Technical BackgroundIn this section, we provide background information on
the techniques this research is encompassing.
Code reuse. In the absence of any memory defense
in computer systems in the past, attackers directly injected
shellcode through memory corruption vulnerabilities. With
the widely deployed memory defense Data Execution Prevention (DEP), performing code-reuse attacks became theprominent way for exploiting memory corruption vulnerabilities. Code-reuse attacks allow attackers to achieve thesame goals as with injected shellcode by executing code
chunks already available in the program.
A requirement to achieve these goals is calling functions.
With DEP in place, attackers are still able to call functions
by means of the code-reuse technique called return-intolibc (RILC) [39]. Attackers write the memory address ofthe desired function on the stack along with the required
arguments, and then trigger the execution of this function byletting the program change the control flow to the function
with a return instruction. By preparing multiple RILC callframes on the stack, multiple functions can be chained forexecution.
With the emergence of 64-bit architectures, RILC attacks have become less prominent, given that the calling
conventions on 64-bit architectures is different than in 32bit architectures: to speed up performance, the first few
arguments of functions are transferred through processor
registers instead of the stack memory. Consequently, performing 64-bit RILC attacks is non-trivial because it isdifficult to control the necessary argument registers prior
to the control-flow diversion. Return-Oriented Programming(ROP) [40] can overcome this challenge and has de-facto
replaced RILC in practical attacks.
In ROP, so-called gadgets, small code chunks that end in
return instructions, are chained together to perform a desired
operation. An attacker writes the ROP payload, i.e., code
pointers (gadget addresses) and data operands, in memory
and then tricks the program into considering this payload as
its new stack. The return instructions then consume the code
pointers, and the other instructions in the gadgets consume
the data operands on the stack. The expressive power of ROP
is due to every byte of the original code being targetable.
This enables Turing-complete computations.
In response to several defense techniques, other flavorsof code reuse similar to ROP have evolved. For example, Jump-Oriented Programming (JOP) [41] can be used
to bypass some execution monitoring defenses [42] andCounterfeit Object-Oriented Programming (COOP) [43] canbe used to bypass some Control-Flow Integrity (CFI) [44]defenses. In this paper, we introduce a novel variant ofcode reuse named PIROP that, in turn, seeks to bypass bothrandomization and information disclosure defenses.
Besides the ability to divert the program’s control flow
to the first gadget to start off the chain, attackers today
need two other capabilities. First, to construct the chains,
attackers need control over a region of memory such as
the stack so that they can explicitly store the payload(consisting of code pointers and operands). Second, theyneed to determine the appropriate set of code pointers tostore in this region. Depending on the defenses deployed,
the set may be more or less restricted. For instance, in theabsence of additional measures such as control-flow integrity(CFI) [44], the code pointers may target any byte in the text
segment. CFI, shadow stacks, and similar measures reduce
the set of targetable functions, e.g., to legitimate callsites andfunction entry points. Whatever the available set of targets,the attacks must locate them and place them in the rightlocations—typically the stack.
ASLR.
Address-Space
LayoutRandomization(ASLR) [1] is a lightweight defense against codereuse attacks. The goal is to make the locations of the codegadgets unknown to the attacker. The popular and widely
deployed version of ASLR randomizes the base location ofloaded modules. However, this is vulnerable to information
disclosure, given that a single pointer leak can compromise
the defense [15].
Weaknesses in ASLR motivated the development offiner-grained randomization techniques. Such techniques
typically permute objects in the text segment or randomize
the padding between such objects. Existing permutationbased techniques reorganize individual code pages [3], [6],[9], [14], individual functions [2], [4], [5], [12], [20], [23],or intra-function elements (e.g., basic blocks [8], instructions [7], [10], or data flow [7], [20], [23], [25]). Similarly
existing padding-based techniques typically operate at thefunction level [4], [5], [12] or within individual functions(e.g., randomly padding basic blocks [12], [13], [22], [23],[25], [36] or instructions [10], [11], [45]).
Defenses against information disclosure. Although
ASLR can be bypassed with a single pointer leak, evenfine-grained ASLR techniques are vulnerable to advanced
information disclosure attacks in which attackers can repeatedly leak information at requested locations in memory [16].
To further harden randomization solutions, researchers haveproposed several defenses against advanced information disclosure.
Several Multi-Variant eXecution (MVX) [28]–[30] solutions detect information leaks by comparing execution
results of multiple versions of a running process. Due todifferent randomized address-space layouts of the processes,
the execution observably diverges whenever an attacker
tries to leak information from the memory space. This
strategy is alone insufficient against information disclosureattacks that rely on side channels. However, many MVX
systems also enforce Address Space Partitioning (ASP, or
non-overlapping address spaces) [28], [29], [46]–[50] acrossvariants to ensure that, even if code pointers are somehow
leaked, an attacker cannot rely on such pointers to mountcode reuse without being detected [50].
Execute-only-Memory (XoM) is another defense against
advanced information disclosure. XoM defenses disable theread permissions on the code using either software- [20],[21] or hardware-based [22]–[25] techniques. Similar to
XoM, destructive code read [26], [27] defenses make thecode sections execute-only but at the same time support
reading data that is intermingled with the code, e.g., jump
tables. The key idea is to ensure that every byte readfrom the code sections can no longer be used to execute
instructions.
Another popular approach is to periodically operate rerandomization during the execution. This strategy counters
information disclosure by invalidating all the previously
leaked code pointers. Existing re-randomization solutions
either operate re-randomization at predetermined time intervals [12], [31], [32] or every time particular events markopportunities for attacks (e.g., crashes [33], I/O operations [35], syscalls [36], or control-flow decisions [34]).

3. Bypassing Modern Defenses via PIROPThe defenses discussed in the previous section have one
goal in common: by randomizing the location of code inmemory and preventing information disclosure, they assume
that code-reuse attacks are no longer possible. In the following, we challenge this assumption and demonstrate a
new class of code-reuse attacks named position-independentcode-reuse attacks, which can operate even in complete
absence of information disclosure for both code and data
sections.

3.1. Threat Model
Throughout the rest of this paper, we use the following threat model, similar to the one considered in priorwork [16]:• Data execution prevention: We assume that DEP is inplace, ensuring a memory page can be marked either
writable or executable but not both, a standard technique deployed on most computer systems nowadays.
• Address space layout randomization: We assume that
ASLR is in place, randomizing the base address ofbinary and library images, as well as data memory,
like stack, heap, and other (memory) mapped regions.
Also a standard technique on most computer systems
today.
• Out-of-bounds memory write: We assume that the target
application contains a vulnerability that enables theattacker to corrupt memory by writing outside theboundaries of an existing buffer or object. Specifically,
the vulnerability should allow an attacker to operatea non-linear relative memory write, that is writing at
an attacker-controlled offset from a program pointer.
Multiple vulnerability types can provide such “functionality”, like out-of-bounds accesses on arrays, type

confusion, and use-after-frees (UAF). The vulnerability should also allow writing values smaller than theword size used by the program (e.g., 1 or 2 bytes, oreven just bits). Non-linear memory write bugs can beas simple as the example shown in Listing 1 below
and they have become more common [38], [51], [52]:according to an analysis by Microsoft, about 60% of theheap corruption vulnerabilities detected in the last three
years represent such non-linear vulnerabilities [53].
• Control-flow hijacking: The previous overwrite bug canbe used to corrupt a code pointer and hijack control
flow, as is commonly the case in such attacks.
• Known application: We assume that the attacker hasa copy of the targeted application, but the exact codelayout of the application running at the target is notknown.
Listing 1: Example of small, relative overwrite bug.
/* index is controlled by the attacker */void write_array(char *array, int index, char byte){...
array[index] = byte;...
}

Most importantly, we do not assume a memory disclosure vulnerability that enables an attacker to leak code
pointers, which is a fundamental requirement in existing
attacks [16], [43]. If the attacker can reliably leak code
pointers, all the deployed randomization schemes are nolonger effective. Effectively, we assume an attacker is unable
to exploit disclosed information due to:1) absence of information disclosure vulnerabilities (ideal
case)2) presence of defenses that actively detect information
leaks (e.g., MVX), or3) techniques that mitigate the impact of information disclosure via XoM or destructive code reads, raising thebar against traditional code-reuse attacks.

3.2. Position-independent Code Reuse
A common assumption in the literature is that randomization techniques combined with perfect information
disclosure defenses can stop code-reuse attacks [50]. We
now introduce a new way of performing code-reuse attacks
called Position-Independent Return-Oriented Programming(PIROP) that can bypass these protection mechanisms.
PIROP’s essence is that disclosing information to derandomize the randomization may be unnecessary and a generative approach to code reuse is possible. A PIROP attack
essentially reuses the randomized code pointers produced by
the program without ever leaking them.
A PIROP attack can be conceptually split in four steps.
The first step, and the most crucial one, is stack massaging,which forces the victim program to generate a rudimentary
ROP payload on the stack on the attacker behalf. The second
and third steps rely on a relative memory write primitive

to patch the code pointers and data operands in the ROP
payload (as necessary). The last step is to make the program
execute the prepared ROP payload for actual exploitation.
(i) Stack massaging. In code-reuse attacks, the exploitation payload consists of code pointers and data operands.
Traditionally, an attacker first discloses the code pointers,i.e., locations of the gadgets, and then creates a chain ofthem by carefully placing the code pointers (along with data
operands) in a specific order. Afterwards, the attacker forcesthe victim program to write this entire ROP payload inmemory. Since in our threat model disclosing code pointers
is no longer possible, an attacker can no longer craft a ROP
payload with traditional techniques.
The goal of stack massaging is to overcome the absenceof information disclosure capabilities by forcing the program
to create the intended ROP payload on behalf of the attacker.
By carefully making the program process certain attackercontrolled inputs, she can massage the stack and have theprogram itself place the desired (randomized) code pointersand data operands into the right position in memory.
While the proposed technique could be, in principle,
generalized to arbitrary memory massaging and code-reuseattacks, the stack is an ideal means to lure the program
into generating a code-reuse payload for us, since programs
already continuously and nearly contiguously place code
pointers (i.e., return addresses) on the stack. At every function call, the return address is pushed on the stack andsome temporary space is also reserved for the variables of
the called function. The more nested and recursive function
calls are made, the more code pointers are active on thestack. Once the program returns from these functions, thecode pointers will be left stale on the stack. Subsequently,
the program can be stimulated to produce code pointers on
the stack again with a different input to the program. An
interesting point to note for the stack is that reserved variablelocations are not always initialized and used, which means
that, if surgically placed code pointers can survive multiple
stack massaging steps (i.e., not overwritten in subsequent
program inputs), the stack will contain a collection of code
pointers from different attacker-controlled code paths. In
other words, the stack will contain an attacker-controlled
ROP payload written in memory without disclosing any
information.
During the stack massaging step, the attacker first determines which code pointers and data can be massaged on
the stack by executing the vulnerable input and variations.
The objective is to find massageable code pointers that can
provide gadgets with critical operations such as executing
system calls and stack pivoting. Next, the attacker seeks
to align the code pointers and data on the stack such thatthese can be patched where necessary. To find suitablealignments, the attacker needs to find inputs that provide
fine-grained control over the callstack layout. To reducethe input-exploration space, the attacker can use simple
heuristics, such as focusing on input-controlled recursivefunctions, input-controlled allocas, input-controlled JITted stack frames, or simply locating different inputs thatyield different callstack depths. To craft our exploits, weused such heuristics to aid our manual analysis, but theapproach could be automated to reduce the exploitation
effort. We leave fully automatic PIROP exploit generation
as future work.
(ii) Code pointer patching. The code pointers in thegenerated ROP payload in memory point each to executablecode gadgets. In an ideal case, the gadgets in the ROP
payload may be usable as is in the exploit. Although thisis perhaps rare in practice, in such a case the code pointers
can be left unpatched to mount a patchless PIROP exploit.
The code pointers can also be left unpatched when thecorresponding gadgets are neither harmful nor functional inwhich case they will just behave as no-operation gadgets.
However, sometimes the code pointers may be harmful(i.e., it can hinder the exploitation) or the exploitation may
require a certain operation that is not easily available in thecode gadgets reachable from the massaged code pointers. To
resolve these issues, code pointers can be patched in placein the ROP payload to point to different code locations. If
we only patch a few selected bits in the code pointers using
a relative memory write primitive (e.g., a non-linear buffer
overflow [54]), we can redirect each patched pointer to alocation relative to the original target. This is to ensure
the ROP payload remains randomization-agnostic, while
expanding the gadget set at our disposal.
The extent to which we can expand the gadget set
depends on the capabilities of the relative memory write
primitive and on those of the underlying randomization andinformation disclosure defenses. For example, a memory
write primitive that can overwrite a memory location after
every N bytes is not useful if the writable bytes do not
overlap with the actual bytes that we seek to overwrite. A
non-linear memory corruption primitive that can increment
or decrement massaged code pointers with specific offsets
would be the ideal case, but, in practice, as we will show,
the ability to overwrite single bytes or bits is sufficient forour purposes.
The level of randomization defines to what degree wecan patch the code pointers. For performance reasons, randomization techniques generally provide no or very little
entropy in the least significant bits of code pointers. Hence,
we can simply focus code pointer patching on these bits
to expand our gadget set. The number of reachable code
locations directly depends on the number of low-order bits
without entropy, as dictated by the randomization granularity.
As an example, assume a randomization technique thatleaves the 8 least significant bits of code pointers nonrandomized. We also assume that the attacker knows towhich code offset in the corresponding module, i.e., executable or library, the code pointers belong, because she
can control the input to the program and knows when andwhere the corresponding code pointers of the code offsets
are produced. Given a target code pointer, for example
0x..7400, the attacker can rely on a relative memory write
primitive to patch this code pointer to any value between
0x..7400 and 0x..74FF. If the primitive is only limited
to setting the least significant 2 bits to 1, an attacker can

only round up the code pointer to one where both bits are
set to 1.
(iii) Operand patching. As in a traditional ROP attack,the code gadgets executed in the exploitation step operateon data that is carefully prepared in the ROP payload. Thisdata is intermingled in the payload with the code pointers.
Note that when the stack is being massaged, the payload
area between the code pointers will be filled up with data.
In the best case for an attacker, she can set this data directly
by controlling the input to the program. If setting the dataaccordingly is not possible or the payload also contains
randomized data pointers that need patching, she can use
a memory write primitive to set up the data.
As observed earlier, the weaker the memory write primitive, the more difficult the exploitation. That is, a weakerwrite primitive might require executing more gadgets justto get the right data, which will also require setting up alarger ROP payload with more gadgets. Fortunately, sincea program execution continuously operates on pointer andnon-pointer data, reusable data operands are also often foundon the stack.
(iv) ROP payload execution. Once the fully prepared
ROP payload is in place, the program’s execution has tobe directed to it to finalize the exploit. Altering the normal
execution of a program is done by changing the target of an
indirect branch instruction, which can be a call*, a jmp*
or a ret instruction. An attacker has to lure the program
into feeding an unexpected target to one of these instructions
to divert the control flow. This can be also done through aposition-independent memory corruption vulnerability.
For example, to alter the target of a call* or jmp*
instruction, a use-after-free vulnerability can be used inabsence of information disclosure. If the set of targets thatcan be fed to these indirect instructions is not satisfying,i.e., does not change the control flow accordingly, a relative
memory write primitive could be used to further alter thetargets and alter the control flow as intended.
In contrast, altering the target of a ret instruction has tobe done on the stack, where the targets of such instructions(i.e., return addresses) are located. For example, an attacker
can overwrite the least significant byte of a return addresson the stack using a stack-based buffer overflow to start off
the ROP chain and finalize the exploit.

4. Proof-of-Concept Attacks
In this section, we validate PIROP by describing several
proof-of-concept attacks on Asterisk, a popular server for
telephony communication, and on Mozilla Firefox. Moreover, we argue that attacks in the wild are moving towards adopting a similar (albeit less general) approach—for instance, Chris Evans’ attack on the FLIC gstreamer
decoder [38]. Collectively, they show that PIROP (1) enables
different types of exploitation, (2) requires a small set ofgadgets, and (3) can be applied to different real-world
applications, both clients and servers, and different defenses.
We initially present all our position-independent attacks
assuming ASLR or other page-granular randomization vari-ants [9]. In other words, the content of a page is always
the same, no matter where the module is in memory andthe 12 least significant bits are fixed. Thus, when we know
one code pointer, we may look for suitable gadgets close
to it—subject to the restrictions that apply to the available
memory write primitive. In later sections, we will revisit
this assumption and evaluate the effectiveness of our PIROP
attacks against finer-grained ASLR techniques.

4.1. Attacks on the Asterisk Server
The first case study targets version v1.8.10.1 of Asterisk
and CVE-2012-5976 [52] on 64-bit Ubuntu 12.04 LTS.
Vulnerability. The vulnerability allows an attacker tocontrol the size parameter of an alloca function callthrough the Content-length header field in an HTTP request
to the manager on the server. Without further bounds checking, the server subtracts this size from the stack pointer bymeans of alloca. Asterisk handles every HTTP request
with a new thread with its own stack and providing a size
larger than 0x7c000 (Asterisk’s default stacksize on 64bit architectures1 ) allows the attacker to target the stack ofanother thread. An example of the request is:
POST /asterisk/manager HTTP/1.0
Host: asterisk.example.com
Content-length: 507916<-- large value

The server will write this sentence in thememory region allocated with the alloca() function.

We use this vulnerability both for stack massaging,and for a byte-level write primitive for the stack. Stackmassaging occurs when we provide multiple requests withdifferent content-length fields to make the program fill thestack with code pointers in the form of return addresses atdifferent offsets. We obtain our write primitive similarly, by
providing content which the server subsequently stores in
the allocated memory at a desired offset.
4.1.1. Launching a shell with PIROP gadgets. In thefirst exploit, we launch a shell on the server, from a client
connected via the network, using only PIROP gadgets. Later,
we will show an alternative attack that does code injection
and requires fewer unique code pointers to be patched.
Stack massaging. To massage the stack and populate
it with code pointers, we repeatedly trigger the alloca
vulnerability while feeding it different sizes through theContent-length field of multiple requests. By subtracting thestack pointer with the given size, alloca creates a stackbuffer to contain the request’s content data. Subsequently,
the program processes the remaining parts of the request
which includes calling several functions. These function
calls spill return addresses at the adjusted stack pointer.
Depending on whether the request carries data, the return
addresses differ. Specifically, in the absence of data, theprogram spills 6 return addresses, and 3 return addresses
otherwise.
1. or 0x3c000 on 32-bit architectures

To exploit the system, we patch the return addresses tomake them point to interesting gadgets at a relative offset‘close’ to the original address. Specifically, since the 12 leastsignificant bits do not vary under page-level randomization,
we can patch them in any way we see fit. We therefore
use the byte-level write primitive to overwrite the leastsignificant byte of a return address. The primitive does not
permit us to overwrite the second byte, because 4 of its
bits are randomized. The obvious question is whether theremaining set of gadgets is sufficient for attackers.
To answer this question, we perform gadget analysis on
the available code pointers. To minimize side effects andother complexity, we restrict our gadgets to at most 15
instructions that may however include conditional jumps.
Since the patch ranges are small, we consider call instructions also as valid instructions in gadgets as long as theycall functions that are leaf nodes, i.e. functions calling not
any other function, to further increase the gadget space. We
call such call instructions leaf calls.
Launching a shell is only possible if we have gadgets
that can execute a program (so we can start /bin/sh to
begin with), and also gadgets that can prepare the arguments.
For the former, we found a syscall gadget that we use to
execute a dup2 system call and an execve system call,while for the latter we found a pair of gadgets to move avalue from the stack into rax (which contains the syscall
number) in two steps, and also simple gadgets that pop rdi
and rsi (the first and second arguments) from the stack.
We set the third argument rdx, required by the execve
system call, to 0 by moving the return value of the call todup2 (which gets stored in rax) into rdx.
We use the dup2 system call to duplicate a socket filedescriptor into the standard input file descriptor of Asterisk
for ensuring that the shell can receive commands through the
network. Initially, Asterisk’s standard input and output are
set to /dev/null. Since execve preserves these, without
dup2, the launched shell would have no way to get input
and would exit. Because the file descriptor numbers are
unknown, we first saturate the connection limit of Asterisk
so that we can randomly pick a socket file descriptor number
and later probe for the connection that feeds input to theshell. The complete exploit uses a total of 1 non-patched and24 patched code pointers (gadgets), for which we massaged
the stack by means of 9 manipulated calls to alloca. 3
patched code pointers lead to gadgets with a leaf call.
Code pointer patching. After making the program spill
the code pointers on the stack, we patch their least significant bytes so they will point to the picked gadgets at a small
offset from the original addresses. However, our byte-level
write primitive is contiguous and if we patch a code pointer,everything preceding it will be overwritten, including theother code pointers.
To remedy the problem, we create a memory write primitive that resembles a non-linear memory write primitive—
capable of writing at any desired offset in an area of code
pointers without spoiling any of the others. By sending thecontent data of the request byte-by-byte over the network,
we can essentially pause any time without tearing down theconnection. When we continue to send the data, Asterisk
continues writing at the paused offset within the allocatedbuffer. We achieve the desired memory write primitive as
follows: (1) we create a connection Cx , which causes Asterisk to allocate a new thread Tx with a fresh stack Sx ;(2) we repeat the process and create a second connection
Cy , which causes a fresh thread stack Sy to be allocatedlower than stack Sx in the address space; (3) through Cx ,we send an incomplete request that triggers the alloca
vulnerability to make Tx ’s stack pointer point into stack Sy
and writes the partial content data into the allocated buffer;(4) we massage our rudimentary ROP payload on stack Sy ;(5) finally, we send the remaining data of the delayed request
to overwrite the data within the rudimentary ROP payload.
By controlling the size of the content data partially sent with
the incomplete request, we can control the offset at which
the remaining data gets written within the payload. To affectmultiple distinct offsets, we send multiple partial requests
over different connections.
Operand patching. Another important step in PIROP is
the patching of the data operands consumed by the gadgets.
We use the memory write primitive as we did for code
pointer patching and patch up the arguments of the dup2
system call to small file descriptor numbers and the second
argument of the execve system call to 0 (NULL). We set
the third argument of execve through the return value of
dup2, which is 0.
The more challenging part is setting the first argumentof execve, which should be a pointer to the program
name string "/bin/sh". We can write the string with thewrite primitive. However, we cannot write the string pointer,
since we do not know its memory address. Fortunately,
during memory massaging, the program also spills heapand stack pointers on the stack including a stack pointerto the alloca-allocated buffer, which we can use for our
purposes. We preserve this buffer pointer by ensuring thatit aligns with unused gaps in subsequent massaging steps.
ROP payload execution. To execute the ROP payload
the stack pointer has to point to the first gadget. We ensurethat a thread’s stack pointer points to the first gadget by massaging and patching the payload on this particular thread.
This thread belongs to a connection that is waiting for its
first request. After the ROP payload has been finalized on
this thread’s stack, sending its awaited first request starts off
the gadget chain because the payload is aligned such thatits first gadget is at the thread’s stack pointer.
4.1.2. Minimizing pointer patching. To show the effectiveness of PIROP on stronger defenses than page-granularrandomization, we showcase another attack on Asterisk witheven more restrictions. Specifically, we restrict our pointerpatching strategy to (i) minimize the number of patchedgadgets and (ii) ensure each patched gadget always remains
in the same function as the original code pointer spilled on
the stack by the program. This is to showcase how PIROP
fares against fine-grained, function-level randomization. Under these restrictions, we demonstrate a more advanced
exploit on Asterisk in which we perform code injection,

disable the DEP protection through the mprotect systemcall, and execute the shellcode. Like in the previous attack,the shellcode starts a shell through execve and dup2.
The exploit first makes the heap readable, writable andexecutable, and then copies the shellcode in chunks to the
executable heap. Like in the previous attack, we also utilize
the unused gaps and the constructed memory write primitive
to patch the code pointers and data operands. We also
apply the same technique for control-flow hijacking. In this
exploit, we used 16 iterations for the massaging and just
5 different original code pointers, two of which did not
require any modifications whatsoever and could be used ina patchless fashion in the final ROP payload. Eventually, weused 21 non-patched and 14 patched code pointers (gadgets)in this attack, in which 1 patched code pointer led to a gadgetwith a leaf call. We also noticed a number of other patchlessgadgets available on the stack that point to PLT stubs in glibc(e.g., free), which suggests that a fully patchless exploit
with less ambitious goals (e.g., injecting a use-after-freevulnerability in the program) may be also possible.

4.2. Attacks on Firefox
To substantiate our approach, we also show that othertypes of programs such as browsers are vulnerable to
PIROP. For this demonstration, we adopt a vulnerability
similar to CVE-2016-1977 [51] into Mozilla Firefox 50.0.1,
which allows a stack-based out-of-bound bit set. In theoriginal vulnerability the bit set is limited to a range of
256 byte. For our proof-of-concept exploit we only extended
the reachable memory region not to require additional effort
to further escalate the relative write primitive. While notas unrestrained as the vulnerability used in Asterisk, thevulnerability still allows an attacker to patch pointers andoperands in the ROP payload and can also effect patching
writes at the bit granularity.
Vulnerability. The vulnerability does not reside in acomponent exclusive to Firefox, but instead is located inside
the font library Graphite2 [55] which is used to rendercomplex smart fonts. A key feature of Graphite2 is allowing fonts to define special handling for rendering complex
glyphs. To enable this feature, it is possible to embed abasic script in the form of bytecode into the font, which isinterpreted at runtime. The corresponding scripting language
is called Graphite Description Language (GDL) [56]. The
features of GDL allow for example exchanging glyphs forother glyphs of the same font or combining parts of them.
Commonly this is used to represent complex combinationsof characters that would otherwise require an individual
glyph for every combination. Providing a smart font rendering allows supporting a large variety of complex writing
systems.
The GDL is compiled to bytecode and embedded into
the font by the Graphite2 tool chain. When such a fontis loaded, it is passed as a buffer to the library which
processes it and allows characters to be rendered with itafterwards. The interpretation is performed by a stack-based
VM included with the Graphite2 library. During the initialprocessing, different checks are performed to ensure thevalidity of the bytecode. One of these checks calls the
Machine::Code::decoder::analysis::set_ref
function which does not properly check the bounds of abuffer. As this buffer is allocated on the stack, this provides
us with a basic relative memory write primitive. However,as the code only allows flags to be set and not cleared, weare also limited to setting bits in the target byte. This is
still enough to change the target of a return address on thestack. Also it allows us to change individual bits instead ofa whole byte when compared to the Asterisk vulnerability,
giving us more precise control to bypass more fine-grained
randomization defenses.
Stack massaging. In contrast to the Asterisk exploit, we
do not possess the ability to extend the stack by an arbitrary
length using alloca. Therefore we cannot bridge the gap
to other thread’s stacks and change values in them. Thus, ourpatching and execution steps must happen within the samestack. Also the stack-relative bit set is limited to writing after
the stack-allocated array. This still allows targeting return
addresses in stack frames generated earlier in the call chain.
Hence, we can leverage return addresses of any functions
that lead to the execution of the vulnerability. In addition,
the design of the Firefox JavaScript engines gives us agreat amount of flexibility: we can place a wide variety ofdifferent return addresses on the stack if we direct JavaScript
execution along different paths we control. For this purpose,
we used detours such as the eval function and JavaScript
callbacks. Furthermore, the JavaScript engine reuses thenative CPU stack to implement the JavaScript stack. Thismeans that, whenever we trigger a call in JavaScript, a return
address to the appropriate interpreter entry point is placed on
the stack. If JIT-compiled code is used, this return address
is replaced by the actual address of the generated code
triggering the font load. We can use this property to create
recursive code that places a high number of return addresseson the stack. Notably, we can achieve full stack massaging
capabilities, as we have precise control over the offsets
between the return addresses on the stack. In particular, we
can add multiples of the native word width by leveraging
the JavaScript call stack and passing as many arguments as
we need to self-controlled JavaScript functions.
Code pointer patching. Once we have forced thebrowser to place the necessary code pointers at the rightlocations in the stack, we patch the resulting ROP payload
as necessary. For this purpose, we force the load of a
specifically crafted font. During the loading of the font,
the vulnerable function will be executed and set the bits
we indirectly specify via the embedded GDL. It should
be noted that we are not limited to a single write. The
GDL environment allows us to perform multiple patching
operations during a single font loading. Using this method,
we can patch as many return addresses as needed and thus
construct more complex gadget chains.
Argument preparation. The next step is to patch theactual operands passed to the gadgets. One possibility is topatch existing data already spilled in the ROP payload. However, as we can control arguments being placed on the native

stack from JavaScript, we can place the correct operands
ourselves. The number of arguments that are passed to afunction in JavaScript are placed on the native stack indouble-precision floating-point format of 64-bit length. We
inverted the encoding in order to place arbitrary values on
the native stack. It should be noted that there are someminor limitations, i.e., we cannot write every number due
to floating point error handling. We use this mechanism toplace immediate operands on the stack that are consumed
by our gadgets, and most importantly, we use it to prepare
the required function arguments. To support data pointeroperands, we can patch existing (randomized) data pointers
spilled on the stack by following the same strategy adopted
for code pointers.
ROP payload execution. After finalizing the stack withthe gadget addresses and the corresponding operands, we
can trigger the chain by simply letting the font loading
return as normal—assuming the font loading succeeds. We
then return from our JavaScript function. Thus, the stack
deconstructs until it reaches the first return address wetampered with, which redirects control to our ROP chain.
Initially, we compute the location of our argument string on
the stack. We achieve this by leveraging multiple gadgets
that add the correct offset to a register, which coincidentallycontains a close stack address. We then transfer this value tordx and use another gadget to place the syscall number ofthe system function in rax. Finally, we use a syscall gadget
to invoke the system function. It should be noted that we
can easily prepare long strings in order to execute arbitrary
command payloads on the target machine.

5. Evaluation
To demonstrate the expressiveness of PIROP, we evaluate the availability of gadgets in Asterisk 1.8.10.1, Apache
2.4.25, Nginx 1.20.2, Lighttpd 1.4.45 and Firefox 50.0.1.
For the gadget analysis, we extended the Ropper [57]multi- architecture gadget analysis tool to support a userdefined, initial address set and recursive disassembly. This
enables us to search and utilize novel gadget types containing direct unconditional and conditional branches as well as
direct calls to leaf functions, e.g. functions without calls.
We collect the potentially targetable code locations inthe servers by running their test suites and tracing theservers’ execution with the GDB debugger. Every time a
new request arrives, we store a snapshot of the stack. Next,
we clear the lower part of the stack by writing dummy
values. Dummy values help us identify unused locations,
i.e., gaps on the stack. As explained previously, gaps arevaluable for stack massaging, because we can fill themwith code or data pointers using other requests. For every
instance of the server, we also store a snapshot of the loaded
libraries. For Firefox we use a similar method, but limit
our analysis for simplicity on callstacks that are directly
related to the vulnerability we use in our exploit. We breakon every execution of the vulnerable font loading function
and save the callstack leading to its execution. By modifying
the JavaScript code leading up to the font load we createddifferent paths resulting in a bigger set of potential gadgets.
Unlike in the proof-of-concept Firefox exploit, we are notaiming to get specific gadgets in the JIT-compiled code
during this process. Finally, we combine the snapshots ofthe stacks with the loaded libraries and perform the gadget
analysis with the extended Ropper tool. Table 1, shows thenumber of stack dumps processed.
Application
Asterisk 1.8.10.1
Httpd 2.4.25
Nginx 1.20.2
Lighttpd 1.4.45
Firefox 50.0.1#Stack dumps
131
216
507
208
47

TABLE 1: Analyzed stack dumps for the applications considered.

Category
Stack Pivot (SP)Load Mem (LM)Write Mem (WM)
Load Reg (LR)
Clear Reg (CR)Inc Reg (IR)Sub Reg (SR)
Add Reg (AR)Xchg Reg (XR)
Invert Reg (NR)
Syscall (S)Gadget lengths. Subject to the level of randomization,
PIROP patches the code pointers spilled by the program tomake them point to the gadget at a relative offset from theoriginal address. In Fig 1a and 1b, we show the numberof gadgets available, with different lengths, respectively,
when an attacker has a byte level memory write primitive
as in the Asterisk exploit or a 4-bit memory write primitive
as in the Firefox exploit. We define gadget length as thenumber of instructions in the gadget. In the proof-of-concept
exploits, while the smaller gadgets enabled popping values
into registers from the stack, the longer gadgets enabled operations like mathematical computations and memory loads
by dereferencing registers.
The results show that there is an abundance of gadgets
available in every gadget length bucket in all evaluated applications. Although gadgets with 0 leaf calls are dominating
the numbers, there are still many gadgets with 1 leaf callbut significantly less than gadgets with 0 leaf calls. Amongthe gadgets reachable with the byte level memory write
primitive, we also found gadgets with 2 and 3 leaf calls,
but there were few of them, namely in total 11 gadgets had
2 leaf calls in the gadget length buckets from 13 to 15 of
Nginx and 1 gadget had 3 leaf calls in the gadget length
bucket 15 of Nginx. Among the gadgets reachable with the
4-bit memory write primitive, we found no gadget that has
2 or more leaf calls. In Firefox we had not found any gadgetwith 1 or more leaf calls, which we believe is due to Firefox
being a much more complex application and for being a C++
application with many indirect virtual calls. Finally, we notethat the number of gadgets reachable with the byte level
memory write primitive is an order of magnitude more thanthe ones reachable with the 4-bit memory write primitive.
Gadget semantics. To successfully perform a codereuse attack, one will need gadgets with the desired functionalities. Table 2 classifies the gadgets according to theirsemantics, based on their instructions. This group of semantics are used by Ropper. We further extended this groupby adding the instructions not reg and syscall to thecorresponding categories. During the analysis we assign
categories to the found gadgets. In Fig 2a and 2b, werespectively show the number of gadgets, that are reachable

Instructions (Intel syntax)
sub rsp, num
add rsp, num
mov rsp, mem
mov rsp, reg
xchg reg/mem, rsp
add rsp, num
ret num
mov reg, mem
mov mem, reg
pop reg
xor reg, reg
add reg, 1
inc reg
sub reg, reg
add reg, reg
xchg reg, reg
neg reg
not reg
int 0x80
syscall

TABLE 2: Instructions used to assign categories to gadgets.
by patching a byte or 4-bits in the code pointers, in eachcategory.
To perform critical operations on the system, gadgets
with syscall instructions are crucial to have at reach. Furthermore the availability of a syscall gadget can dictate whether
a successful exploit might be possible or not. Among thegadgets reachable by patching a byte, the number of gadgets
with syscalls ranges from 748 in Asterisk to 46 in Firefox.
Among the gadgets reachable by patching 4 bits, the numberof gadgets with syscalls for the applications Asterisk, Nginx
and Lighttpd is respectively 24, 12, and 16. The code
pointers in the collected stack dumps for Apache and Firefox
did not provide a gadget when patching 4 bits in the code
pointers. In such a case, an attacker can opt for expanding
the patching capabilities with the already reachable gadgets
by emulating a write primitive that can patch more bits ofthe code pointers.
Although memory operating instructions are much moreprevalent than data computing instructions, the overall results indicate that the expressiveness is good enough withthe amount of gadgets available in the categories.
Effectiveness against Defenses. Table 3 shows theeffectiveness of PIROP against ASLR techniques throughentropy numbers calculated for our different PIROP exploits
on Asterisk (AST1, AST2) and Firefox. The entropy of each
exploit provides a measure of its exploitation probability
across different randomization techniques and is computedby summing up the entropy of its individual gadgets. The
entropy of a gadget is computed by taking the log withbase 2 of the gadget’s number of possible configurations.
For each randomization technique, the entropy numbers arecomputed without taking into account the effect of any otherrandomization technique to assess the effect of the individual
techniques on the exploits.
In the single random base, module-level and page-level
randomization techniques, the code is page-aligned whichmeans that, regardless of where the code is mapped, theFrequency

Distribution of Gadget Length
3000
2500
2000
1500
1000
500
0

1 LC
0 LC

ApacheNginx
Lighttpd
Gadget Length and Application (total #gadgets)

15 (1528)
14 (822)
13 (870)
12 (951)
11 (1002)
10 (1022)
9 (955)8 (949)7 (877)6 (846)5 (869)4 (870)3 (906)
2 (898)15 (790)
14 (399)
13 (422)
12 (443)
11 (445)
10 (447)
9 (402)8 (355)7 (330)6 (334)5 (359)4 (353)3 (341)
2 (347)15 (2856)
14 (1603)
13 (1654)
12 (1646)
11 (1741)
10 (1784)
9 (1569)
8 (1583)
7 (1395)
6 (1296)
5 (1229)
4 (1162)
3 (1260)
2 (1354)

15 (1338)
14 (605)
13 (654)
12 (706)
11 (704)
10 (711)9 (670)8 (645)7 (673)6 (730)5 (766)4 (810)3 (916)2 (803)15 (2279)
14 (1183)
13 (1182)
12 (1184)
11 (1131)
10 (1118)
9 (1120)
8 (1064)
7 (1074)
6 (1022)
5 (1060)
4 (1040)
3 (997)
2 (965)AsteriskFirefox(a) Gadgets with 8-bits patched code pointers.

Distribution of Gadget Length
300

1 LC
0 LC

Frequency

250
200
150
100
50
0

ApacheNginx
Lighttpd
Gadget Length and Application (total #gadgets)

15 (119)
14 (74)13 (94)12 (104)
11 (113)
10 (108)
9 (99)
8 (110)7 (100)6 (95)
5 (88)
4 (86)
3 (72)
2 (62)

15 (83)14 (47)13 (57)
12 (62)
11 (47)
10 (48)9 (50)
8 (40)
7 (29)
6 (35)
5 (45)
4 (31)
3 (17)
2 (15)

15 (283)
14 (196)
13 (220)
12 (193)
11 (193)
10 (184)
9 (160)8 (153)7 (162)6 (149)5 (127)4 (96)
3 (101)2 (122)15 (113)
14 (47)
13 (64)12 (91)
11 (69)10 (60)9 (59)
8 (71)
7 (74)
6 (76)
5 (69)
4 (72)
3 (91)
2 (87)

15 (198)
14 (143)
13 (168)
12 (173)
11 (170)
10 (160)
9 (145)8 (137)7 (110)6 (94)
5 (112)4 (87)
3 (83)
2 (89)

AsteriskFirefox(b) Gadgets with 4-bits patched code pointers.

Figure 1: Number of gadgets available in applications for different gadget lengths, split by the number of leaf calls (LCs).
The number in parentheses indicates the total number of gadgets for each bar.
least significant 12 bits in all code addresses are fixed inevery randomization iteration. Because the PIROP exploits
operate on the portion of these 12 non-randomized bits, theentropy for these exploits is 0, making these randomization
techniques completely ineffective against PIROP.
For the function-level randomization technique, sincecompilers tend to align functions to 16-byte aligned boundaries2 . , the least significant 4 bits of each code address
remain non-randomized. With a byte write primitive, eachpatched gadget of our Asterisk exploits, which is always
in the same function as the original gadget, has an entropyof 4 bits. Since we patch 6 different code pointers to get
the gadgets in the process creation Asterisk exploit and 3
different code pointers in the code injection exploit, theaccumulated entropies are respectively 24 bits and 12 bits.
2. Since instruction fetch units commonly operate on 16-byte aligned
blocks [58], compilers tend to align branch targets like function and loop
entry points to 16 bytes for optimization purposes.

In the Firefox exploit, the 4-bit write primitive operates on
the non-randomized least significant 4 bits of code pointers.
For this reason, the entropy for each gadget (and thus
for the resulting exploit) is 0. This shows that functionlevel randomization can be significantly weakened or madecompletely ineffective by PIROP.
Similar to function-level randomization, for basic blocklevel randomization, the entropy of each gadget is also givenby the number of patch values that are valid in at least oneof all the possible randomization iterations. Conservatively
assuming that basic blocks have no alignment when randomized, all possible patch values are valid when patchingcode pointers to get to the gadgets. Since we patch the lastbyte in the Asterisk exploits and the basic blocks have noalignment, the entropy for a single basic block is 8 bits.
In the process creation Asterisk exploit we retrieve gadgets
from 6 different basic blocks and in the code injection
exploit from 3 different basic blocks, which translate to theFrequency

Available Gadgets in the Functional Categories
1 LC
0 LC

1000
800
600
400
200
0

ApacheNginx
Lighttpd
Gadget Category and Application (total #gadgets)

S (46)NR (156)
XR (114)
AR (344)
SR (234)
IR (413)
CR (1743)
LR (10534)
WM (929)
LM (633)
SP (299)

S (147)NR (244)
XR (42)
AR (107)SR (205)
IR (106)
CR (1077)
LR (4359)
WM (277)
LM (200)
SP (166)

S (135)NR (270)
XR (222)
AR (255)
SR (463)
IR (260)
CR (1378)
LR (17195)
WM (758)
LM (535)
SP (770)

S (292)NR (532)
XR (54)
AR (309)SR (247)
IR (65)
CR (1357)
LR (5695)
WM (606)
LM (468)
SP (457)

S (748)NR (359)
XR (131)
AR (209)SR (834)
IR (527)
CR (2136)
LR (8143)
WM (467)
LM (631)
SP (398)

AsteriskFirefox(a) Gadgets with 8-bits patched code pointers.

Available Gadgets in the Functional Categories
1 LC
0 LC

Frequency

100
80
60
40
20
0

ApacheNginx
Lighttpd
Gadget Category and Application (total #gadgets)

S (0)NR (6)XR (11)
AR (33)SR (16)
IR (22)
CR (131)
LR (1172)
WM (62)LM (59)SP (24)S (16)NR (16)
XR (3)
AR (8)SR (14)
IR (8)CR (89)LR (548)
WM (13)
LM (35)
SP (5)S (12)NR (24)
XR (12)
AR (16)SR (17)
IR (11)CR (81)
LR (2079)
WM (25)
LM (35)
SP (48)S (0)NR (38)
XR (1)
AR (14)SR (29)IR (8)CR (99)LR (545)
WM (41)
LM (47)
SP (37)

S (24)NR (22)
XR (31)
AR (24)
SR (70)IR (51)
CR (213)LR (1023)
WM (31)LM (50)SP (44)AsteriskFirefox(b) Gadgets with 4-bits patched code pointers.

Figure 2: Number of gadgets, split by the number of leaf calls (LCs), that are assigned a certain category. The mapping of
the abbreviated category is depicted in Table 2. The numbers in parentheses depict the total number of gadgets covered in
the stacked bars.
entropy number 48 bits for the former exploit and 24 bits
for the latter. However, in practice, the entropy is lower,
because functions with a small number of basic blocks havea few basic block permutations and thus a lower entropy.
This is reflected in the final numbers reported in Table 3.
The Firefox exploit leverages gadgets from 6 different basic
blocks and modifies up to 4 bits of a given return addresses,
which gives an entropy of 24 bits with 4 bits of entropy
for each basic block. However, on average we patch only
2.33 out of 4 bits decreasing the actual entropy to 14.00.
The functions contain a sufficiently large number of basic
blocks to not further reduce the entropy. Based on theseresults, it can be noted that basic block-level randomization
makes successful PIROP exploitation much harder.
For callee-saved register stack slot randomization, theentropy of each gadget is determined by the number of
permutations of the effectively used register restoring in-structions. In the process creation Asterisk exploit, we use 3function epilogues, yielding a total entropy number of about
10.08 bits. Although in the code injection exploit against
Asterisk we also use 3 function epilogues, the total entropy
is about 10.49 bits due to the usage of a different numberof register restoring instructions in different epilogues. The
Firefox exploit does not utilize whole function epilogues andinstead only relies on smaller gadgets. Thus, the number ofactually used register restoring instructions is lower. In total
2 gadgets contain such instructions resulting in an entropyof 7.75 bits. These numbers indicate that callee-saved register stack slot randomization has an impact, but provides
insufficient entropy against PIROP to deter practical attacks.
For callee-saved register allocation randomization, theentropy per gadget is the number of permutations of theeffectively used callee-saved registers in the gadget. Since
overlapping gadgets share the degree of randomness, weCode Randomization
Techniques
Single random base [1]Module-level [6], [14]Page-level [3], [9]Function-level [2], [4]–[6], [12], [20], [23]Basic block-level [3], [8], [9]Callee-saved register stack slots [7], [10], [13], [23]Callee-saved register allocation [7], [20], [23], [25], [45]
Defenses against information disclosures
MVX [28]–[30], [46]–[50]XoM [20]–[25]Destructive code reads [26], [27]Re-randomization [12], [31]–[36]Entropy PIROP Exploits
AST1
AST2
FF
0
0
0
0
0
0
0
0
0
24
12
0
31.64
20.64
14.00
10.08
10.49
7.75
5.17
12.08
7.49

Bypassed(byte-level write)

•
•
•
◦
◦
◦
◦
•
•
•
•

Bypassed(bit-level write)

•
•
•
•
◦
◦
◦
•
•
•
•

Comments

Functions 4-bit aligned

Requires live pointers

TABLE 3: Effectiveness of PIROP against state-of-the-art code randomization and information disclosure defense techniques,
including the entropy in the exploits under different code randomization techniques. Note that our analysis refers to theindividual defense techniques rather than full existing solutions (◦=‘severely weakened’, •=‘completely bypassed’)consider the longest gadget among them. In the processcreation Asterisk exploit, we effectively use 2 callee-saved
registers in two different gadgets. Since there are 6 possible
callee-saved registers, the entropy for this exploit is 5.17
bits (i.e. log2 (6 ∗ 6)). In the code injection Asterisk exploit,
we have 3 different gadgets in which we, respectively,
effectively use 3, 1 and 1 callee-saved registers. This gives
an entropy of 12.08 bits. In the Firefox exploit 2 gadgets
use 2 and 1 callee-saved registers, respectively, which results
in an entropy of 7.49 bits. Again, these numbers indicatethat callee-saved register allocation randomization, while
effective, provides insufficient entropy against PIROP todeter practical attacks.
Moreover, PIROP also bypasses all defenses against
information disclosure listed in Table 3. MVX [28]–[30],[46]–[50] can detect deviant behavior when randomized
pointers are directly leaked or leaked pointers are used
for exploitation. With PIROP, the attack is fully positionindependent, that is requires no disclosure and no attackerprovided pointers (only offsets), thus the absolute addresses
are no longer relevant. Moreover, since PIROP never reads
the code, XoM [20]–[25] and destructive code reads [26],[27] are equally powerless. Finally, PIROP is also generally
resilient to traditional code re-randomization, given that evenpatched code pointers are re-randomized correctly to theirpatched re-randomized counterparts by the defense. This,
however, assumes only live pointers on the stack are usedin the attack (e.g., as done in our Firefox exploit).

6. Mitigations
Defending against PIROP attacks is possible, but retaining the performance and deployability advantages of
traditional code randomization is challenging. In the following, we discuss several potential approaches to mitigate
or prevent the attacks proposed earlier.
Stopping PIROP primitives. A practical way to stop
PIROP attacks is to remove the necessary primitives. For
example, to eliminate relative memory write primitives, we
may rely on memory safety solutions [59]–[64] or, alternatively, data-flow integrity solutions [65], [66]. However,these solutions incur nontrivial performance overhead, reducing the performance benefits of ASLR. Also, in rarecases, it may be possible to exploit a system without patching.
An alternative is to thwart PIROP’s stack massaging
primitive, either by means of stack randomization techniques [4], [5], [12], [67], or shadow stacks [67]–[71].
Unfortunately, stack randomization is not cheap in termsof performance, while efficient implementations of shadow
stacks are hard to implement securely [17], [18], since they
themselves rely on randomization. In general, eliminatingstack massaging alone stops PIROP, but not necessarily
other variants of position-independent code reuse attacks.
Improving ASLR. Fine-grained ASLR [7], [7], [8],[10]–[13], [20], [22], [23], [23], [25], [25], [36], [45] also
mitigates PIROP, but at a cost in performance. Specifically,as shown in Section 5, more efficient solutions such asfunction-level or register-level randomization may not offer
sufficient entropy per patched gadget. Very fine-grained
randomization (i.e., at or below the basic block level) significantly raises the bar for an adversary, but is expensive, e.g.,
because of the less efficient use of the instruction cache.
Code pointer hiding offers a good compromise [22],[23]. While it cannot remove position-independent gadgets
in the trampoline tables, one could randomize such tables with high entropy and/or sprinkle them with booby
traps [72]. Finally, in MVX [28]–[30], [46]–[50] we could
limit the high-entropy randomization to the “slave” variant,which typically has a higher performance budget because of
the faster (emulated) system calls [73].
Data space randomization. Data randomization alone(e.g., heap ASLR) is not sufficient to stop PIROP, as theattacker can patch not only code but also data pointers (oravoid them altogether). However, techniques that randomize
the data space itself by means of encryption are anotheravenue for mitigation. Full data space randomization [74]can produce a non-linear randomization of all the bits in the
ROP payload, making PIROP’s patching step much harder
but also introducing nontrivial overheads. More efficientsolutions such as PointGuard [75], ASLR-Guard [71], Shuffler [32], LR2 [20], and CCFI [76] encrypt only code/data
pointers, but with different encryption schemes. The stronger

the encryption, the higher the per-patched-gadget entropy,
but the lower the performance. As with ASLR, these solutions do not stop the rare cases where patchless exploits
may be possible.
Other defenses. Other code-reuse defenses to consider
for mitigation include CPI and CFI, although they are bothmore expensive than randomization. CPI [70] can isolate
code pointers and guarantee their integrity, but also needs
to protect its safe region [77]. As for CFI, [44], [70], [78]–[90], the more fine-grained the CFI strategy, the better the
security. However, even coarse-grained CFI may suffice toreduce the gadget space such that practical attacks become
hard.

7. Related WorkWe extensively discussed mitigation strategies against
PIROP and traditional code reuse in the previous sections.
Hence, we only focus on related work describing attacks
related to position-independent code reuse.
Advanced code-reuse attacks. After the original ROP
attack [91], many advanced forms of code-reuse attacks havebeen proposed by the community to counter a variety ofdefenses. For example, jump-oriented programming (JOP)
attacks [41], [92] solely rely on forward indirect branches to
bypass defenses that only protect the return branches. Morerecent code-reuse attacks assume even tighter constraints to
bypass control-flow integrity (CFI) or related techniques. A
first generation of attacks proposes code-reuse techniques
to bypass anomaly-based CFI [93], [94] and coarse-grained
CFI absent a shadow stack [94]–[96]. A second generationshows that even fine-grained CFI variants are susceptible topractical attacks [43], [97], [98]. Unlike PIROP, all thesecode-reuse attack techniques focus on defenses that deterministically restrict the (known) gadget set at the attacker’s
disposal.
Other code-reuse variants target randomization-based
defenses. JIT-ROP attacks [16], [34] demonstrate that an
attacker can rely on arbitrary read primitives to disclose
arbitrary code pointers in code/data sections and craft a justin-time ROP payload against fine-grained ASLR. SROP [99]highlights that an attacker can also rely on particular harderto-randomize code gadgets and reduce the information disclosure surface. More recently, inference attacks [100] showthat an attacker can disclose the location of relevant gadgets
by leaking the location of related gadgets via disclosure
code reads. Finally, counterfeit object-oriented programming(COOP) [43], address-oblivious code reuse [101], and Newton [102] show that JIT code-reuse attacks are possible bysolely relying on code pointers disclosed by data sections.
Unlike all these attacks, PIROP demonstrates that codereuse attacks are even possible in complete absence of
information disclosure from code or data sections, providing a concrete upper bound to the security of ASLR andinformation disclosure defenses.
Advanced exploitation primitives. The primitives usedin PIROP draw inspiration from techniques adopted in previous exploitation strategies. For example, our stack massag-

ing primitive is inspired by heap massaging techniques [103]to facilitate the exploitation of temporal (e.g., use-after-free)vulnerabilities. Similar techniques have also been recently
applied to physical memory to facilitate exploitation of hardware (e.g., Rowhammer) vulnerabilities [104], [105]. Unlike
all these techniques, PIROP relies on memory massaging
primitives to lure a victim into generating a code-reuse
payload on her behalf as a prelude to exploitation.
Similarly, the adoption of relative memory write primitives in PIROP is inspired by partial pointer overwrites
used to facilitate 32-bit RILC exploitation [37] or reducethe information disclosure effort in modern exploits [38].
Relative memory write primitives have also been used before
to bypass stack cookies, e.g., using a non-linear stackbased buffer overflow [54]. Unlike all these techniques,
PIROP relies on relative memory write primitives to operate
multiple and targeted modifications to a full ROP payload
for disclosure-resilient position-independent code reuse exploitation on modern 64-bit architectures.
Attacks against ASLR. Many existing attacks havedemonstrated weaknesses in ASLR techniques. Traditional
attacks against randomization rely on memory disclosure toleak code pointers from code/data sections and bypass theprotection [15], [16], [34], [106]. Other attacks demonstrate
that, even in absence of memory disclosure, an attacker can
bypass coarse-grained randomization (traditional ASLR) via
a variety of side channels, such as control flow [107], [108],
memory deduplication [109], cache [110], [111], TLB [111],
crashes [19], [112], exceptions [17], [113], [114], and memory allocations [18]. Unlike all these techniques, PIROP
demonstrates that information disclosure is not a fundamental precondition for modern code-reuse attacks and practical
exploits are still possible even with fine-grained randomization and no disclosure capabilities.

8. Conclusion
ASLR and CFI are the most prominent solutions to efficiently mitigate code-reuse exploits. Recent attacks against
ideal CFI implementations have established an upper boundfor their security guarantees.
In this paper, we investigated a similar upper boundfor ASLR techniques. We assumed an ideal scenario, thatis an attacker with no information disclosure capabilities
to leak the code layout. We demonstrated practical attacks
via a method we call Position-Independent Return-Oriented
Programming (PIROP). Rather than leaking code pointers
and using a just-in-time code-reuse strategy, attackers canlure the victim into generating a position-independent codereuse payload, later tweaked and used for exploitation. Our
research shows that PIROP bypasses common ASLR implementations completely, and significantly weakens several
more advanced defenses. Finally, our analysis suggests that,rather than offering a competing solution, code randomization may be better combined with CFI to guarantee sufficient
protection.

Acknowledgments
We would like to thank the anonymous reviewers fortheir valuable feedback. This work is based upon research supported in part by the European Commission
through project H2020 MSCA-RISE-2015 “PROTASIS” under Grant Agreement No. 690972 and H2020 “BASTION”
under Grant Agreement No. 640110, in part by the U.S.
Office of Naval Research under award numbers N00014-161-2261, N00014-17-1-2788, and N00014-17-1-2782, and inpart by the Netherlands Organisation for Scientific Researchthrough grants NWO 639.023.309 VICI “Dowsing” andNWO 639.021.753 VENI “PantaRhei”.
The paper reflects only the authors’ view and the Agency
and the Commission are not responsible for any use that may
be made of the information it contains.

[17]

E. Goktas, R. Gawlik, B. Kollenda, E. Athanasopoulos, G. Portokalidis, C. Giuffrida, and H. Bos, “Undermining information hiding(and what to do about it),” in USENIX SEC, 2016.

[18]

A. Oikonomopoulos, E. Athanasopoulos, H. Bos, and C. Giuffrida,“Poking holes in information hiding,” in USENIX SEC, 2016.

[19]

A. Bittau, A. Belay, A. Mashtizadeh, D. Mazières, and D. Boneh,“Hacking blind,” in S&P, 2014.

[20]

K. Braden, S. Crane, L. Davi, M. Franz, P. Larsen, C. Liebchen, and
A. R. Sadeghi, “Leakage-resilient layout randomization for mobile
devices,” in NDSS, 2016.

[21]

M. Backes, T. Holz, B. Kollenda, P. Koppe, S. Nürnberger, and
J. Pewny, “You can run but you can’t read: Preventing disclosure
exploits in executable code,” in CCS, 2014.

[22]

S. J. Crane, S. Volckaert, F. Schuster, C. Liebchen, P. Larsen,
L. Davi, A.-R. Sadeghi, T. Holz, B. De Sutter, and M. Franz, “It’sa TRaP: Table randomization and protection against function-reuseattacks,” in CCS, 2015.

[23]

S. Crane, C. Liebchen, A. Homescu, L. Davi, P. Larsen, A. R.
Sadeghi, S. Brunthaler, and M. Franz, “Readactor: Practical code
randomization resilient to memory disclosure,” in S&P, 2015.

[24]

J. Gionta, W. Enck, and P. Ning, “HideM: Protecting the contents
of userspace memory in the face of disclosure vulnerabilities,” in
CODASPY, 2015.

[25]

J. Gionta, W. Enck, and P. Larsen, “Preventing kernel code-reuseattacks through disclosure resistant code diversification,” in CNS,
2016.

References[1]

PaX Team, “Address space layout randomization (ASLR),” 2003,
pax.grsecurity.net/docs/aslr.txt.

[2]

M. Conti, S. Crane, T. Frassetto, A. Homescu, G. Koppen, P. Larsen,
C. Liebchen, M. Perry, and A.-R. Sadeghi, “Selfrando: Securing thetor browser against de-anonymization exploits,” in PETS, 2016.

[3]

S. Crane, A. Homescu, and P. Larsen, “Code randomization: Haven’t
we solved this problem yet?” in SecDev, 2016.

[26]

[4]

S. Bhatkar, D. C. DuVarney, and R. Sekar, “Efficient techniques forcomprehensive protection from memory error exploits,” in USENIX
SEC, 2005.

A. Tang, S. Sethumadhavan, and S. Stolfo, “Heisenbyte: Thwarting
memory disclosure attacks using destructive code reads,” in CCS,
2015.

[27]

[5]

——, “Address obfuscation: An efficient approach to combat a broad
range of memory error exploits,” in USENIX SEC, 2003.

J. Werner, G. Baltas, R. Dallara, N. Otterness, K. Z. Snow, F. Monrose, and M. Polychronakis, “No-execute-after-read: Preventing code
disclosure in commodity software,” in ASIACCS, 2016.

[6]

C. Kil, J. Jun, C. Bookholt, J. Xu, and P. Ning, “Address spacelayout permutation (ASLP): Towards fine-grained randomization ofcommodity software,” in ACSAC, 2006.

[28]

K. Koning, H. Bos, and C. Giuffrida, “Secure and efficient multivariant execution using hardware-assisted process virtualization,” in
DSN, 2016.

[7]

V. Pappas, M. Polychronakis, and A. D. Keromytis, “Smashing thegadgets: Hindering return-oriented programming using in-place code
randomization,” in S&P, 2012.

[29]

S. Volckaert, B. Coppens, A. Voulimeneas, A. Homescu, P. Larsen,
B. De Sutter, and M. Franz, “Secure and efficient application monitoring and replication,” in USENIX ATC, 2016.

[8]

R. Wartell, V. Mohan, K. W. Hamlen, and Z. Lin, “Binary stirring:Self-randomizing instruction addresses of legacy x86 binary code,”in CCS, 2012.

[30]

R. Gawlik, P. Koppe, B. Kollenda, A. Pawlowski, B. Garmany, andT. Holz, “Detile: Fine-grained information leak detection in script
engines,” in DIMVA, 2016.

[9]

M. Backes and S. Nürnberger, “Oxymoron: Making fine-grained
memory randomization practical by allowing code sharing,” in
USENIX SEC, 2014.

[31]

Y. Chen, Z. Wang, D. Whalley, and L. Lu, “Remix: On-demand live
randomization,” in CODASPY, 2016.

[10]

J. Hiser, A. Nguyen-Tuong, M. Co, M. Hall, and J. W. Davidson,“ILR: Where’d my gadgets go?” in S&P, 2012.

[32]

[11]

A. Homescu, S. Neisius, P. Larsen, S. Brunthaler, and M. Franz,“Profile-guided automated software diversity,” in CGO, 2013.

D. Williams-King, G. Gobieski, K. Williams-King, J. P. Blake,
X. Yuan, P. Colp, M. Zheng, V. P. Kemerlis, J. Yang, and W. Aiello,“Shuffler: Fast and deployable continuous code re-randomization,”in OSDI, 2016.

[12]

C. Giuffrida, A. Kuijsten, and A. S. Tanenbaum, “Enhanced operating system security through efficient and fine-grained address space
randomization,” in USENIX SEC, 2012.

[33]

K. Lu, S. Nürnberger, M. Backes, and W. Lee, “How to make ASLR
win the clone wars: Runtime re-randomization,” in NDSS, 2016.

[34]

[13]

H. Koo and M. Polychronakis, “Juggling the gadgets: Binary-level
code randomization using instruction displacement,” in ASIACCS,
2016.

L. Davi, C. Liebchen, A. R. Sadeghi, K. Z. Snow, and F. Monrose,“Isomeron: Code randomization resilient to (just-in-time) returnoriented programming,” in NDSS, 2015.

[35]

[14]

M. Sun, J. C. Lui, and Y. Zhou, “Blender: Self-randomizing address
space layout for android apps,” in RAID, 2016.

D. Bigelow, T. Hobson, R. Rudd, W. Streilein, and H. Okhravi,“Timely rerandomization for mitigating memory disclosures,” in
CCS, 2015.

[15]

P. Vreugdenhil, “Pwn2Own 2010 Windows 7 Internet Explorer
8 exploit,” 2010. [Online]. Available: https://labs.mwrinfosecurity.
com/blog/mwr-labs-pwn2own-2013-write-up-webkit-exploit/
K. Z. Snow, F. Monrose, L. Davi, A. Dmitrienko, C. Liebchen, and
A.-R. Sadeghi, “Just-in-time code reuse: On the effectiveness offine-grained address space layout randomization,” in Proceedings ofthe 2013 IEEE Symposium on Security and Privacy, 2013.

[36]

X. Chen, H. Bos, and C. Giuffrida, “CodeArmor: Virtualizing thecode space to counter disclosure attacks,” in EuroS&P, 2017.

[37]

Anonymous, “Bypassing PaX ASLR protection,” Phrack magazine,
vol. 11, no. 59, 2002.

[16]

[38]

C. Evans, “A scriptless 0day exploit against Linux desktops,”
http://scarybeastsecurity.blogspot.nl/2016/11/0day-exploitadvancing-exploitation.html.

[62]

K. Koning, T. Kroes, E. van der Kouwe, H. Bos, and C. Giuffrida,“Delta pointers: Buffer overflow checks without the checks,” inEuroSys, 2018.

[39]

Solar Designer, “Return-to-libc attack,” BugTraq, August 1997.

[63]

[40]

R. Roemer, E. Buchanan, H. Shacham, and S. Savage, “Returnoriented programming: Systems, languages, and applications,” ACM
Trans. Info. & System Security, vol. 15, no. 1, 2012.

A. Milburn, H. Bos, and C. Giuffrida, “Safeinit: Comprehensive andpractical mitigation of uninitialized read vulnerabilities,” in NDSS,
2017.

[64]

[41]

T. Bletsch, X. Jiang, V. W. Freeh, and Z. Liang, “Jump-oriented
programming: A new class of code-reuse attack,” in ASIACCS, 2011.

I. Haller, J. Yuseok, H. Peng, M. Payer, C. Giuffrida, H. Bos, andE. van der Kouwe, “Typesan: Practical type confusion detection,” in
CCS, 2016.

[42]

L. Davi, A.-R. Sadeghi, and M. Winandy, “Dynamic integrity measurement and attestation: Towards defense against return-oriented
programming attacks,” in ACM STC, 2009.

[65]

M. Castro, M. Costa, and T. Harris, “Securing software by enforcing
data-flow integrity,” in OSDI, 2006.

[66]

[43]

F. Schuster, T. Tendyck, C. Liebchen, L. Davi, A.-R. Sadeghi, andT. Holz, “Counterfeit object-oriented programming: On the difficultyof preventing code reuse attacks in C++ applications,” in S&P, 2015.

P. Akritidis, C. Cadar, C. Raiciu, M. Costa, and M. Castro, “Preventing memory error exploits with WIT,” in S&P, 2008.

[67]

X. Chen, A. Slowinska, D. Andriesse, H. Bos, and C. Giuffrida,“StackArmor: Comprehensive protection from stack-based memory
error vulnerabilities for binaries,” in NDSS, 2015.

[68]

T. H. Dang, P. Maniatis, and D. Wagner, “The performance cost of
shadow stacks and stack canaries,” in ASIACCS, 2015.

[69]“Clang’s SafeStack,” http://clang.llvm.org/docs/SafeStack.html.

[70]

V. Kuznetsov, L. Szekeres, M. Payer, G. Candea, R. Sekar, andD. Song, “Code-pointer integrity,” in OSDI, 2014.

[71]

K. Lu, C. Song, B. Lee, S. P. Chung, T. Kim, and W. Lee, “ASLRGuard: Stopping address space leakage for code reuse attacks,” in
CCS, 2015.

[72]

S. Crane, P. Larsen, S. Brunthaler, and M. Franz, “Booby trapping
software,” in NSPW, 2013.

[44]

M. Abadi, M. Budiu, U. Erlingsson, and J. Ligatti, “Control-flow
integrity,” in CCS, 2005.

[45]

K. Onarlioglu, L. Bilge, A. Lanzi, D. Balzarotti, and E. Kirda, “GFree: Defeating return-oriented programming through gadget-lessbinaries,” in ACSAC, 2010.

[46]

[47]

B. Salamat, T. Jackson, A. Gal, and M. Franz, “Orchestra: Intrusion detection using parallel execution and monitoring of program
variants in user-space,” in EuroSys, 2009.
B. Cox, D. Evans, A. Filipi, J. Rowanhill, W. Hu, J. Davidson,
J. Knight, A. Nguyen-Tuong, and J. Hiser, “N-variant systems: asecretless framework for security through diversity,” in USENIX
SEC, 2006.

[48]

S. Volckaert, B. De Sutter, T. De Baets, and K. De Bosschere,“GHUMVEE: Efficient, effective, and flexible replication,” in FPS,
2012.

[73]

P. Hosek and C. Cadar, “Varan the unbelievable: An efficient nversion execution framework,” in ASPLOS, 2015.

[74]

[49]

D. Bruschi, L. Cavallaro, and A. Lanzi, “Diversified process replicae
for defeating memory error exploits,” in IPCCC, 2007.

S. Bhatkar and R. Sekar, “Data space randomization,” in DIMVA,
2008.

[75]

S. Volckaert, B. Coppens, and B. De Sutter, “Cloning your gadgets: Complete ROP attack immunity with multi-variant execution,”
TDSC, vol. 13, no. 4, 2016.

C. Cowan, S. Beattie, J. Johansen, and P. Wagle, “Pointguard TM:
protecting pointers from buffer overflow vulnerabilities,” in USENIX
SEC, 2003.

[76]

A. J. Mashtizadeh, A. Bittau, D. Boneh, and D. Mazières, “CCFI:Cryptographically enforced control flow integrity,” in CCS, 2015.

[77]

K. Koning, X. Chen, H. Bos, C. Giuffrida, and E. Athanasopoulos,“No need to hide: Protecting safe regions on commodity hardware,”in EuroSys, 2017.

[50]

[51]

H. Fuhrmannek, “Bug 1248876 - (CVE-2016-1977) Graphite2 Machine::Code::decoder::analysis::set_ref stack out of bounds bit set,”https://bugzilla.mozilla.org/show_bug.cgi?id=1248876.

[52]

E. Intelligence, “DoS? Then Who Was Phone?” http://blog.
exodusintel.com/tag/cve-2012-5976/.

[53]

M. Miller, “Heap corruption issues reported to Microsoft,”2017. [Online]. Available: https://twitter.com/epakskape/status/
851479629873332224[54]

S. Gross, “Strengths and weaknesses of LLVM’s SafeStackbuffer overflow protection,” http://blog.includesecurity.com/2015/11/
LLVM-SafeStack-buffer-overflowprotection.html.

[78]

B. Niu and G. Tan, “Per-input control-flow integrity,” in CCS, 2015.

[79]

U. Erlingsson, M. Abadi, M. Vrable, M. Budiu, and G. C. Necula,“XFI: Software guards for system address spaces,” in OSDI, 2006.

[80]

M. Zhang and R. Sekar, “Control flow integrity for COTS binaries,”
in USENIX SEC, 2013.

[81]

C. Tice, T. Roeder, P. Collingbourne, S. Checkoway, Ú. Erlingsson, L. Lozano, and G. Pike, “Enforcing forward-edge control-flow
integrity in GCC & LLVM,” in USENIX SEC, 2014.

[55]

S. International, “Graphite Home,” http://graphite.sil.org/.

[56]——, “Graphite Font development,” http://scripts.sil.org/cms/scripts/
page.php?site_id=projects&item_id=graphite_devFont#fontdev.

[82]

T. Bletsch, X. Jiang, and V. Freeh, “Mitigating code-reuse attacks
with control-flow locking,” in ACSAC, 2011.

[57]

S. Schirra, “Ropper,” https://github.com/sashs/Ropper.

[83]

[58]

Intel, “Intel R 64 and IA-32 Architectures Optimization Reference
Manual,”https://www.intel.com/content/dam/www/public/us/
en/documents/manuals/64-ia-32-architectures-optimizationmanual.pdf, June 2016.

Z. Wang and X. Jiang, “HyperSafe: A lightweight approach toprovide lifetime hypervisor control-flow integrity,” in S&P, 2010.

[84]

C. Zhang, T. Wei, Z. Chen, L. Duan, L. Szekeres, S. McCamant,
D. Song, and W. Zou, “Practical control flow integrity and randomization for binary executables,” in S&P, 2013.

[59]

S. Nagarakatte, J. Zhao, M. M. Martin, and S. Zdancewic, “CETS:
compiler enforced temporal safety for C,” in ISMM, 2010.

[85]

M. Payer, A. Barresi, and T. R. Gross, “Fine-grained control-flow
integrity through binary hardening,” in DIMVA, 2015.

[60]——, “SoftBound: Highly compatible and complete spatial memory
safety for C,” in PLDI, 2009.

[86]

[61]

E. van der Kouwe, V. Nigade, and C. Giuffrida, “Dangsan: Scalable
use-after-free detection,” in EuroSys, 2017.

V. van der Veen, E. Göktaş, M. Contag, A. Pawloski, X. Chen,
S. Rawat, H. Bos, T. Holz, E. Athanasopoulos, and C. Giuffrida,“A tough call: Mitigating advanced code-reuse attacks at the binarylevel,” in S&P, 2016.

[87]V. van der Veen, D. Andriesse, E. Goktas, B. Gras, L. Sambuc,
A. Slowinska, H. Bos, and C. Giuffrida, “Practical context-sensitive
CFI,” in CCS, 2015.

[102] V. van der Veen, D. Andriesse, M. Stamatogiannakis, X. Chen,
H. Bos, and C. Giuffrida, “The dynamics of innocent flesh on thebone: Code reuse ten years later,” in CCS, 2017.

[88]

M. Zhang and R. Sekar, “Control flow and code integrity for COTS
binaries: An effective defense against real-world ROP attacks,” in
ACSAC, 2015.

[103] A. Sotirov, “Heap feng shui in JavaScript,” Black Hat Europe, 2007.

[89]

B. Niu and G. Tan, “Modular control-flow integrity,” in PLDI, 2014.

[90]

V. Mohan, P. Larsen, S. Brunthaler, K. W. Hamlen, and M. Franz,“Opaque control-flow integrity,” in NDSS, 2015.

[91]

H. Shacham, “The geometry of innocent flesh on the bone: Returninto-libc without function calls (on the x86),” in CCS, 2007.

[92]

S. Checkoway, L. Davi, A. Dmitrienko, A. R. Sadeghi, H. Shacham,and M. Winandy, “Return-oriented programming without returns,”
in CCS, 2010.

[93]

E. Goktas, E. Athanasopoulos, M. Polychronakis, H. Bos, and
G. Portokalidis, “Size does matter: Why using gadget-chain length
to prevent code-reuse attacks is hard,” in USENIX SEC, 2014.

[94]

N. Carlini and D. Wagner, “ROP is still dangerous: Breaking modern
defenses,” in USENIX SEC, 2014.

[95]

L. Davi, A. R. Sadeghi, D. Lehmann, and F. Monrose, “Stitching
the gadgets: On the ineffectiveness of coarse-grained control-flow
integrity protection,” in USENIX SEC, 2014.

[96]

E. Goktas, E. Athanasopoulos, H. Bos, and G. Portokalidis, “Out ofcontrol: Overcoming control-flow integrity,” in S&P, 2014.

[97]

N. Carlini, A. Barresi, M. Payer, D. Wagner, and T. R. Gross,“Control-flow bending: On the effectiveness of control-flow integrity,” in USENIX SEC, 2015.

[98]

[99]

I. Evans, F. Long, U. Otgonbaatar, H. Shrobe, M. C. Rinard,
H. Okhravi, and S. Sidiroglou-Douskos, “Control jujutsu: On the
weaknesses of fine-grained control flow integrity,” in CCS, 2015.
E. Bosman and H. Bos, “Framing signals—a return to portableshellcode,” in S&P, 2014.

[100] K. Snow, R. Rogowski, and M. Polychronakis, “Return to the zombie
gadgets: Undermining destructive code reads via code inference
attacks,” in S&P, 2016.
[101] R. Rudd, R. Skowyra, D. Bigelow, V. Dedhia, T. Hobson, S. Crane,
C. Liebchen, P. Larsen, L. Davi, M. Franz, A.-R. Sadeghi, andH. Okhravi, “Address oblivious code reuse: On the effectivenessof leakage resilient diversity,” in NDSS, 2017.

[104] K. Razavi, B. Gras, E. Bosman, B. Preneel, C. Giuffrida, and H. Bos,
“Flip Feng Shui: Hammering a needle in the software stack,” in
USENIX SEC, 2016.
[105] V. van der Veen, Y. Fratantonio, M. Lindorfer, D. Gruss, C. Maurice, G. Vigna, H. Bos, K. Razavi, and C. Giuffrida, “Drammer:
Deterministic Rowhammer attacks on mobile platforms,” in CCS,
2016.
[106] F. Serna, “The info leak era on software exploitation,” in BlackHat
USA, 2012.
[107] I. Evans, S. Fingeret, J. Gonzalez, U. Otgonbaatar, T. Tang,
H. Shrobe, S. Sidiroglou-Douskos, M. Rinard, and H. Okhravi,“Missing the point(er): On the effectiveness of code pointer integrity,” in S&P, 2015.
[108] J. Seibert, H. Okhravi, and E. Söderström, “Information leaks without memory disclosures: Remote side channel attacks on diversified
code,” in CCS, 2014.
[109] E. Bosman, K. Razavi, H. Bos, and C. Giuffrida, “Dedup Est
Machina: Memory deduplication as an advanced exploitation vector,” in S&P, 2016.
[110] B. Gras, K. Razavi, E. Bosman, H. Bos, and C. Giuffrida, “ASLR
on the line: Practical cache attacks on the MMU,” in NDSS, 2017.
[111] R. Hund, C. Willems, and T. Holz, “Practical timing side channel
attacks against kernel space ASLR,” in S&P, 2013.
[112] H. Shacham, M. Page, B. Pfaff, E.-J. Goh, N. Modadugu, and
D. Boneh, “On the effectiveness of address-space randomization,”in CCS, 2004.
[113] R. Gawlik, B. Kollenda, P. Koppe, B. Garmany, and T. Holz,“Enabling client-side crash-resistance to overcome diversificationand information hiding,” in NDSS, 2016.
[114] B. Kollenda, E. Goktas, T. Blazytko, P. Koppe, R. Gawlik, R. K.
Konoth, C. Giuffrida, H. Bos, and T. Holz, “Towards automateddiscovery of crash-resistant primitives in binaries,” in DSN, 2017.