Защитись и замети! Коваленко Дмитрий aka Ingrem Спецвыпуск Xakep, номер #045, стр. 045-068-6 Функция сначала находит длину строки, которую нужно скопировать. Затем с помощью двух последовательных сдвигов на 1 бит вправо нацело делит эту длину на 4 – получается размер строки, выраженный в двойных словах. Правда, полученный размер обязательно кратен 4, поэтому, если длина строки не делится нацело на 4, теряется остаток ("хвостик" строки в 1, 2 или 3 байта длиной). Происходит копирование строки двойными словами; его выполняет инструкция по адресу 0x0047366A. Затем функция путем обнуления старших 30 битов ecx находит остаток от деления длины строки на 4 (потерянный при предыдущем копировании "хвостик") и копирует его уже побайтно. Такой идиотский, на первый взгляд, код генерируется компилятором С++ для увеличения скорости. Заметим, что функция никак не контролирует длину копируемой строки – отсюда, очевидно, и переполнение буфера. Теперь посмотрим в IDA код, который вызвал эту процедуру перед аварийным завершением программы. Идем на адрес 0x00453D69 (мы его выловили отладкой, помнишь?) и видим там вот что: Листинг loc_453D62: ; CODE XREF: sub_453D20+6j .text:00453D62 push edx; .text:00453D63 push ecx; .text:00453D64 call sub_473648; >-- сравнение строк .text:00453D69 add esp, 8 ...... В CODE XREF – единственная ссылка. Кликаем по ней, приходим к следующему: Листинг .text:00453D20 sub_453D20 proc near ; CODE XREF: sub_453C95+Fp .text:00453D20 ; sub_453CD6+Fp… .text:00453D20 push ebx .text:00453D21 cmp eax, 80000001h .text:00453D26 jnz short loc_453D62 ...... Смотрим CODE XREF – шесть ссылок: Что ж, не так и много. Вполне можно проверить на отладке. Загружаем WinRAR в Soft-Ice, ставим и временно отключаем брейкпоинт: :bpx 00453D20 :bd * WinRAR загрузился, подводим курсор к 29A.RAR, включаем брейкпоинт. Открываем архив. При каждом всплывании Soft-Ice смотрим на стек и запоминаем адрес, откуда пришел вызов. После тринадцатого всплывания Soft-Ice происходит аварийное завершение. Адрес вызова 0x00453CEA. Опять идем в IDA. Видим процедуру: Листинг .text:00453CD6 var_104 = dword ptr -104h .text:00453CD6 SubKey = byte ptr -100h .text:00453CD6 .text:00453CD6 push ebx .text:00453CD7 add esp, -104h; >-- резервируем буфер (260 байт!) .text:00453CDD mov ebx, eax .text:00453CDF lea ecx, [esp+104h+SubKey] .text:00453CE3 mov eax, ebx .text:00453CE5 call sub_453D20; >-- копирование строки .text:00453CEA push esp ...... .text:00453D05 add esp, 104h .text:00453D0B pop ebx .text:00453D0C retn; >-- управление отдается на 0048671A Загрузим WinRAR в Soft-Ice, поставим и отключим брейкпоинт на 00453CD6, это начало процедуры. Перед открытием 29A.RAR включим брейкпоинт. При первом срабатывании трассируем код до 0x00453CDD, запоминаем адрес выделенного буфера и снимаем брейкпоинт. Потом ставим брейкпоинт на 0x00453CEA. Он будет срабатывать каждый раз, сразу после того как инструкция по адресу 0x00453CE5 вызвала процедуру копирования строки. Смотрим, что скопировалось в буфер. В конце концов в буфере оказывается наше длинное расширение ;-). Нажимая F10, трассируем процедуру до адреса 0x00453D0C и останавливаемся. Смотрим esp. Он указывает на двойное слово 0x0048671A. Вот мы и нашли уязвимость. |