Модуль 0: Інструкція
Основи баз даних та спеціалізовані мови програмування
Ординський Олександр • викладач
ВТФК • Вінниця • 2025
2025
Ця лекція демонструє всі доступні типи слайдів
Лекція -1: Вступ до курсу (приклад)
Вразливість програмного забезпечення, яка виникає, коли програма записує дані за межі виділеного буфера в пам'яті, що може призвести до перезапису сусідніх областей пам'яті та виконання шкідливого коду.
Аналогія: Уявіть склянку води. Якщо ви ллєте воду понад її край, вода потрапляє на стіл і може зіпсувати документи поруч. Так само переповнення буфера "проливає" дані в сусідні області пам'яті.
char *strcpy(char *dest, const char *src);Функція strcpy() не перевіряє розмір буфера призначення:
#include
#include
int main() {
char buffer[8];
char *input = "Це дуже довгий рядок, який не поміститься";
// НЕБЕЗПЕЧНО! Переповнення буфера
strcpy(buffer, input);
printf("Buffer: %s\n", buffer);
return 0;
} Примітка: Цей код призведе до переповнення буфера, оскільки вхідний рядок більший за розмір buffer[8]
void vulnerable() {
char buffer[64];
gets(buffer); // Небезпечна функція!
printf("Input: %s\n", buffer);
}
int main() {
vulnerable();
return 0;
}char buffer[64]; — виділяє 64 байти на стекуgets(buffer); — читає дані БЕЗ перевірки розміруВізуалізація пам'яті під час атаки buffer overflow:
┌──────────────────────┐ ← Вища адреса
│ Адреса повернення │ ← Перезаписується!
├──────────────────────┤
│ Збережений EBP │
├──────────────────────┤
│ Локальні змінні │
├──────────────────────┤
│ buffer[64] │ ← Початок буфера
└──────────────────────┘ ← Нижча адреса■ buffer[64] — виділена область (64 байти)
■ Адреса повернення — ціль атаки
■ Напрямок росту стеку — донизу (до нижчих адрес)
■ buffer[64] — виділена область (64 байти)
■ Адреса повернення — ціль атаки
■ Напрямок росту стеку — донизу (до нижчих адрес)
■ buffer[64] — виділена область (64 байти)
■ Адреса повернення — ціль атаки
■ Напрямок росту стеку — донизу (до нижчих адрес)
gets() — не обмежує розмір вводуstrcpy() — не перевіряє межі буфераsprintf() — може переповнити буферstrcat() — ризик переповненняfgets(buf, size, stdin) — обмежує розмірstrncpy(dest, src, n) — копіює максимум n байтівsnprintf(buf, size, fmt) — обмежує вивідstrncat(dest, src, n) — обмежена конкатенація#include
void vulnerable(char *input) {
char buffer[16];
strcpy(buffer, input);
}
int main(int argc, char *argv[]) {
vulnerable(argv[1]);
return 0;
}
gcc -g -fno-stack-protector vuln.c -o vuln
gdb ./vuln
(gdb) break vulnerable
(gdb) run $(python3 -c 'print("A" * 32)')
(gdb) x/32xw $esp
(gdb) info registers
💡 Порада: Використовуйте x/32xw $esp для перегляду вмісту стеку та виявлення переповнення
Багато розробників забувають додавати +1 для null-термінатора при виділенні пам'яті під рядки
// НЕПРАВИЛЬНО!
char *copy_string(const char *src) {
char *dest = malloc(strlen(src));
strcpy(dest, src);
return dest;
}Виділено недостатньо пам'яті — відсутній байт для '\0'
// ПРАВИЛЬНО!
char *copy_string(const char *src) {
char *dest = malloc(strlen(src) + 1);
strcpy(dest, src);
return dest;
}Додано +1 для null-термінатора '\0' в кінці рядка
Використовуйте різні типи слайдів для кращого засвоєння матеріалу студентами
Напишемо разом програму для перевірки на переповнення буфера з використанням безпечних функцій
Готові? Почали кодити!
Лекція 1: Введення в мову C та управління пам'яттю
Дякую за увагу! 💾