Конечно, нам нужно решить упражнение PRACTICA_44, но мы будем решать его в следующих частях. Сейчас мы увидим дополнительную информацию, которую мы можем получить используя WINDBG внутри IDA. Мы будем использовать предыдущий случай PRACTICA 41B, про который мы знаем, что это переполнение кучи.
Мы перейдём от отладчика IDA к WINDBG и убедимся, что он находится в режиме USER через DEBUGGER OPTIONS.
Мы меняем GFLAGS для того, чтобы процесс имел включенный PAGE HEAP в режиме FULL.
И я запускаю скрипт SCRIPT2.
Но на этот раз, когда программа останавливается, я присоединяю IDA к анализу PRACTICA41B загруженного в ЗАГРУЗЧИК и конечно в режиме отладки USER WINDBG.
Логично, что программа будет падать, как и прежде, когда она пытается записать за пределы выделенного блока и переполнить его.
Разумеется, для этого необходимо сконфигурировать WINDBG внутри IDA. В любом случае, если у вас возникли проблемы с установкой WINDBG и IDA не распознает его, вы можете присоединить WINDBG за пределами IDA и набирать команды там. У Вас не будет интерфейса IDA, но вы будете получать ту же информацию.
Хорошо. WINDBG имеет много полезных команд для исследования кучи. Я думаю, что для работы с кучами, этот интерфейс является наиболее полными.
Эта команда очень полезна. Она просто работает полностью с включенным режимом PAGE HEAP FULL. И мне сообщается размер выделенного блока, который использует программа или занят (не свободный) и сообщает мне историю мест, где это произошло, когда этот блок был выделен.
Если бы мы выполнили ту же команду в блоке, который был освобожден или свободен, команда покажет нам историю тех мест где был освобождён блок.
Распределение приходит из адреса: 002411AC PRACTICA41B+ 0x000011AC
И выше, в списке истории, программа похоже вызывает функцию MALLOC. Затем идет внутренний вызов RTLALLOCATEHEAP и т.д.
Ниже, в списке истории у нас есть такой вызов 0024109D PRACTICA41B+0x0000109D
Команда помечает адреса возврата вызовов куда входила программа, чтобы выделить блоки.
Команда показывает USER ADDRESS, который является начальным блоком для USER, где он может быть записан. Этому предшествует заголовок блока.
На веб-страницы MICROSOFT мы видим информацию о заголовке, в данном случае, информацию о кучи в режиме FULL PAGE . Заголовок начинается с байтов ABCDBBBB и заканчивается байтами DCABBBBB. Давайте посмотрим, увидим ли мы это непосредственно перед началом, где мы писали.
С помощью команды DT WINDBG, за которой следует _DPH_BLOCK_INFORMATION, команда будет выдавать нам информацию о полях заголовка.
Если мы пойдем по адресу, который указывает STACK TRACE .
Немного ниже сохраняется история распределения. Это соответствует тому, что нам дала команда.
!heap –p –a xxx
Теперь мы докажем, какую информацию дает нам команда, когда мы используем её с нормальной кучей.Очевидно, это будет не так специфично и не будет иметь истории каждого блока, но это хорошо.
Я выключаю режим PAGE GUARD FULL.
Я запускаю скрипт снова и когда программа остановится, я присоединяю снова IDA с анализом и локальным отладчиком WINDBG, как и раньше.
Логически, мы не имеет ту же информацию и программа падает, когда она переходит к выполнению. Давайте посмотрим нашу кучу.
Статистики кучи такая.
Если мы пойдем в область где перешла программа, смотря на стек, мы понимаем, что она приходит отсюда.
И регистр EBP не меняется и поскольку мы знаем программу, мы будем делать чит, смотря на значение буфера, которое мы передали в функцию GETS_S, которое является началом выделенного блока потому. Теперь программа копирует его. Он передается в качестве агумента (очевидно мы можем это сделать, потому что это простая программа и для учебы, в противном случае, мы должны включить PAGE GUARD и делать то что мы видели раньше)
Переменная BUF продолжает указывать на начало кучи. Поэтому мы можем пойти туда.
BLOCK LIST ENTRY поломан. Мы знаем это.
Очевидно, поскольку все поломано, мы постараемся присоединиться прежде чем куча сломается, чтобы увидить информацию о блоке. Хорошо. Я не могу запустить его непосредственно в IDA, потому что он запускается в режиме отладки в куче. Поэтому я буду помещать байты EB FE, чтобы программа зациклилась и когда я запущу его, я буду присоединиться к нему.
Я буду изменять байты 74 18 условного перехода на байты EB FE. После изменения я выбираю EDIT → PATCH PROGRAM → APPLY PATCH TO INPUT FILE.
Сейчас я запускаю скрипт. Как только он зациклится, я останавливаюсь здесь. Но поскольку я уже прошел через MALLOC я уже могу увидеть кучу.
После выделения, в регистре EAX остается адрес блока.
Давайте посмотрим, что скажет нам команда.
USER как всегда является частью где Вы можете писать, а ENTRY это где начинается заголовок. Посмотрим на них.
Команда показывает только одну кучу, и вот где она. Давайте посмотрим её содержимое.
Если мы посмотрим в список, там будет блок. Если мы найдем его по адресу заголовка, то программа сообщит нам его размер.
Он больше не показывает нам историю, хотя, если размер, общий размер равен 0xF, потому что, чтобы найти общее количество, программа умножает на 8, что даёт нам.
hex\(0xf \* 0x8\)
'0x78'
Это полный размер с заголовком и концевиком и т.д.
В случае нормальной кучи, чтобы увидеть значения, мы должны использовать такую команду.
Проблема заключается в том, что они закодированы (XOR) константой. Где мы можем найти константу чтобы раскодировать(UNXOR) их.
Мы видим, что поле смещению 0x50 структуры кучи называется ENCODING
Мы можем создать небольшую таблицу. Очевидно, мы сломаем программу и не сможем запустить её больше, но один раз это можно сделать.
Я заменяю значения, чтобы зашифровать.
Поскольку, в этом случае размер равен 0xF, мы должны умножить его на 8, чтобы найти общие размер и это даёт мне 0x78. То же самое у меня получилось в начале где включен заголовок и концевик.
Хорошо. Мы медленно наблюдаем и знакомимся с блоками кучи. В следующий раз, мы увидим, что MONA расскажет нам об этом. Поможет она нам или нет.
Автор оригинального текста — Рикардо Нарваха.
Перевод и адаптация на английский язык — IvinsonCLS.
Перевод и адаптация на русский язык — Яша Яшечкин.
Перевод специально для форума системного и низкоуровневого программирования - WASM.IN