ROP compilers are described twice in a rather redundant fashion.
In fact, so-called “ROP compilers” exist to take an existing vulnerable program and a desired execution flow and generate a series of return addresses.
The general strategy for executing ROPs is to write a chain of return addresses at the RIP to achieve the behavior that we want. Each return address should point to a gadget, which is a small set of assembly instructions that already exist in memory and usually end in a ret instruction (note that gadgets are not functions, they don’t need to start with a prologue or end with an epilogue!). The gadget then executes its instructions and ends with a ret instruction, which tells the code to jump to the next address on the stack, thus allowing us to jump to the next gadget!
If the code base is big enough, meaning that the code imports enough libraries, there are usually enough gadgets in memory for you to be able to run any shellcode that you want. In fact, ROP compilers exist on the Internet that will automatically generate an ROP chain for you based on a target binary and desired malicious code!
I would recommend shifting the middle paragraph to just before the example, and deleting the first ROP reference.
ROP compilers are described twice in a rather redundant fashion.
I would recommend shifting the middle paragraph to just before the example, and deleting the first ROP reference.