- •Основы исследование безопасности программного обеспечения
- •Оглавление
- •Обращение к читателю
- •Введение
- •С чего начать
- •Инструменты исследователя
- •Установка исследуемой программы
- •Типовая защита «Запрос пароля» или «Запрос ввода регистрационного номера»
- •Исследование типовой защиты в отладчике OllyDbg
- •Исследование типовой защиты в дизассемблере ida Pro
- •Типовая защита «Запрос пароля» или «Запрос ввода регистрационного номера» с шифрованием сообщения
- •Технологии защиты программного кода от исследования и отладки
- •Как не надо проектировать защиту программ
- •Как обмануть отладчик и дизассемблер
- •Приложение 1. Ассемблер в Windows
- •О стеке
- •Команды передачи управления
- •Литература для дополнительного изучения
- •Приложение 2. Отладчик OllyDbg
- •Откуда скачать программу
- •Установка и настройка программы
- •Дизассемблированный код (листинг)
- •Регистры
- •Наиболее полезные клавиши в OllyDbg
- •Подключение плагинов в OllyDbg
- •Встроенный язык ida Pro
- •Плагины ida Pro
- •Литература для дополнительного изучения
- •Задание для самостоятельного выполнения
- •Список используемой литературы
О стеке
Стек – структура данных. Поддерживается на уровне процессора наличием двух регистров (ESP, EBP) и двух команд PUSH (положить в стек), POP (достать из стека). Стек используют команды CALL (вызов процедуры), RET (возвращение из процедуры), ENTER (организация стека при входе в процедуру), LEAVE (восстановление стека после команды ENTER), INT (вызов прерывания), IRET (возврат из прерывания).
За один раз с помощью команды PUSH в стек можно поместить четырехбайтовый операнд, при этом содержимое регистра ESP уменьшается на 4. ESP – указатель стека, он указывает на последний помещенный в стек элемент. Пример работы со стеком приведен в Листинге 4.
Листинг 4 «Работа со стеком»:
//работа со стеком
#include <Windows.h>
#include <stdio.h>
DWORD a,b,c,d,e;
WORD f;
void main()
{
__asm {
mov eax,10001h
mov a,esp
//поместить в стек четыре байта
push eax
mov b,esp
pop c
//поместить в стек два байта
push ax
mov d,esp
pop f
//доступ к стеку непосредственно через регистр ESP
push 200002h //поместить в стек константу
mov eax,[esp]
mov e,eax
pop eax
};
printf("%u %x %u %u %x\n", a-b,c,a-d,f,e);
}
Рис. Результат работы программы
Команды передачи управления
К командам передачи управления относятся команды условного и безусловного переходов, CALL, RET, INT, IRET.
Различают передачу управления в пределах существующего сегмента и межсегментную передачу управления. В первом случае происходит изменение регистра EIP (указателя команд). Межсегментный переход в реальном режиме предполагает изменение содержимого EIP вместе с содержимым сегментного регистра CS, где содержится адрес сегмента. Каждая задача в ОС Windows работает в своем виртуальном адресном пространстве, представляющем один большой сегмент, размер которого определяется 32-битным числом. Поэтому все переходы в программах для ОС Windows осуществляются в рамках этого сегмента и предполагают изменение содержимого регистра EIP (справедливо для CALL, RET).
Листинг 5 «Нахождение максимального из трех чисел»:
//условные и безусловные переходы
#include <Windows.h>
#include <stdio.h>
DWORD a,b,c,d;
void main()
{
a=400;
b=600;
c=700;
__asm {
mov eax,a
cmp eax,b
ja l1
mov eax,b
l1:
cmp eax,c
jna l2
jmp l3
l2:
mov eax,c
l3:
mov d,eax
}
printf("%d\n",d);
}
Рис. Результат выполнения программы
Рассмотрим Листинг 5. В командах условного и безусловного переходов присутствует операнд «адрес переход». В листинге используются метки, чтобы не зависеть от абсолютных адресов. Метка – символьное имя, за которым идет двоеточие. При трансляции метки заменяются конкретными числовыми адресами.
Команда JMP l1 осуществляет переход по адресу, который лежит в переменной l1.
В командах условного перехода переход осуществляется согласно условию, связанному непосредственно с состоянием шести арифметических флагов. По этой причине команды условного перехода стоят обычно после тех команд, которые изменяют эти флаги.
MASM
Пакет MASM32 (Macro Assembler) версии 10.0 можно скачать с сайта: http://movsd.com
Рассмотрим общую схему трансляции программы, написанной на языке ассемблера.
Двум стадиям трансляции с языка ассемблера соответствуют: ассемблер ML.EXE и редактор связей (компоновщик, линковщик) LINK.EXE. Эти программы предназначены для перевода модуля (модулей) на языке ассемблера в исполняемый модуль, состоящий из команд процессора (имеет расширение EXE в ОС Windows).
Для файла PROG.ASM на языке ассемблера стадии трансляции будут следующими:
c:\masm32\bin\ml /c /coff PROG.ASM
После работы данной команды появляется объектный модуль PROG.OBJ.
c:\masm32\bin\link /SUBSYSTEM:WINDOWS PROG.OBJ
В результате последней команды появляется исполняемый модуль PROG.EXE.
Листинг 6 «Каркас программы на языке ассемблера для ОС Windows».
.586P
;плоская модель памяти
.MODEL FLAT, STDCALL
;---------------------------------------
;сегмент данных
_DATA SEGMENT
;здесь будут располагаться переменные
L DD 0
_DATA ENDS
;сегмент кода
_TEXT SEGMENT
;здесь будет располагаться ассемблерный код программы
START:
MOV EAX,L
RET ;выход
_TEXT ENDS
END START
В программе всего одна инструкция процессора RET, остальное – директивы макроассемблера MASM.
.586P – инструкция указывает процессору множество допустимых команд.
Директива .MODEL FLAT говорит ассемблеру, что программа должна рассматриваться в контексте плоской модели памяти.
Директива STDCALL используется для задания соглашения о вызовах процедур.
С помощью директив _DATA SEGMENT / _DATA ENDS ограничена область, где будут храниться данные. В сегменте данных определена переменная L. Тип переменной DD (DWORD, т.е. двойное слово), аналог int в С.
Область программы, ограниченная директивами _TEXT SEGMENT / _TEXT ENDS, содержит исполняемый код. Данная область называется сегментом кода. Команда RET возвращает управление операционной системе.
Строка START – метка, с которой должно начаться выполнение программы.