Защитись и замети! Коваленко Дмитрий aka Ingrem Спецвыпуск Xakep, номер #045, стр. 045-068-3 Слово предоставляется канарейке, или Что делать, если ничего не помогло Но теперь предположим такую ситуацию. Допустим, перед записью в буфер ты почему-то не можешь явно задать или проверить длину данных. Что тогда? Оставить дырку, надеясь, что ее никогда не найдут? При таком раскладе я могу тебе посоветовать простой способ защиты. Его называют защитой на основе canary word. Суть его вот в чем: еще при объявлении буфера его делают на 4 байта больше. "Лишние" 4 байта в конце буфера используются для контроля его целостности. Перед тем как записывать что-либо в буфер, генерируется случайное двойное слово – так называемое canary word, которое заносится одновременно в глобальную переменную и в последние 4 байта буфера. Теперь, если при записи в буфер произойдет переполнение, canary word в конце буфера будет затерто кодом эксплоита: Глобальная переменная при этом не пострадает. Так что после записи в буфер достаточно сравнить canary word в глобальной переменной с canary word в буфере. Совпадают – все оk, нет – буфер переполнен, ахтунг! Теперь возьмем то несчастное приложение, которое мы пытались уберечь от переполнения строкой. Чтобы защитить буфер с помощью canary word, достаточно добавить пару строчек в исходный код уязвимой процедуры: Листинг static DWORD CanaryWord; int overflow_proc(char* big) { char buff[10+4]; CanaryWord = GetTickCount(); *((DWORD*)&buff[11]) = CanaryWord; strcpy(buff, big); if(*((DWORD*)&buff[11])!=CanaryWord) { MessageBox(0, "Buffer overflow detected!", \ "Warning!", MB_OK+MB_ICONWARNING); ExitProcess(0); }; return 0; } Как видишь, все элементарно. Сначала получаем сanary word. Для этого используем API GetTickCount, которая возвращает количество микросекунд, прошедших с момента включения компьютера. Это значение, конечно, не случайное, но предсказать его заранее абсолютно точно почти нереально. Затем сanary word заносится в глобальную переменную CanaryWord и в последние 4 байта буфера. Производится чтение в буфер. Сразу после чтения, до return, сравнивается CanaryWord и последние 4 байта в буфере. Если результат сравнения положительный – буфер не переполнен. Если отрицательный – выдадим сообщении о возможной атаке и завершим работу программы. Для завершения используем API ExitProcess. Этот и другие исходники к первой части ты можешь найти на диске, прилагающемся к журналу. Вот и все :-). Немного экзотики: неисполняемый стек 5 правил безопасного программирования Отпечатать крупными буквами и повесить над монитором! 1. Перед тем как скопировать строку в буфер, проверяй ее длину. 2. Везде, где только можно, пользуйся безопасными функциями для работы со строками. 3. Проверяй или явно указывай длину данных, которые записываешь в буфер. |