LINUX.ORG.RU

Си. Почему бы не запретить запись в стек?

 


1

4

Решил немного разобраться как работают уязвимости. Как я понял, весомая их часть модифицирует стек.

#include <stdio.h>

register long unsigned rsp asm("rsp");

void print_arg(int arg) {
    ((int*)rsp)[3] = 0xBADC0DE;
    printf("arg = %x\n", arg);
}

int main(int argc, char **argv) {
    print_arg(0xF00D);
    return 0;
}

Этот код отрабатывает и не выводит ошибкок с

-fhardened -fcf-protection=full

На мой взгляд выглядит небезопасно.

Почему бы не вставлять проверки на ассемблере при записи в память, на включаемость в регион стека? Если нужно записать что то в аргумент на стеке (int), то проверку можно не вставлять. При записи по указателю, уже обязательно вставлять. Если адрес стека то ошибка. В memset проверять пересечение двух диапазонов.

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

void read_file(const char *name)
{
        char buff[999];
        FILE *f = fopen(name, "rb");
        read_block(f, buff);
}

void read_block(FILE *f, char *buff)
{
        // тут компилятор должен вывести что len(buff) == 999
        fread(buff, 1, 9999, f);
}

Что бы все идеально работало, нужно будет:

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

Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от anonymous

Какой океан? Будь точней, технический форум всё таки. В треде специалисты явно, один ты как домохозяйка какая-то.

Шутка

Объясню вам на понятном для вас языке.
Это как НАСРАТЬ в тред.

Forum0888
()
$ cat foo.c
#include <stdio.h>

register long unsigned rsp asm("rsp");

void print_arg(int arg) {
    ((int*)rsp)[3] = 0xBADC0DE;
    printf("arg = %x\n", arg);
}

int main(int argc, char **argv) {
    print_arg(0xF00D);
    return 0;
}

$ gcc -O3 -fstack-protector-all foo.c
$ ./a.out
arg = f00d
*** stack smashing detected ***: terminated
zsh: IOT instruction  ./a.out

На -O1 оно не срабатывает, потому что ты перезаписываешь rbp в стеке или ещё какую-то ерунду.

А ты придумал на каждое обращение к памяти вставлять какие-то проверки, как valgrind. Это будет очень медленно (valgrind исполняет код “10-50 times slower than natively”).

shdown
()
Ответ на: комментарий от MOPKOBKA

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

watchcat382
()
Ответ на: комментарий от shdown

На -O1 оно не срабатывает, потому что ты перезаписываешь rbp в стеке или ещё какую-то ерунду.

Надо просто подобрать адрес, главное что так можно сделать.

А ты придумал на каждое обращение к памяти вставлять какие-то проверки, как valgrind.

Не на каждое.

MOPKOBKA ★★★★★
() автор топика
Ответ на: комментарий от alysnix

сегменты вводили как хак

Это на 8086 они - хак. А уже на 286 - это средство управления защитой памяти. У него правда сегменты маленькие были и это было неудобно. На 386 и далее они уже 4 гига,чего вполне достаточно в абсолютном большинстве случаев.

наступила другая эпоха. эпоха длинного адреса.

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

watchcat382
()
Ответ на: комментарий от MOPKOBKA

Надо просто подобрать адрес, главное что так можно сделать.

Что можно сделать? Затереть отладочные данные на стеке специальной инструкцией? Можно, но fstack-protector работает только с адресами возврата на стеке (которые пишутся инструкцией call и читаются инструкцией ret). В этом, кажется, и смысл твоей задумки, по крайней мере, я не понимаю, в чём ещё она заключается.

Не на каждое.

Ну почти каждое.

void f(int *a)
{
    *a = 1;
}
тут будет?

shdown
()
Последнее исправление: shdown (всего исправлений: 1)
Ответ на: комментарий от MOPKOBKA

Что можно сделать?

Эксплойт.

Ну так покажи эксплойт кода, собранного с -fstack-protector-all. Твой код не работает (либо перезаписывает не то, либо, если перезаписывает то, валится с “stack smashing detected”).

Да.

Отлично, почти любое обращение к памяти оборачиваем в кучу проверок. Как мне FFT написать теперь, оно будет люто тормозить или что?

shdown
()
Ответ на: комментарий от shdown

Ну так покажи эксплойт кода, собранного с -fstack-protector-all.

https://godbolt.org/z/MdfWYxTP7

Как мне FFT написать теперь, оно будет люто тормозить или что?

Пиши как и прежде, не заботясь о безопасности.

MOPKOBKA ★★★★★
() автор топика
Ответ на: комментарий от MOPKOBKA

https://godbolt.org/z/MdfWYxTP7

Даже не знаю, что тут можно сказать. Ты перезаписал данные, которые код может перезаписывать. Твои проверки тут бы никак не спасли, потому что это валидная операция (вместо ((int*)rbp)[-3] = 0xBADC0DE; можно написать isAdmin = 1;).

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

shdown
()
Ответ на: комментарий от shdown

Конечно не предполагается что в коде будет *rbp = 0xBADCODE, вместо этого должен быть fread() который читает дальше буфера. Или например ошибка при вычисление индекса.

MOPKOBKA ★★★★★
() автор топика
Последнее исправление: MOPKOBKA (всего исправлений: 1)
Ответ на: комментарий от shdown

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от anonymous

И просьба - не сри много в ЛОР.

Откуда я знал, что всё долетает до ЛОРа?! Я думал большинство сообщений оседает в дороге… Пардон кнешно 🤔️

anonymous
()
Ответ на: комментарий от MOPKOBKA

Какой ещё *rbp, при чём тут регистр rbp? Как не предполагается, если ты раньше ответил, что хочешь вставлять проверки в код

void f(int *a)
{
    *a = 1;
}
? Какой fread, который читает дальше буфера. Какая ошибка при вычислении индекса, ты хочешь и в арифметику над указателями вставить проверки или что, я не понимаю.

shdown
()
Ответ на: комментарий от alysnix

Ну да, так и есть. Он ещё скачет по идеям абсолютно хаотично. До каких-то сегментов дошёл (в изначальном тексте топика вообще нет такого слова). «компилятор должен вывести что len(buff) == 999» — невозможно это в общем случае, проблема останова, а если компилятор может что-то выводить, то в чём смысл его идеи? Можно просто засунуть повсюду проверку границ.

shdown
()
Последнее исправление: shdown (всего исправлений: 3)
Ответ на: комментарий от Forum0888

Раз дцать детально объяснял и приводил примеры

Не помню вообще ни одного раза. Это всегда была бестолковая вода в виде мутных словес про метаданные, апи и «[вставить_рандомное_слово] любой сложности». Детальное объяснение - это пример как минимум входных данных и кода, который их обрабатывает, с описанием результата.

arkhnchul ★★★
()
Ответ на: комментарий от arkhnchul

Это всегда была бестолковая вода в виде мутных словес про метаданные,

Для вас это «бестолковая вода» потому, что не понимаете в чём
профит от возможности в run-time создавать динамически объекты о которых компилятор ничего не знает.

То о чём сегодня говорил понятно?
Хотя бы в чём профит такого API?

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 3)
Ответ на: комментарий от Forum0888

Реализуется это приблизительно так.

- дополняем в линкер и загрузчик требуемую функциональность;

- добавляем в core необходимый API

«- А как именно вы, мышки, станете ежиками - это уже ваши проблемы, я стратегией занимаюсь.»(с)

arkhnchul ★★★
()
Ответ на: комментарий от Forum0888

То о чём сегодня говорил понятно?

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

ну начнем с простого. Ты говоришь что-то типа

Объект может быть: 2D, 3D, звук, конфигурация 1С, Excel, …

что такое «объект … 2D»? Я могу выдать наверно с десяток описаний, означающих разные вещи, и ко всем им подойдет философская категория «двумерный объект».

arkhnchul ★★★
()
Ответ на: комментарий от arkhnchul

Вы совершенно «не в теме».
Зачем судите о том в чём не БУМ БУМ?

У меня например были ранее годами реальная разработка, которая позволила ОСРВ для М6000, СМ1-М, СМ-2М, ... сделать многозадачной.

Так вот то над чем вы смеётесь было реализовано.
И функциональность кода загрузчика была расширена, ...

Для вас то о чём говорю «ёжики».
То бишь вы просто не БУМ БУМ о чём речь и как решаются такие задачи.
А щёки любите надувать.

Нельзя же так ...

Forum0888
()
Ответ на: комментарий от arkhnchul

У вас хоть какой-то опыт имеется для работы с 2D и 3D графикой?
Что такое модель, ...

Поиском поищите типа «объект для 3d», ...

https://www.sound-objects.com/ Звуковые Объекты

Ведь вы просто не в теме, да ещё возмущаетесь.
Эти элементарные термины вам не понятны.

Почитайте что такое: COM, OLE, ...

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 2)
Ответ на: комментарий от Forum0888

У вас хоть какой-то опыт имеется для работы с 2D и 3D графикой?

да. И именно поэтому я могу сопоставить «объект 2D» с множеством весьма и весьма разных сущностей, каждая из которых будет так или иначе являться таковым объектом.

arkhnchul ★★★
()
Ответ на: комментарий от Forum0888

Почитайте что такое: COM, OLE, …

воооот, хоть какая-то конкретика пошла наконец. Ты переизобретаешь COM/OLE - ака возможность использовать в своей софтине внешние «объекты» в понимании ООП, с инкапсуслированным состоянием и торчащими наружу методами/API, которые можно дергать для управления сим объектом?

arkhnchul ★★★
()
Ответ на: комментарий от arkhnchul

Не фантазируйте.
Вы простых вещей не поняли, а теперь что-там своё домысливаете.

Хотя в чём -то вы и правы.
Типа все компиляторы ОДИНАКОВЫ.

Перечитайте о чём в постах говорилось.
Об 1С почитайте что-нибудь.
Конфигурации как раз и есть одной из разновидностью метаданных.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 1)
Ответ на: комментарий от arkhnchul

Нет конечно.

К примеру возьмём любую конфигурацию 1С.
Она содержит метаданные о логическом формате представления объектов.
А вот когда вы открываете конфигурацию, то метаданные используются для создания объектов в run-time для работы с их данными.
Например имеются метаданные о Документе.
На основании их вы можете создать десятки документов разного типа.
Но их формат представления задан с помощью метаданных.

Гм., это же азбука ...

Для того, чтобы понять о чём говорил в постах нужно многое знать.
В противном случае оппонент считает это каким-то бредом.
Потому и говорю, что вы «не в теме» и для вас, сказанное - ПОЛНЫЙ БРЕД.

К примеру у вас имеется опыт в использовании в разработке проектов с использованием COM, OLE, ActiveX, ...?
Мне приходилось годами использовать эти технологии для разработки.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 9)
Ответ на: комментарий от shdown

https://godbolt.org/z/Pd5Thnfo7

Какая ошибка при вычислении индекса, ты хочешь и в арифметику над указателями вставить проверки или что, я не понимаю.

При любом чтении/записи по указателю да.

MOPKOBKA ★★★★★
() автор топика
Последнее исправление: MOPKOBKA (всего исправлений: 2)
Ответ на: комментарий от arkhnchul

Нет.

Не ООП точно, но много более функционально однозначно.

Гм., вот подумал о том, что non problem добавить API для поддержки а-ля ООП.

У меня поддержан C++ struct и расширенный, который имеет например данные о семантике полей (любой сложности), ...
Поэтому для API интроспекция и рефлексия это «обыденность».
То бишь вы можете создать метаданные скажем для представления архитектуры данных mongedb и без участия компиляторов работать с данными базы.
Метаданные являются логическим описанием объектов.

Не ну правда, почитайте например об 1С и что такое конфигурация.
Хотя конечно это всего лишь один из способов логического представления архитектуры базы данных.

Пока рано публиковать.
Реализовал лишь процентов пять от планируемого.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 10)
Ответ на: комментарий от MOPKOBKA

https://godbolt.org/z/Pd5Thnfo7

А твои проверки спасут от такого fread/strcpy/…? Если да, то как?

Я вот нихрена не понимаю, что конкретно ты предлагаешь. Судя по топику, остальные тоже не понимают. Описать идею внятно ты не можешь (судя по всему, у тебя её и нет). По топику понятно, что у тебя в голове полная каша. Этому не помогает то, что ты уходишь от ответов на прямые вопросы, избирательно цитируешь вопросы.

shdown
()
Последнее исправление: shdown (всего исправлений: 1)
Ответ на: комментарий от Forum0888

Не ООП точно, но много более функционально однозначно.

я вот тоже ваших развесистых терминов не понмаю… у вас что, типа есть читатель неких метаданных, что по ним генерит код, например на с++, и напускает на него плюсовый компилятор? типа так?

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

alysnix ★★★
()
Последнее исправление: alysnix (всего исправлений: 1)
Ответ на: комментарий от Forum0888

У вас хоть какой-то опыт имеется для работы с 2D и 3D графикой? Что такое модель, …

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

alysnix ★★★
()
Ответ на: комментарий от shdown

А твои проверки спасут от такого fread/strcpy/…? Если да, то как?

Да.

Я вот нихрена не понимаю, что конкретно ты предлагаешь.

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

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

MOPKOBKA ★★★★★
() автор топика
Последнее исправление: MOPKOBKA (всего исправлений: 1)