- •Компьютерные преступления методические указания к выполнению практических занятий по учебной дисциплине
- •090301 «Компьютерная безопасность»
- •2.1.1 Классификации механизмов защиты программного обеспечения (по)
- •2.1.2 Исследование программы Denoiser
- •2.1.3 Физические и виртуальные адреса
- •2.1.3 Вопросы для самоконтроля
- •2.2.1 Восстановление с помощью fsck
- •2.2.3 Вопросы для самоконтроля
- •2.3 Практическая работа №3: «Изучение работы Snort - свободной сетевой системы предотвращения вторжений (ips)»
- •2.3.1 Общие положения
- •2.3.2 Установка Snort (Windows xp)
- •2.3.3 Режим снифера
- •2.3.4 Режим регистратора пакетов
- •2.3.5 Режим обнаружения сетевых вторжений
- •2.3.6 Создание собственных правил Snort
- •2.3.7 Написание контекстных правил (подключение препроцессоров)
- •2.3.8 Подключение препроцессора Portscan
- •2.3.9 Вопросы для самоконтроля
- •2.4 Практическая работа №4 «Анализ антивирусного программного обеспечения»
- •2.4.1 Общие положения
- •2.4.2 Классификация антивирусных продуктов
- •2.4.3 Выполнение практической работы
- •2.4.4 Вопросы для самоконтроля
- •2.5 Практическая работа № 5: «Стеганография. Использование программ скрытого шифрования»
- •2.5.1 Основные понятия и определения стеганографии
- •2.5.2 Методы, технологии, алгоритмы
- •2.5.3. Практическая реализация
- •2.5.3.1 Работа с s-Tools
- •2.5.4 Программа ImageSpyer
- •1. Общие положения 1
- •1.1 Цель и задачи практических занятий 1
- •2.3.1 Общие положения 21
- •2.4.1 Общие положения 37
- •Компьютерные преступления методические указания к выполнению практических занятий по учебной дисциплине
- •090301 «Компьютерная безопасность»
- •394026 Воронеж, Московский просп., 14
2.1.3 Физические и виртуальные адреса
Физические адреса соответствуют номерам ячеек оперативной памяти, где в действительности расположены или будут расположены переменные и команды. Переход от виртуальных адресов к физическим может осуществляться двумя способами. Перемещающий загрузчик на основании имеющихся у него исходных данных о начальном адресе физической памяти, в которую предстоит загружать программу, и информации, предоставленной транслятором об адресно-зависимых константах программы, выполняет загрузку программы, совмещая ее с заменой виртуальных адресов физическими[4].
Преобразование адресов. Обычно, программа делится на сегменты – сегмент кода, сегмент данных и дополнительные сегменты, для каждого сегмента существует:
RVA – относительный виртуальный адрес, который используется для корректного обращения к данным в памяти,
PhysOffs физический адрес – смещение сегмента относительно начала файла.
То есть, при загрузке программы весь файл загружается, начиная с адреса VA (virtual address – текущий свободный виртуальный адрес), а каждый сегмент, начинающийся в файле с адреса PhysOffs, помещается с адреса VA+RVA. Поэтому для преобразования физического адреса в виртуальный нам необходимо сделать следующую операцию: VirtualAddress=VA+PhysicalAddress+RVA-PhyssOffs.
Чтобы в QView узнать адрес Image Base VA смотрите в PE-заголовке - при нажатии клавиши F8 (это возможно в режимах «HEX VIEW» и «ASM VIEW», если вы находитесь в режиме «TEXT VIEW» то для переключения в другие режимы нажмите F4).
Перед нами таблица сегментов (см. рисунок 2) :
Сначала нужно определить к какому сегменту относится найденный нами адрес. PhysOffs сегмента «.data» лежит в диапазоне 1B200-1F200, что удовлетворяет нашему адресу 1B368, то есть, строка будет находится именно в этом сегменте. Вычислим ее виртуальный адрес по вышеописанной формуле, он равен 1001D168.
Рис. 2. Таблица сегментов
Теперь попытаемся найти строку содержания «PUSH 1001D168». Для этого перейдем в режим «ASM VIEW», нажимая F4 до тех пор, пока не увидим на экране команды ассемблера. Еще необходимо перевести редактор в 32-битный режим – для этого нажмем F2, чтобы внизу окна рядом с надписью «F2 16/32» - «/32» выделялось черным цветом. Нажав F6, мы вызовем режим ассемблерного поиска, куда введем push 1001D168.
Е сли все сделать правильно, то поиск укажет на строку с адресом 00000B08. Чтобы сделать удобной навигацию по файлу, находясь на этой строке нажмем ALT и «плюс» (но не на цифровой клавиатуре) – это создаст метку указывающую на строку нашу строку (см. рис. 3).
Рис.3. Ассемблерный режим
Функция, которая принимает адрес строки как параметр – не является MessageBox. Скорее всего, это «оберточная функция» языка программирования, на котором написана программа (а написана она на Visual C++). Эта функция в свою очередь, проведя некоторые, не интересующие нас операции над входными данными, в конечном счете вызовет MessageBox… В этом можно убедиться, если нажать комбинацию SHIFT+1 – то есть переход по адресу указанному в CALL.
Так как мы находимся «в хвосте» защитного механизма (точнее в ветке, которая исполняется при неправильно введенном S/N), то теперь нужно найти код, который на эту ветку переключает. То есть, если в выражении
if (S_N==VALID_KEY) goto GOOD;
else goto BAD;
изменить «равно» (==) на «не равно» (!=), то программа будет считать себя зарегистрированной при любых введенных данных, кроме случая, когда вводится правильный S/N.
Итак, продолжаем исследование. Команды выполняются последовательно друг за другом за исключением случаев, когда ход выполнения меняется командами переходов (jmp, ja,jae,jb,jbe,jc,je,jz,jnz,jg и т.д.) или командами call и ret. Поэтому начинаем просматривать программу «вверх».
00000AFF: 5E pop esi
00000B00: C3 ret
00000B01: 6A30 push 00000030
00000B03: 6880D10110 push 1001D180
00000B08: 6868D10110 push 1001D168
00000B0D: 8BCE mov ecx,esi
00000B0F: E8D41C0100 (1) call 000127E8
По адресу 00000B00 находится команда ret. Этой командой обычно заканчиваются функции – и ее назначение вернуть управление в место, откуда эта функция была вызвана. Это означает, что сама команда, и все что лежит выше – относится к другой подпрограмме, либо это второй «хвост». Следовательно, что наша функция начинается по адресу 00000B01.
Теперь остается найти код, который ее вызвал. Если код вызывается при помощи функции call, то нам придется преобразовывать физический адрес в виртуальный… Если же на данный участок кода происходит «прыжок» через команду семейства jump, то этого делать нет смысла, потому что при близких переходах jmp XX переходит на XX байт вперед относительно себя. То есть, какую бы адресацию мы не задали, количество байт между адресами в одном сегменте всегда будет одинаковым. Так что можно пробовать искать адрес «B01» напрямую.
В режиме «ASM VIEW», (см. рис. 4) нажмем F6 и введем «@B01» (символ «@» означает, что это подстрока).
Давайте проанализируем увиденное:
Рис. 4. Режим ASM VIEW
00000AEA: 51 push ecx // передать параметры
00000AEB: 52 push edx // передать параметры
00000AEC: E8AF000000 (1) call 00000BA0 // что-то вызвать
00000AF1: 83C40C add esp,0000000C //баланс стека
00000AF4: 84C0 test al,al // проверить al
00000AF6: 7409 (2) jz 00000B01 // если al=0, то jmp
00000AF8: 8BCE mov ecx,esi
00000AFA: E827C80000 (3) call 0000D326
00000AFF: 5E pop esi
00000B00: C3 ret
00000B01: 6A30 push 00000030
00000B03: 6880D10110 push 1001D180
00000B08: 6868D10110 push 1001D168 // “Wrong reg”
00000B0D: 8BCE mov ecx,esi
00000B0F: E8D41C0100 (4) call 000127E8 //Сообщить «BAD»
Возможно, мы находимся в том самом месте, где нужно изменить «равно» на «не равно». Тогда проведем эксперимент – изменим jz на jnz. Для этого нужно включить режим редактирования, нажав ALT+F3 (переключиться на столбик команд можно клавишей <Tab>).
Взлом-то, конечно, осуществлен, но при каждом запуске нажимать Enter – непорядок. Нужно бы изменить программу так, чтобы она всегда считала себя зарегистрированной. Как?
Ну к примеру, взять и удалить весть процесс регистрации. Мы знаем, что весь код регистрации находится в DLL, то есть программе в любом случае необходимо ее загрузить. Давайте попытаемся найти в программе ссылку на DLL_REG.DLL[5].
Для этого (см. рис. 5) загрузим в Qview файл Denoiser.exe и в 32-битном режиме «ASM VIEW» в «ассемблерном поиске» (по F6), введем «@DLL_REG».
Рис. 5.Загрузка в Qview файл Denoiser.exe и в 32-битном режиме «ASM VIEW» в «ассемблерном поиске»
Ловко и быстро мы находим следующий код:
00004CA7: E8F6B00200 call 0002FDA2
00004CAC: 8B4008 mov eax,dword ptr [eax+08]
00004CAF: 6818D44300 push 0043D418
00004CB4: 6AFF push FFFFFFFF
00004CB6: 50 push eax
00004CB7: FF154C664400 call DLL_reg.dll,?Registration…
00004CBD: 85C0 test eax,eax
00004CBF: 7409 jz 00004CCA
00004CC1: 66C705B81E44000100 mov word ptr [00441EB8],0001
00004CCA: 6A00 push 00000000
00004CCC: 8D4C2408 lea ecx,dword ptr [esp+08]
00004CD0: E800000000 call 00004CD5