Malware Analysis Class
Malware Analysis Class
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, the attacker
needs to be able to inject bad code into the target system. Return-into-libc
attacks proved this assumption to be wrong and Return-Oriented Programming even
made it one step further than return-into-libc that this technique as
return-into-libc attacks 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 (ROP) is architecture independent and, it can
bypass traditional defensive measures. In response, the security community came
up with some suggestions to defeat ROP. This document briefly introduces and
describes ROP and some mitigations against it.
return-oriented programming, g-free, aslr, dep
One false assumption that the
security community made was malicious activity can be blocked by preventing the
introduction of malicious code to the 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 is an advanced technique that falsifies
this assumption by being able to introduce malicious activity 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 classic stack smashing attacks, assuming
there are no memory protections, attacker usually finds 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 diverts the flow
of the program to execute it 1, pp. 3-4. In detail, attackers try to control
the program counter register (EIP) while storing the payload somewhere in the
memory, then points to the injected code by overwriting EIP’s address since
buffer is allocated contiguously in the stack. In response, W?X (Write-XOR-eXecute) memory protection techniques such as NX
and 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 not both 2, pp. 2. This same approach also
implemented in hardware level as NX bit (No-eXecute) by companies such as Intel
and AMD but in this case, they introduced an executable bit that indicates
whether if the memory area is either dedicated for storage or processor
instructions. DEP stands for Data Execution Prevention, it is Windows’ version
of W?X memory protection but on system level. 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, the attacker still needs to
be able to subvert a program flow as it was before with the stack buffer
overflow attacks but this time, adversaries use existing code in the target
system. ROP is a generalization of return-into-libc that does not rely on
function calls, instead it can build instruction chains with the existing code
in the target system without making any function calls. ROP is a very effective
technique which 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 2, pp. 3 of ROP and more advanced techniques such as
G-Free remain unbroken.
ROP is affiliated by every attack that uses existing code in the target system.
However, the name ROP is first brought up by Hovav Shacham 2 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 W?X type of defenses
can be bypassed.
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 pp. 12. In 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 attack, 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 useful.
way to accomplish a ROP attack is to use the stack buffer overflow exploits.
Road map for ROP starts with finding suitable gadgets for the desired behavior.
For finding gadgets, there are available tools such as Rp++ 7, Nrop 8 and,
ROPgadget 9. Chance of finding necessary gadgets for the task increases as
the codebase gets larger. Traditional tools find gadgets by locating every
return instruction and then walking back from these instructions while looking
at 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
2, pp. 12. The postcondition is when the return instruction in its last
instruction sequence is executed, ESP points to the next gadget to be executed
2, pp. 12. In the next step, stack needs to be overwritten with the payload
that contains gadget addresses previously chosen. Key difference here from
stack smashing attacks is that 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 its gadgets to be stored
in adjacent memory blocks or solely in stack, furthermore gadget payload can be
divided onto stack and heap. One crucial information to note is this same
process applies to every architecture with a single difference which is the
equivalent instruction semantics of different architectures. Recall that
attackers overwrite the stack with the payload in such a way that they can set
the EIP with the address of first gadget. Additionally, return-oriented program
stored in 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. Either way the gadget chain will be executed accordingly one
by one returning to each other creating the desired behavior.
Defenses that focus on the use of return instruction for
return-oriented programming have been proposed but such defenses can be
defeated by using variants of return-oriented programming which are not using
return instructions 2, pp. 3. There are however more complex counter measures
to prevent return-oriented programming that focuses on control-flow integrity. This
type of defenses remain unbroken. Control-flow integrity oriented security
measures are also supported by authors of return-oriented programming 2, pp.
30. In this section, widespread used ASLR and a proposed defense; G-Free are defined
and commented. There are numerous propositions including hardware modifications
Instruction Based Memory Access Control 6. Also, Windows has additional
mitigations such as SEHOP to prevent the attacker from diverting the flow by
overwriting exception pointers. DEP/NX by itself is not a defense against
return-oriented programming therefore, it is excluded.
Space Layout Randomization
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 stack, heap and, libc addresses. At each execution
stack, heap and, library addresses change therefore, memory segment addresses
are not static anymore. Still with a stack smash, attackers can get the control
of EIP but this time they do not know where to go. It is applied wide spread
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. PIE stands for Position Independent Executable which tells 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 12, partial address overwrite
11 and, base address brute forcing 10. 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
13, pp. 1. 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 sled bytes. The malicious
code is forced realign with the actual code when upon reaching to NOP sleds.
However, this approach introduces overheads which is going to be mentioned in
the last part of the section. Aligned instructions’ performance is not affected
by this approach.
attaches a short header that encrypts the return address stored on the stack
for entry points of the functions end with a RETURN instruction. Later, it
inserts a footer corresponding to the header to restore the return address to
its original value 14, pp. 4. This step prevents the attacker to jump to an
arbitrary position because at the end, in the footer, decryption routine is
waiting. 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
makes use of Frame Cookies to prevent the attacker from using JUMP/CALL
instructions 14, pp. 5. Wherever this kind of instructions 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
application to crash.
remains unbroken but introduces 23% more memory usage and 3% decrease in
performance 14, pp. 5. It also makes use of code rewriting techniques to
remove unaligned free-branch instructions
Return-Oriented programming proves to be
very effective as it was used in popular malwares 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 usage 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.
ROP is 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, malwares become smaller therefore
harder to detect by traditional defense systems and it makes code signing
useless against ROP. Implementation of defenses for embedded systems are even
more problematic due to the need of 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.
Salwan, “An introduction to the Return Oriented Programming and ROP chain
generation” in Shell-Storm.
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.
Designer, “Getting around non-executable stack (and fix)”, 10-Aug-1997.
Online. Available: https://marc.info/?l=bugtraq&m=87602746719512.
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
Szor, “Duqu – Threat Research and Analysis”, McAffee Labs. Available: https://securingtomorrow.mcafee.com/wp-content/uploads/2011/10/Duqu1.pdf
C. A. Francillon, D. Perito, and C. Castelluccia, “Defending Embedded Systems
Against Control Flow Attacks.” Available: http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.150.3803&rep=rep1&type=pdf
Souchet, “rp++”, https://github.com/0vercl0k/rp
Wailly, “Nrop”, https://github.com/awailly/nrop
Salwan, “ROPgadget” in Shell-Storm
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.
Durden, “Bypassing PaX ASLR protection.”, 2002, Phrack Mag. 59, 9. http://www.phrack.org/archives/59/p59_0x09_Bypassing%20PaX%20ASLR%20protection_by_Tyler%20Durden.txt.
Blazakis, “Interpreter exploitation”, 2010, In Proceedings of WOOT 2010, H. Shacham and C. Miller, Eds. USENIX
Onarlioglu, L. Bilge, A. Lanzi, D. Balzarotti, and E. Kirda, “ACSAC ’10,” in Proceedings of the 26th Annual Computer
Security Applications Conference, pp. 49–58.
14 J. Xu, Z. Kalbarczyk, R. K. Iyer,
“Transparent runtime randomization for security”, 2003, 260- 269.