Используйте переполнение кучи для записи произвольных данных

Я пытался изучить основы атаки переполнения кучи. Меня больше всего интересует использование коррупции или модификация метаданных fragmentа для основы атаки, но я также открыт для других предложений. Я знаю, что моя цель эксплоита должна быть переписана указателем на функцию printf() с указателем функции challenge() , но я не могу понять, как добиться этой записи. У меня есть следующий fragment кода, который я хочу использовать, который использует malloc из glibc 2.11.2 :

 void challenge() { puts("you win\n"); } int main(int argc, char **argv) { char *inputA, *inputB, *inputC; inputA = malloc(32); inputB = malloc(32); inputC = malloc(32); strcpy(inputA, argv[1]); strcpy(inputB, argv[2]); strcpy(inputC, argv[3]); free(inputC); free(inputB); free(inputA); printf("execute challenge to win\n"); } 

Очевидно, что достижение фактической перезаписи метаданных выделенного fragmentа является тривиальным. Однако я не смог найти способ использовать этот код, используя любой из стандартных методов. Я прочитал и попытался реализовать методы из:

  • Бумага: w00w00 при переполнении кучи
    • Несмотря на то, что бумага очень понятна, технология unlink устарела в течение некоторого времени.
  • Malloc Maleficarum.txt
    • Эта статья расширяет методы эксплойтов из w00w00 дней и учитывает новые версии glibc. Тем не менее, я не нашел, что, учитывая 5 методов, подробно описанных в документе, код выше соответствует любому из предпосылок для этих методов.
  • Понимание кучи, разбивая его (pdf)
    • В pdf-файле дается довольно хороший обзор того, как работает куча, но фокусируется на двойных бесплатных методах.

Первоначально я пытался использовать этот код, манипулируя величиной размера блока для inputC, чтобы он обратил внимание на главу блока inputC. Когда это не сработало, я попытался еще раз вернуться к блоку ввода B. Именно тогда я понял, что новый glibc выполняет проверку работоспособности по размеру.

Как пользователь может воспользоваться эксплойтом, чтобы воспользоваться бесплатным, считая, что у него есть возможность редактировать метаданные выделенного fragmentа на произвольные значения, и пользователь может перезаписать значение в GOT или записать на любой другой произвольный адрес?

Примечание. Когда я пишу «произвольный адрес», я понимаю, что страницы памяти могут быть только для чтения или защищены, я имею в виду адрес, который, как я могу предположить, могу писать.

Примечание. Прежде чем ответить, я скажу, что это чисто академический ответ, который не предназначен для использования в злонамеренных целях. Я знаю об упражнениях, которые выполняет OP, и они являются открытыми исходными кодами и не предназначены для поощрения пользователей использовать эти методы в неутвержденных обстоятельствах.

Я подробно расскажу о технике ниже, но для вашей справки я бы взглянул на трюки Vudo malloc (на них ссылаются в одной из ваших ссылок выше), потому что мой обзор будет коротким: http://www.phrack.com /issues.html?issue=57&id=8

В нем подробно описывается, как malloc обрабатывает создание блоков памяти, вытягивая память из списков и других вещей. В частности, для этой атаки интерес представляет атака разблокировки (примечание: вы правы, что glibc теперь выполняет проверку работоспособности по размерам по этой конкретной причине, но вы должны быть старше libc для этого упражнения … legacy bro).

Из статьи выделенный блок и свободный блок используют одну и ту же структуру данных, но данные обрабатываются по-разному. Посмотреть здесь:

 chunk -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | prev_size: size of the previous chunk, in bytes (used | | by dlmalloc only if this previous chunk is free) | +---------------------------------------------------------+ | size: size of the chunk (the number of bytes between | | "chunk" and "nextchunk") and 2 bits status information | mem -> +---------------------------------------------------------+ | fd: not used by dlmalloc because "chunk" is allocated | | (user data therefore starts here) | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | bk: not used by dlmalloc because "chunk" is allocated | | (there may be user data here) | + - - - - - - - - - - - - - - - - - - - - - - - - - - - - + | | | | | user data (may be 0 bytes long) | | | | | next -> +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+ | prev_size: not used by dlmalloc because "chunk" is | | allocated (may hold user data, to decrease wastage) | +---------------------------------------------------------+ 

Выделенные блоки не используют указатели fd или bk, но бесплатные. Это будет важно позже. Вы должны знать достаточно программирования, чтобы понять, что «блоки» в malloc Дага Ли организованы в двусвязный список; есть один список бесплатных блоков, а другой для выделенных (технически есть несколько списков бесплатно в зависимости от размеров, но здесь это не имеет значения, поскольку код выделяет блоки одного размера). Поэтому, когда вы освобождаете определенный блок, вам нужно исправить указатели, чтобы сохранить список в такте.

например, скажите, что вы освобождаете блок y из приведенного ниже списка:

 x <-> y <-> z 

Обратите внимание, что на диаграмме выше пятна для bk и fd содержат необходимые указатели для повторения по списку. Когда malloc хочет взять блок p из списка, он вызывает, среди прочего, макрос для исправления списка:

 #define unlink( y, BK, FD ) { BK = P->bk; FD = P->fd; FD->bk = BK; BK->fd = FD; } 

Сам макрос не трудно понять, но в старых версиях libc важно отметить, что он не выполняет проверки работоспособности по размеру или указателям, на которые написано. В вашем случае это означает, что без какой-либо случайной рандомизации вы можете outlookировать и надежно определять статус кучи и перенаправлять произвольный указатель на выбранный вами адрес путем переполнения кучи (через strncopy здесь) определенным образом ,

Есть несколько вещей, необходимых для того, чтобы атака работала:

  • указатель fd для вашего блока указывает на адрес, который вы хотите перезаписать минус 12 байтов. Смещение должно выполняться с malloc, очищающим выравнивание, когда оно изменяет список
  • Указатель bk вашего блока указывает на ваш shellcode
  • Размер должен быть -4. Это выполняет несколько вещей, а именно устанавливает биты состояния в блоке

Поэтому вам придется играть со смещениями в вашем конкретном примере, но общий вредоносный формат, который вы пытаетесь передать с помощью strcpy, имеет формат:

| нежелательный для заполнения законного буфера | -4 | -4 | addr вы хотите перезаписать -12 (0x0C) | addr, вы хотите позвонить

Обратите внимание, что отрицательное число устанавливает поле prev_size равным -4, что делает свободную маршрутизацию верной, что кусок prev_size фактически начинается в текущем блоке, который вы контролируете / развращаете.

И да, правильное объяснение не будет полным без упоминания, что эта атака не работает с текущими версиями glibc; размер имеет проверку работоспособности, и метод unlink просто не работает. Это в сочетании с смягчениями, такими как рандомизация адреса, делает эту атаку нежизнеспособной ни на чем, кроме устаревших систем. Но метод, описанный здесь, – это то, как я сделал эту задачу;)

Обратите внимание, что большинство методов, описанных в Malloc Malleficarum, теперь защищены. Glibc значительно улучшил все эти двойные бесплатные сценарии.

Если вы хотите улучшить свои знания о методах Malloc Malleficarum, прочитайте Malloc Des-Malleficarum и Дом Знаний: Reloaded, написанный blackngel. Эти тексты можно найти в phrack.

Malloc Des-Malleficarum

Я также работаю над этим, и я могу сказать вам, что, например, House of Mind больше не эксплуатируется, по крайней мере, как объясняется в текстах. Хотя можно было бы обойти новые ограничения, добавленные в код. Добавьте, что самый простой способ выполнить ваш код – перезаписать адрес .dtors, поэтому ваш код будет всегда выполняться после завершения программы.

Если вы загружаете код glibc и изучаете критические зоны malloc. И т. Д., Вы найдете проверки кода, которые не документированы в ранее упомянутых документах. Эти проверки были включены, чтобы остановить двойную бесплатную вечеринку.

С другой стороны, презентация Джастина Н. Фергюсона («Понимание кучи, разбивая ее»), которую вы можете найти на YouTube (BlackHat 2007), идеально подходит для понимания всей механики кучи, но я должен признать, что показанные методы далеки от надежности, но, по крайней мере, он открывает новое поле для эксплуатации.

Понимание кучи, разбив ее

В любом случае, я также работаю над этим, поэтому, если вы хотите связаться со мной, мы можем поделиться своими достижениями. Вы можете связаться со мной в домене overflowedminds.net как newlog (самостоятельно создайте адрес электронной почты ^^).

Переполнение кучи сложно сделать, и они очень сильно зависят от кучи, хотя похоже, что вы идете после кучи Windows CRT, которая имеет множество смягчений, специально предназначенных для прекращения этого типа атаки.

Если вы действительно хотите это сделать, вам нужно радоваться прыжкам в WinDbg и вступать в такие функции, как свободно, чтобы точно видеть, что происходит внутри свободно, и, следовательно, какой контроль вы могли бы достичь через кучу переполнение предыдущего значения.

Я не дам вам более конкретной помощи, чем по той простой причине, что демонстрация переполнения кучи обычно достаточна для защитной безопасности. Защитные эксперты по безопасности могут сообщать о переполнении кучи, не требуя в полной мере использовать ее. Единственные люди, которым нужно полностью использовать переполнение кучи вплоть до удаленного выполнения кода, – это люди, использующие ошибки в нападении , и если вы хотите это сделать, вы сами по себе.