2.**Find**`POP_RDI`, `PUTS_PLT` and `MAIN_PLT` gadgets
3. Use previous gadgets lo **leak the memory address** of puts or another libc function and **find the libc version** \([donwload it](https://LIBC.blukat.me/)\)
4. With the library, **calculate the ROP and exploit it**
This tutorial is going to exploit the code/binary proposed in this tutorial: [https://tasteofsecurity.com/security/ret2libc-unknown-libc/](https://tasteofsecurity.com/security/ret2libc-unknown-libc/)
Another useful tutorials: [https://made0x78.com/bseries-ret2libc/](https://made0x78.com/bseries-ret2libc/), [https://guyinatuxedo.github.io/08-bof\_dynamic/csaw19\_babyboi/index.html](https://guyinatuxedo.github.io/08-bof_dynamic/csaw19_babyboi/index.html)
The template need an offset before continuing with the exploit. If any is provided it will execute the necessary code to find it \(by default `OFFSET = ""`\):
```bash
####################
#### Find offset ###
####################
OFFSET = ""#"A"*72
if OFFSET == "":
gdb.attach(p.pid, "c") #Attach and continue
payload = cyclic(1000)
print(r.clean())
r.sendline(payload)
#x/wx $rsp -- Search for bytes that crashed the application
#cyclic_find(0x6161616b) # Find the offset of those bytes
return
```
**Execute** `python template.py` a GDB console will be opened with the program being crashed. Inside that **GDB console** execute `x/wx $rsp` to get the **bytes** that were going to overwrite the RIP. Finally get the **offset** using a **python** console:
Now we need to find ROP gadgets inside the binary. This ROP gadgets will be useful to call `puts`to find the **libc** being used, and later to **launch the final exploit**.
```python
PUTS_PLT = elf.plt['puts'] #PUTS_PLT = elf.symbols["puts"] # This is also valid to call puts
The `MAIN_PLT` is needed to call the **main function** again after one interaction to **exploit** the overflow **again** \(infinite rounds of exploitation\). **It is used at the end of each ROP to call the program again**.
The **POP\_RDI** is needed to **pass** a **parameter** to the called function.
In this step you don't need to execute anything as everything will be found by pwntools during the execution.
## 3- Finding LIBC library
Now is time to find which version of the **libc** library is being used. To do so we are going to **leak** the **address** in memory of the **function**`puts`and then we are going to **search** in which **library version** the puts version is in that address.
This will send some bytes util **overwriting** the **RIP** is possible: `OFFSET`.
Then, it will set the **address** of the gadget `POP_RDI` so the next address \(`FUNC_GOT`\) will be saved in the **RDI** registry. This is because we want to **call puts****passing** it the **address** of the `PUTS_GOT`as the address in memory of puts function is saved in the address pointing by `PUTS_GOT`.
After that, `PUTS_PLT` will be called \(with `PUTS_GOT` inside the **RDI**\) so puts will **read the content** inside `PUTS_GOT` \(**the address of puts function in memory**\) and will **print it out**.
Finally, **main function is called again** so we can exploit the overflow again.
This way we have **tricked puts function** to **print** out the **address** in **memory** of the function **puts** \(which is inside **libc** library\). Now that we have that address we can **search which libc version is being used**.
As we are **exploiting** some **local** binary it is **not needed** to figure out which version of **libc** is being used \(just find the library in `/lib/x86_64-linux-gnu/libc.so.6`\).
But, in a remote exploit case I will explain here how can you find it:
### 3.1- Searching for libc version \(1\)
You can search which library is being used in the web page: [https://libc.blukat.me/](https://libc.blukat.me/)
It will also allow you to download the discovered version of **libc**
Then, the address to the function `system` and the **address** to the string _"/bin/sh"_ are going to be **calculated** from the **base address** of **libc** and given the **libc library.**
```python
BINSH = next(libc.search("/bin/sh")) - 64 #Verify with find /bin/sh
SYSTEM = libc.sym["system"]
EXIT = libc.sym["exit"]
log.info("bin/sh %s " % hex(BINSH))
log.info("system %s " % hex(SYSTEM))
```
Finally, the /bin/sh execution exploit is going to be prepared sent:
The last ROP \(`rop1`\) ended calling again the main function, then we can **exploit again** the **overflow** \(that's why the `OFFSET` is here again\). Then, we want to call `POP_RDI` pointing to the **addres** of _"/bin/sh"_ \(`BINSH`\) and call **system** function \(`SYSTEM`\) because the address of _"/bin/sh"_ will be passed as a parameter.
Finally, the **address of exit function** is **called** so the process **exists nicely** and any alert is generated.
**This way the exploit will execute a** _**/bin/sh**_**shell.**
You could also use [**ONE\_GADGET** ](https://github.com/david942j/one_gadget)to obtain a shell instead of using **system** and **"/bin/sh". ONE\_GADGET** will find inside the libc library some way to obtain a shell using just one **ROP address**.
However, normally there are some constrains, the most common ones and easy to avoid are like `[rsp+0x30] == NULL` As you control the values inside the **RSP** you just have to send some more NULL values so the constrain is avoided.