Performing code-injection attacks on program RTARGET
is much more
difficult than it is for CTARGET
, because it uses two techniques
to thwart such attacks:
Fortunately, 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 is referred to as return-oriented programming
(ROP). The strategy with ROP is to identify byte sequences within an existing
program that consist of one or more instructions followed by the instruction
ret
. Such a segment is referred to as a gadget. Figure 2
illustrates how the stack can be set up to execute a sequence of n
gadgets. In this figure, the stack contains a sequence of gadget addresses. Each
gadget consists of a series of instruction bytes, with the final one being
0xc3
, encoding the ret
instruction. 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 not enough to implement many
important operations. For example, it is highly unlikely that a compiled function
would have popq %rdi
as its last instruction before ret
.
Fortunately, 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: 400f15: c7 07 d4 48 89 c7 movl $0xc78948d4,(%rdi) 400f1b: c3 retq
The byte sequence 48 89 c7
encodes the instruction
movq %rax, %rdi
. (See Figure 3A for the encodings of useful
movq
instructions.) This sequence is followed by byte value
c3
, which encodes the ret
instruction. The function
starts at address 0x400f15
, and the sequence starts on the fourth byte
of the function. Thus, this code contains a gadget, having a starting address of
0x400f18
, that will copy the 64-bit value in register %rax
to register %rdi
.
Your code for RTARGET
contains a number of functions similar to
the setval_210
function shown above in a region we refer to as the
gadget farm. Your job will be to identify useful gadgets in the gadget farm
and use these to perform attacks similar to those you did in Phases 2 and 3.
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.
For Phase 4, you will repeat the attack of Phase 2, but do so on program
RTARGET
using gadgets from your gadget farm. You can construct your
solution using gadgets consisting of the following instruction types, and using
only the first eight x86-64 registers (%rax
–%rdi
).
movq
: The codes for these are shown in Figure 3A.
popq
: The codes for these are shown in Figure 3B.
ret
: This instruction is encoded by the single byte 0xc3
.
nop
: This instruction (pronounced “no op,” which is short
for “no operation”) is encoded by the single byte 0x90
. Its
only effect is to cause the program counter to be incremented by 1.
rtarget
demarcated by the functions start_farm
and mid_farm
.popq
instruction, it will pop data from the stack.
As a result, your exploit string will contain a combination of gadget addresses and
data.Before you take on the Phase 5, pause to consider what you have accomplished so far.
In Phases 2 and 3, you caused a program to execute machine code of your own design.
If CTARGET
had been a network server, you could have injected your own
code into a distant machine. In Phase 4, you circumvented two of the main devices
modern systems use to thwart buffer overflow attacks. Although you did not inject your
own code, you were able inject a type of program that operates by stitching together
sequences of existing code. You have also gotten 95/100 points for the lab. That’s
a good score. If you have other pressing obligations consider stopping right now.
Phase 5 requires you to do an ROP attack on RTARGET
to invoke function
touch3
with a pointer to a string representation of your cookie. That may
not seem significantly more difficult than using an ROP attack to invoke
touch2
, except that we have made it so. Moreover, Phase 5 counts for only
5 points, which is not a true measure of the effort it will require. Think of it as more
an extra credit problem for those who want to go beyond the normal expectations for the
course.
To solve Phase 5, you can use gadgets in the region of the code in rtarget
demarcated by functions start_farm
and end_farm
. In addition
to the gadgets used in Phase 4, this expanded farm includes the encodings of different
movl
instructions, as shown in Figure 3C. The byte sequences in this part
of the farm also contain 2-byte instructions that serve as functional nops, i.e.,
they do not change any register or memory values. These include instructions, shown in
Figure 3D, such as andb %al,%al
, that operate on the low-order bytes of
some of the registers but do not change their values.
movl
instruction has on the
upper 4 bytes of a register, as is described on page 183 of the text.Good luck and have fun!