Abstract— Computer security is a
progress in which attackers find new ways to exploit and defenders try to
develop defenses against them. Prior assumption before the introduction of
return-into-libc attacks was that to create malicious behavior, attackers need
to be able to inject bad code into the target system. Return-into-libc attacks
proved this assumption to be wrong. As return-into-libc attacks,
return-oriented programming uses existing code in the target system to create
arbitrary behavior but it does not use any function calls or limited to libc. Return-oriented
programming is architecture independent and it can bypass traditional defensive
measures. In response, address randomization and control-flow integrity
solutions developed to prevent return-oriented programming. This document briefly
introduces and describes return-oriented programming and some mitigations
return-oriented programming, g-free, aslr, dep
introduction of return-into-libc attacks, it was believed that to create
malicious or harmful behavior an attacker needs to introduce bad code into the
target system. Since it is not possible to accurately classify an execution as
harmful, some parts of the security community focused on isolating the injected
code with memory protection methods. Return-oriented programming (ROP)
is an advanced technique that falsifies this prior assumption by being able to
create malicious activities without injecting any harmful code independent of
the underlying architecture. ROP is a generalization of the return-into-libc attacks which has been introduced to defy memory
protections developed against classical stack buffer overflow attacks such as
stack smashing. In classical stack smashing attacks, assuming there are no
memory protections, attackers usually find a bug in a program which can be
exploited to inject malicious code (e.g. reverse shell payload) into the stack
by overwriting the adjacent memory blocks and divert the flow of the program to
execute it 1. In detail, attackers try to control program counter register
(EIP) while storing the payload somewhere in the memory, then point it to the
injected code by overwriting EIP’s address since the buffer is allocated
contiguously in the stack. In response, W?X (Write-XOR-eXecute) memory protection techniques such as
NX bit (No-eXecute) and Data Execution Prevention (DEP) have been developed to
overcome this type of attacks. Briefly, W?X type of defenses mark the partitions of the memory either
as writable or executable but never both 2. This same approach is also
implemented at hardware level as NX bit by companies such as Intel and AMD. NX
bit indicates whether if the memory area is either dedicated to storage or
processor instructions. DEP stands for Data Execution Prevention, it is
Windows’ version of W?X memory protection but on the system level. The same
approach is also used by Linux and macOS. To defeat W?X type
protections, instead of code injecting, attackers use existing functions of
libc in the target system. Using existing code for malicious behavior
was first suggested by Solar Designer 3. In Unix systems, standard C library
contains system methods such as file I/O and, file execution and it is linked
by almost all Unix C programs. For this attack to be successful, attackers need
to be able to subvert
a program’s flow as it was before with the stack
buffer overflow attacks except with ROP, adversaries use existing code
snippets that end with a return instruction in the target system. ROP is a
generalization of return-into-libc attack which does not rely on function
calls, instead, it can build instruction chains with the existing code snippets
in the target system without making any function calls. ROP is a very effective
technique used by malwares such as Stuxnet and Duqu 45. Some defenses have
been developed to stop this attack such as ASLR, G-Free and, IB-MAC
6 (for IoT embedded systems). Among some of the defenses such as ASLR can be
bypassed by variants 12 of ROP and more advanced techniques such as G-Free
II. Return-Oriented Programming.
ROP is affiliated with every attack that uses existing code in the target
system. However, the name ROP is first brought up by Hovav Shacham 7 as an
attack that uses existing code snippets ending with return statements which can
be chained together to create arbitrary behavior without making any function
calls. With this approach, NX bit or any W?X type of defenses
can be bypassed. ROP is independent of underlying architecture and it was
successfully used on other architectures such as x86, RISC 8, ARM 9 and,
return-oriented program is a combination of one or more gadgets which upon
execution, creates the attacker’s desired behavior. A gadget consists of words
on the stack including single or multiple instruction sequence pointers and
corresponding immediate values, that encodes a logical unit 2. In the x86
architecture, a gadget can contain other gadgets since x86 instructions are not
aligned, but this is not true for other architectures. Apart from
return-into-libc attacks, ROP’s building blocks are not functions, rather they
are short code snippets ending with a return statement. In theory, every code
sequence ending with a return instruction is a useful gadget.
The easiest way to accomplish a ROP attack is to use the
stack buffer overflow exploits. Roadmap for ROP starts by finding suitable
gadgets for the desired behavior. For finding gadgets, there are available
tools such as Rp++ 11, Nrop 12 and, ROPgadget 13. Chance of finding
necessary gadgets for the task increases as the codebase of the exploited
program gets larger. Traditional tools find gadgets by locating every return
instruction and then walking back from these instructions while looking at the
corresponding sequence and checking for criterions of the user or legitimacy of
the instruction sequence. Correct execution of gadgets has one precondition and
one postcondition. The precondition is that ESP register should point to the
first word in the gadget and the processor executes a return instruction, the
postcondition is when the return instruction in its last instruction sequence
is executed, ESP points to the next gadget to be executed 2. In the next
step, stack needs to be overwritten with the payload that contains gadget
addresses which were previously chosen. Note that unlike classic stack smashing
attacks, there are no processor instructions in the payload, it only consists
of gadget addresses which will be written to the stack. Also, gadgets of a
return-oriented program do not need to be stored in adjacent memory blocks or
solely in the stack, gadgets can be stored on the heap 14, furthermore the
gadget payload can be divided onto the stack and heap. Again, same attack
road-map applies to every architecture, only instruction semantics of the
gadgets vary. Recall that attackers overwrite the stack with the payload in
such a way that they can set the EIP with the address of the first gadget.
Additionally, ROP payload stored on the heap can be initiated by overwriting a
function pointer with the address of a code snippet that sets ESP to the
address of the first gadget and executes a return instruction. Either way, the
gadget chain will be executed accordingly one by one returning to each other
creating the desired behavior.
III. Mitigations Against Return-Oriented
Defenses that focus on the use of return instruction for ROP
have been proposed but such defenses can be defeated by using variants of ROP
which are not using return instructions. There are however more complex
countermeasures to prevent ROP that focuses on control-flow integrity. This
type of defenses remains unbroken. Control-flow integrity oriented security
measures are also supported by authors of ROP 2. In this section, widespread
used Address space layout randomization (ASLR) and a proposed defense; G-Free are
defined and commented. There are numerous propositions including hardware
modifications such as
Instruction Based Memory Access Control (IB-MAC). Also, Windows has additional
mitigations such as SEHOP 16 to prevent the attacker from diverting the flow
by overwriting exception pointers. DEP, NX bit and, any W?X type of mitigations by themselves are not a defense against ROP therefore, they
Space Layout Randomization
ASLR is used to randomize address ranges
of important memory segments at each execution. It is developed to prevent hard-coded
attacks that are using the stack, heap and, libc addresses. At each execution
stack, heap and, library addresses change therefore, memory segment addresses
are not static anymore. Still, with stack smashing, attackers can get the
control of EIP but this time they will not know where to go. Usage of ASLR is
widespread ranging from Android and iOS phones to desktop kernels.
On Linux, ASLR does not randomize every
program because PIE flag of a program needs to be set on compile 17. PIE
stands for Position Independent Executable which tells the compiler that the
base address does not really matter, without it, the program is not taking full
advantage of ASLR thus the attacker might be able to find some gadgets. It is
crucial to compile shared libs with PIE flag on Linux.
Since security is a progress, some ways to bypass ASLR
have been found such as information disclosure 18, partial address overwrite
19 and, base address brute forcing 20. Information disclosure happens
whenever the attacker can extract any meaningful information while ASLR is
deployed. Assuming there is info leak regarding the address of printf method of libc, then the attacker
can compare the distance between methods and find the addresses of desired
gadgets or methods such as execve.
Furthermore, finding the necessary functions or code snippets of libc by brute
force is feasible because ASLR does not randomize everything, it randomizes the
base addresses of each library.
G-Free is a compiler based defense approach against any form
of return-oriented programming 21. G-Free protects aligned free-branch
instructions and prevents misuse of unaligned free-branch instructions. It adds
NOP instructions to align instructions and prepends a JUMP instruction to skip NOP
chunk. The malicious code is forced to realign with the actual code upon
reaching the NOP instructions. However, this approach introduces overheads
which are going to be mentioned in the last part of the section. Aligned
instructions’ performance is not affected by this approach due to prepended
attaches a short header that encrypts the return address stored on the stack
for entry points of the functions that end with a RETURN instruction. To
restore the return address to its original value, it inserts a decryption footer
21. This step prevents the attacker to jump to an arbitrary position because
at the end, in the footer, decryption routine is awaiting. Because of
decryption step in the footer, it calculates a faulty address irrelevant to the
attacker’s intent. RETURN instruction then tries to transfer the flow to a bad
address computed by the footer which the attacker cannot control.
G-Free also makes use of Frame Cookies to
prevent the attacker from using JUMP/CALL instructions 21. Wherever this kind
of instructions are found, an additional header is attached which computes and
pushes a random cookie onto the stack. Then again, a validation footer is
attached to fetch the cookie and determine if the destination address is valid.
Upon an invalid case, it causes the application to crash.
G-Free currently remains unbroken but
introduces 23% more memory usage and 3% decrease in performance 21. It also
makes use of code rewriting techniques to remove unaligned free-branch
Return-Oriented programming proves to be
very effective as it was used in popular malware such as Stuxnet and Duqu. With
this technique, attackers can avoid W?X type of protections and furthermore with its variants
they are able to defeat defenses that focus on limiting the use of return
instructions. Suggested more sophisticated defenses remain unbroken but they
also introduce additional overhead and decrease in performance. This attacking
technique emphasizes the importance of control-flow therefore, defense efforts
focused on the control-flow integrity would be in more effect.
independent of underlying architectures and it is Turing-complete. Gadget
finding is still possible even though in the presence of ASLR. Since ROP
provides the attacker the benefit of using existing code in the target system,
malware becomes smaller, therefore, harder to detect by traditional defense
systems and it makes code signing useless against ROP. Implementation of
defenses for embedded systems is even more problematic due to the need for
extra memory and computation.
As ROP proves the prior assumption of
malicious behavior can only be created by injected bad code invalid, this
approach shows it is, in fact, possible to create arbitrary behavior by using
existing code in the target system. In order to make this approach disappear,
control-flow integrity systems ought to be adopted more.
1 J. Salwan, “An
introduction to the Return Oriented Programming and ROP chain generation” in Shell-Storm.
2 R. Roemer, E. Buchanan,
H. Shacham, and S. Savage, “Return-Oriented Programming: Systems, Languages,
and Applications” ACM Transactions on Information and System Security, vol. 15,
no. 1, Mar. 2012.
3 Solar Designer,
“Getting around non-executable stack (and fix)”, 10-Aug-1997. Online.
4 A. Matrosov, E.
Rodionov, D. Harley, and J. Malcho, “Stuxnet Under the Microscope”, Official
site of the antivirus ESET NOD32, ESET. Available: https://www.esetnod32.ru/company/viruslab/analytics/doc/Stuxnet_Under_the_Microscope.pdf
5 P. Szor, “Duqu –
Threat Research and Analysis”, McAffee Labs. Available: https://securingtomorrow.mcafee.com/wp-content/uploads/2011/10/Duqu1.pdf
6 A. C. A. Francillon, D. Perito, and C.
Castelluccia, “Defending embedded systems against control flow attacks,” Proceedings of the first ACM workshop on Secure
execution of untrusted code – SecuCode 09, 2009.
7 H. Shacham, “The geometry of innocent
flesh on the bone,” Proceedings of
the 14th ACM conference on Computer and communications security – CCS 07, 2007.
8 E. Buchanan, R. Roemer, H. Shacham,
and S. Savage, “When good instructions go bad”, Proceedings of the 15th ACM conference on Computer and
communications security – CCS 08, 2008.
9 S. Checkoway, L. Davi, A. Dmitrienko,
A.-R. Sadeghi, H. Shacham, and M. Winandy, “Return-oriented programming without
returns”, Proceedings of the 17th
ACM conference on Computer and communications security – CCS 10, 2010.
10 F. Lindner, “Router Exploitation”,
in BlackHat Briefings USA 2009, 2009.
11 A. Souchet,
12 A. Wailly, “Nrop”,
13 J. Salwan,
“ROPgadget” in Shell-Storm
14 D. D. Zovi, “Practival Return-Oriented
Programming”, in RSA Conference
15 J. Xu, Z. Kalbarczyk, and R. Iyer,
“Transparent runtime randomization for security”, 22nd International Symposium on Reliable Distributed
Systems, 2003. Proceedings.
16 D. Boneh and S. Jana, “Basic Memory
Corruption Attacks.” Available: http://www.cs.columbia.edu/~suman/6183_slides/memory_attacks.pdf
17 P. Biernat, “Address Space Layout
Randomization.”, Available: http://security.cs.rpi.edu/courses/binexp-spring2015/lectures/15/09_lecture.pdf
18 D. Blazakis,
“Interpreter exploitation”, 2010, Proceedings
of WOOT 2010, H. Shacham and C. Miller, Eds. USENIX.
19 T. Durden,
“Bypassing PaX ASLR protection.”, 2002, Phrack Mag. 59, 9, Available: http://phrack.org/issues/59/9.html.
20 H. Shacham, M.
Page, B. Pfaff, E. J. GOH, N. Modadugu, and D. Boneh, “On the effectiveness of
address-space randomization.”, Proceedings
of the ACM Conference on Computer and Communications Security (CCS’04). B.
Pfitzmann and P. Liu Eds., ACM Press, 298–307, 2014.
K. Onarlioglu, L. Bilge, A.
Lanzi, D. Balzarotti, and E. Kirda, “ACSAC ’10”, Proceedings of the 26th Annual Computer Security Applications
Conference, pp. 49–58.