All streams
Search
Write a publication
Pull to refresh

Comments 30

Скрытый текст

О чем статья? Что хотел сказать автор? Что существуют небезопасные функции, которые приводят к уязвимостям в коде? Или это статья от ИИ🤔?

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

Зачем вы жирным пишете?

memcpy + '\0' с проверкой размера

Люди не зря же придумали strncpy. Можно передать длину на 1 меньше - будет человекочитаемо.

Да, но у strncpy тоже свои подводные камни — она может не дописать '\0', и тогда придётся вручную проверять. Поэтому многие используют memcpy + ‘\0’ с контролем размера.

Не может, если использовать n-1. Вы все равно точно так делаете, только замороченно.

Именно. strncpy задумывалась под fixed-size поля, а не как безопасная замена strcpy. Поэтому предсказуемее и быстрее самому сделать memcpy + '\0' с контролем размера, чем ловить сюрпризы.

В вашем сценарии strncpy имеет сложность O(1) - так как скопируется не больше 32 байт, а вот предложенный вами алгоритм - O(n), где n - длина входных данных, так как вычисление strlen - О(n).

Как выше уже написали, понятно как написать понятный и безопасный код с использованием strncpy.

А ваш код получается более многословным, зато с заведомой ухудшенной асимптотикой

Чего не придумают лишь бы не вычислять n-1

Можно после strncpy безусловно класть 0 в sizeof(buf) - 1. Будет две простые строчки вместо своего алгоритма копирования, где выше риск ошибки

У нас на работе принято snprintf, не знаю насколько она прожорливее, но точно безопаснее, но некоторые возмутятся зачем вообще копировать, если есть слайсы и Rust

Сегодня я узнал, что, ура, можно не проверять буфер и RCE всё равно не будет. Как камень с души.

(Не уверен, что это то, что хотел донести до меня автор).

Не совсем 🙂 Защиты мешают сделать RCE, но переполнение всё равно = баг: краши, утечки, нестабильность. Проверять буфер надо обязательно — тем более защиты не идеальны, их иногда удаётся обходить в связке с другими ошибками.

#include <stdio.h>
#include <string.h>

void greet(const char *name) {
    char buf[8];
    strcpy(buf, name); // переполнение
    printf("Привет, %s\n", buf);
}

int main(int argc, char **argv) {
    greet(argc > 1 ? argv[1] : "user");
    return 0;
}

Даже если включены ASLR, NX, canaries и прочие защиты:

1) при вводе строки длиннее 8 символов программа гарантированно упадёт (Segfault);

2) это уже отказ в обслуживании (DoS);

3) а в отчёте об ошибке или дампе памяти может утечь лишняя информация (например, кусок стека)

так правильно если я правильно понял, теперь тут надо проверку написать и написать что случилось, и получается суть сводится к тому что при том когда сигфалт перед ним надо очистить память и очистить ресурс и закрыть или написать что случилось, тоесть придётся делать проверки на переполнение и или обрабатывать или падать

Да, суть в этом: сигфолт — уже поздно что-то чистить. Нужно не допускать переполнения: проверять длину, корректно завершаться и освобождать ресурсы в ветке ошибки

Сегфолта при небольшом переполнении может и не быть

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

Не раскрыта тема проверки корректности адресов возврата/перехода в железе (Intel CET, ARM PAC/BTI).

Кликбейтный заголовокг а в тексте просто пшик. В чем эксплойт? Ну вылетела программа. Ну поймали стектрейсом. А как это проэксплуатировать? Да ни как. Это и близко не эксплойт.

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

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

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

#include <stdio.h>

#include <string.h>

char buf[32] = {0}; // {0} - заполнение гарантирует ноль в конце

void greet(const char *name) {
    memcpy(buf, name, sizeof(buf-1));
    printf("hi, %s\n", name); // пример был хорош
}

int main(int argc, char **argv) {
    const char *name = (argc > 1) ? argv[1] : "world";
    greet(name);
    return 0;
}

Простите за глупый вопрос. Но с учит только в информационной безопасности или компьютер инженеринг

Sign up to leave a comment.

Articles