Return-Oriented Programming
Performing code-injection attacks on the program rtarget is much
more difficult than it is for ctarget, because it uses
two techniques to thwart such attacks:
- Randomization The stack positions differ from one run to another. This defense makes it impossible for you to determine where your injected code will be located in memory.
- Nonexecutable Memory The memory holding the stack is marked as nonexecutable, so even if you could set the program counter to the start of your injected code, the program would fail with a segmentation fault.
Return-Oriented Programming
Fortunately (for doing this lab), clever people have devised strategies for getting useful things done in a program by executing existing code, rather than injecting new code. The most general form of this approach is referred to as return-oriented programming (ROP).
-
R. Roemer, E. Buchanan, H. Shacham, and S. Savage. “Return-oriented programming: Systems, languages, and applications”. ACM Transactions on Information System Security, 15(1):2:1–2:34, March 2012.
-
E.J. Schwartz, T. Avgerinos, and D. Brumley. “Q: Exploit hardening made easy”. In USENIX Security Symposium, 2011.
The ROP strategy is to identify byte sequences within an existing
program that consist of one or more instructions followed by the
ret instruction. Such a segment is referred to as a gadget.
The following figure illustrates how the stack can be set up to execute a sequence of \( n \) gadgets:

The stack contains a sequence of gadget addresses. Each gadget
consists of a series of instruction bytes, with 0xc3 (the ret
instruction) as the final byte of the gadget. When the program
executes a ret instruction starting with this configuration, it
will initiate a chain of gadget executions, with the ret
instruction at the end of each gadget causing the program to jump to
the beginning of the next.
A gadget can make use of code corresponding to assembly-language
statements generated by the compiler, especially ones at the ends of
functions. In practice, there may be some useful gadgets of this
form, but usually not enough to implement many important operations. For
example, it is highly unlikely that a compiled function would have
popq reg as its last instruction before ret. But with a
byte-oriented instruction set such as x86-64, a gadget can often be
found by extracting patterns from other parts of the instruction
byte sequence.
For example, one version of rtarget contains code generated for the
following C function:
void setval_210(unsigned *p)
{
*p = 3347663060U;
}
The chances of this function being useful for attacking a system seem pretty slim. But, the disassembled machine code for this function shows an interesting byte sequence:
0000000000400f15 <setval_210>:
400f15: c7 07 d4 48 89 c7 movl $0xc78948d4,(%rdi)
400f1b: c3 retq
Ignoring the first three bytes at address 0x400f15, we have the
byte sequence 48 89 c7, which encodes the instruction movq rax,
rdi.
Our cherry-picked sequence is followed by byte value c3, which
encodes the ret instruction. So the function starts at address
0x400f15, and the sequence starts on the fourth byte of the
function. Thus this code contains a gadget that has a starting
address of 0x400f18 that copies the 64-bit value in register rax
to register rdi.
The Gadget Farm
Your code for rtarget contains a number of functions similar to
the setval_210 function shown above. They all reside in a region
we refer to as the gadget farm.
farm.c in the tar file you downloaded.Important: The gadget farm is demarcated by functions
start_farm and end_farm in your copy of rtarget.
Do not attempt to construct gadgets from other portions of the program code.
Steps
- Phase 4: Calling
touch2with Gadgets - Phase 5: Calling
touch3with Gadgets and a String Argument (optional)
Rules for This Assignment
-
You must do the assignment on
wilkes. -
Your solutions may not use attacks to circumvent the validation code in the programs.
Specifically, any address you incorporate into an attack string for use by a
retinstruction should be to one of the following destinations:- The addresses for functions
touch1,touch2, ortouch3. -
The address of your injected code.
-
The address of one of your gadgets from the gadget farm.
- The addresses for functions
-
You may only construct gadgets from file
rtargetwith addresses ranging between those for functionsstart_farmandend_farm. -
Your exploit string must not contain byte value
0x0a(ASCII newline or\n) because theGetsfunction uses0x0ato detect the end of a string. -
hex2rawexpects two-digit hex values separated by one or more white spaces.So if you want to create a byte with a hex value of 0, you must write it as
00. To create the word0XDEADBEEFyou should passef be ad detohex2raw(note the reversal required for little-endian byte ordering). -
The
hex2rawpage also contains examples of using shell I/O redirection (<and>) and pipes (|) on the command line, as shown in examples.
Instruction Tables
All values are shown in hexadecimal.
Byte Encodings of movq (movq S, D) Instructions
Warning: could not open file Content/labs/attack/rop-attacks/tables/encodings-movq.md
Byte Encodings of popq Instructions
Warning: could not open file Content/labs/attack/rop-attacks/tables/encodings-popq.md
Byte Encodings of movl (movl S, D) Instructions
Warning: could not open file Content/labs/attack/rop-attacks/tables/encodings-movl.md
Byte Encodings of 2-Byte Functional Nop Instructions
Warning: could not open file Content/labs/attack/rop-attacks/tables/encodings-nop.md
(When logged in, completion status appears here.)