akde/infosec

Information security is ultimately about managing risk


On the return-to-libc post, we described the process of inject­ing a sys­tem call with para­me­ters via envi­ron­ment vari­ables to start a new process. But this requires to exe­cute anoth­er pro­gram (which maybe no avail­able on the target).

Instead of call­ing sys­tem we can call oth­er instruc­tions from some­where in the mem­o­ry. But it would be dif­fi­cult to find instruc­tions in the mem­o­ry which does exact­ly what we want. The idea of ROP is to use only instruc­tions at the end of func­tions before a return (=Gad­gets) and com­bine them via manip­u­la­tion of the return address­es to exe­cute arbi­trary code.

Helper functions for ROP

The fol­low­ing Win­dows sys­tem calls can be used to con­struct a ROP chain.

VirtualProtect()

We want to use Vir­tu­al­Pro­tect() before our shell­code to dis­able DEP for the mem­o­ry where we have inject­ed it. To do this, we start our exe­cu­tion at the over­writ­ten EIP by call­ing a series of gad­gets which cal­cu­late the cur­rent mem­o­ry address­es and argu­ments for the Vir­tu­al­Pro­tect() syscall, call it and return to our shellcode.

Sim­ple ROP chain for exe­cut­ing Vir­tu­al­Pro­tect() before our inject­ed shellcode.
  1. We over­write the buffer with an overflow
  2. We over­write the RIP’s address with an address where we have a gad­get which saves the cur­rent stack point­er. We will use it as our ref­er­ence point for all oth­er instructions.
  3. Then we call a gad­get which jumps to our next gad­get after the fol­low­ing block of reserved spaces for the Vir­tu­al­Pro­tect() call and argu­ments. Note that these mem­o­ry space is ini­tialy only over­writ­ten, but not with the final val­ues (we don’t know yet).
  4. The next gad­get cal­cu­lates the start address of our shell­code (which comes lat­er in the stack) and stores it in a register.
  5. The next gad­get stored this cal­cu­lat­ed val­ue to the mem­o­ry place­hold­er posi­tion for it.
  6. Now, three / six oth­er gad­gets fol­low which cal­cu­late and store the oth­er argu­ments. After all these gad­get ran, all argu­ments from our place­hold­er mem­o­ry are set with the valid values.
  7. Now we set with a last gad­get the return address for Vir­tu­al­Pro­tect() and then jump to it.
  8. Vir­tu­al­Pro­tect() is exe­cut­ed and returns to our pro­vid­ed return address, where…
  9. our shell­code is.

General notes

  • Some­times you can­not find a per­fect gad­get which does one instruc­tion and has a ret direct­ly after it. Then, try to find gad­gets which have instruc­tions before the ret which don’t harm you. For exam­ple, if there is a pop instruc­tion before the ret instruc­tion, you could add a dum­my val­ue to the stack before so that an addi­tion­al pop would not destroy the stack order you overwrote.

Leave a Reply

About

Personal collection of some infosec stuff. Primary purpose of this site is to collect and organize for myself.

Note: Some content is not publicly visible due to copyright issues. Therefore, some links could be broken.

Checklists

Categories

Checklists: Ports

python -c 'import pty;pty.spawn("/bin/bash")';

python3 -c 'import pty;pty.spawn("/bin/bash")';