Оригинальный DVD-ROM: eXeL@B DVD !
eXeL@B ВИДЕОКУРС !

ВИДЕОКУРС ВЗЛОМ
выпущен 2 июля!


УЗНАТЬ БОЛЬШЕ >>
Домой | Статьи | RAR-cтатьи | FAQ | Форум | Скачать | Видеокурс
Новичку | Ссылки | Программирование | Интервью | Архив | Связь

ПРОГРАММИРОВАНИЕ НА C и С++



Программисты долго мучаются с кодом прогаммы, изучают С++, WinAPI функции, MSDN. Потом пишут банальную систему защиты или навешивают банальный протектор, а крэкеры и реверсеры справляются с такой защитой за 5 минут. В итоге, продажи программы почти нулевые. Чтобы такого не допустить, тут самому надо немного поднабрать опыта отладки, реверсинга, тот же отладчик Ollydbg изучить или дизассемблер IDA Pro. Но где искать по крохам эти знания? Нет, конечно можно годами "методом тыка" разбираться, но куда быстрее видеокурс специальный посмотреть. Вот тут он есть: ссылка. Автор курса с большим опытом и объясняет понятно, я из этого курса много узнал про то как работает компьютер, процессор, про инструменты специальные и как с ними работать. Мои коллеги программисты на работе ничего такого и не знают, теперь я им нос утру.

Создание VxD на Visual C++ без ассемблерных модулей #2

Общая схема драйвера VxDМинимальный виртуальный драйвер должен содержать секцию резидентного кода, в которой расположены блок описателя устройства, диспетчер системных сообщений и обработчики сервисных функций.Обработчик системных сообщений анализирует код сообщения, переданный в EAX, выделяет интересующие его сообщения, обрабатывает их и возвращает сброшенный флаг CF в случае успеха, и установленный — в случае неудачи. Для всех необрабатываемых сообщений должен возвращаться сброшенный флаг CF.Обработчики сервисных функций вызываются по таблице, так что каждой функции соответствует собственный обработчик. Способ передачи параметров и возврата результатов определяется разработчиком.При необходимости драйвер может содержать обработчики запросов V86 и PM API. Для доступа к данным виртуальных машин DOS, указатели на которые могут передаваться в регистрах при запросе, достаточно преобразовать их в линейные 32-разрядные адреса, ибо первый мегабайт адресного пространства текущей виртуальной машины непосредственно «виден» из VxD. Для доступа к данным приложений Win16 потребуется выполнить отображение адресов посредством функции VMM _SelectorMapFlat.Программирование VxDСредства разработки, включаемые файлы и библиотекиМинимально необходимый набор включаемых файлов и библиотек содержится в Windows 95 DDK (подкаталоги Inc32 и Lib). Обычно требуется включение хотя бы файлов BASEDEF.H и VMM.H.Файлы VXDWRAPS.H, CONFIGMG.H и некоторые другие оформлены в стиле обычного языка C, поэтому при включении их в файлы типа CPP директивы #include необходимо помещать внутрь квалификатора extern "C":extern "C" {
#include <vxdwraps.h>
} Файлы из DDK можно включать и в тексты модулей обычных приложений, определив перед этим символическое имя Not_VxD. При этом определяются только полезные константы и типы, а определение специфических для VxD конструкций отключается.Структуры, обычно используемые в VxDVxD_Desc_Block - блок описателя устройстваОписывает структуру DDB. Заполняется статически, чтобы к моменту загрузки драйвера все поля имели нужные значения.ULONG DDB_Next;
USHORT DDB_SDK_Version;
USHORT DDB_Req_Device_Number;
UCHAR DDB_Dev_Major_Version;
UCHAR DDB_Dev_Minor_Version;
USHORT DDB_Flags;
UCHAR DDB_Name [8];
ULONG DDB_Init_Order;
ULONG DDB_Control_Proc;
ULONG DDB_V86_API_Proc;
ULONG DDB_PM_API_Proc;
ULONG DDB_V86_API_CSIP;
ULONG DDB_PM_API_CSIP;
ULONG DDB_Reference_Data;
ULONG DDB_Service_Table_Ptr;
ULONG DDB_Service_Table_Size;
ULONG DDB_Win32_Service_Table;
ULONG DDB_Prev;
ULONG DDB_Size;
ULONG DDB_Reserved1;
ULONG DDB_Reserved2;
ULONG DDB_Reserved3;

  • DDB_Next — поле для адреса следующего DDB в списке VMM. Инициализируется нулем.
  • DDB_SDK_Version — версия DDK, с которой построен драйвер. Инициализируется константой DDK_VERSION.
  • DDB_Req_Device_Number — идентификатор устройства. При отсутствии назначенного идентификатора задается нулевое значение.
  • DDB_Dev_Major_Version — старшая часть номера версии драйвера.
  • DDB_Dev_Minor_Version — младшая часть номера версии драйвера.
  • DDB_Flags — для служебных флагов VMM. Инициализируется нулем.
  • DDB_Name — имя устройства, дополненное пробелами до восьми символов.
  • DDB_Init_Order — позиция драйвера в списке загрузки. Если порядок загрузки не важен, используется константа UNDEFINED_INIT_ORDER (нуль).
  • DDB_Control_Proc — адрес функции диспетчера системных сообщений.
  • DDB_V86_API_Proc — адрес функции диспетчера V86 API.
  • DDB_PM_API_Proc — адрес функции диспетчера PM API.
  • DDB_V86_API_CSIP — служебное поле, инициализируется нулем.
  • DDB_PM_API_CSIP — служебное поле, инициализируется нулем.
  • DDB_Reference_Data — служебное поле, инициализируется нулем.
  • DDB_Service_Table_Ptr — указатель таблицы адресов процедур—обработчиков сервисных функций.
  • DDB_Service_Table_Size — количество сервисных функций, реализованных в драйвере.
  • DDB_Win32_Service_Table — служебный указатель таблицы функций Win32, инициализируется нулем.
  • DDB_Prev — поле для адреса предыдущего DDB в списке VMM, инициализируется константой 'Prev'.
  • DDB_Size — размер структуры описателя.
  • DDB_Reserved1 — служебное поле. Инициализируется константой 'Rsv1'.
  • DDB_Reserved2 — служебное поле. Инициализируется константой 'Rsv2'.
  • DDB_Reserved3 — служебное поле. Инициализируется константой 'Rsv3'.
Client_Reg_Struc - структура пакета регистров клиентаОписывает состояние регистров процессора в вызвавшей виртуальной машине/приложении (клиенте).ULONG Client_EDI;
ULONG Client_ESI;
ULONG Client_EBP;
ULONG Client_res0;
ULONG Client_EBX;
ULONG Client_EDX;
ULONG Client_ECX;
ULONG Client_EAX;
ULONG Client_Error;
ULONG Client_EIP;
USHORT Client_CS;
USHORT Client_res1;
ULONG Client_EFlags;
ULONG Client_ESP;
USHORT Client_SS;
USHORT Client_res2;
USHORT Client_ES;
USHORT Client_res3;
USHORT Client_DS;
USHORT Client_res4;
USHORT Client_FS;
USHORT Client_res5;
USHORT Client_GS;
USHORT Client_res6;
ULONG Client_Alt_EIP;
USHORT Client_Alt_CS;
USHORT Client_res7;
ULONG Client_Alt_EFlags;
ULONG Client_Alt_ESP;
USHORT Client_Alt_SS;
USHORT Client_res8;
USHORT Client_Alt_ES;
USHORT Client_res9;
USHORT Client_Alt_DS;
USHORT Client_res10;
USHORT Client_Alt_FS;
USHORT Client_res11;
USHORT Client_Alt_GS;
USHORT Client_res12;Поля с именами Client_xxx содержат значения соответствующих регистров на момент обращения виртуальной машины или приложения к системной функции. В поле Client_Error может быть занесен код ошибки.Для структуры введен синоним типа (typedef) с именем CRS. В файле VMM.H определены также вспомогательные структуры Client_Word_Reg_Struc и Client_Byte_Reg_Struc и объединение всех трех структур CLIENT_STRUCT.DIOCParams - параметры запроса DeviceIoControlDWORD Internal1;
DWORD VMHandle;
DWORD Internal2;
DWORD dwIoControlCode;
DWORD lpvInBuffer;
DWORD cbInBuffer;
DWORD lpvOutBuffer;
DWORD cbOutBuffer;
DWORD lpcbBytesReturned;
DWORD lpoOverlapped;
DWORD hDevice;
DWORD tagProcess;
  • VMHandle — идентификатор виртуальной машины, сделавшей запрос.
  • dwIoControlCode — код функции. Константы для определенных в системе кодов функций имеют префикс DIOC_, остальные функции определяются разработчиком.
GETVERSION (0) Открывание и опрос интерфейса. Если драйвер не поддерживает Win32 API, он должен вернуть в EAX ненулевое значение. В противном случае в EAX возвращается нуль, а если задан буфер результата, то в него заносится номер версии драйвера.
CLOSEHANDLE (-1) Закрывание интерфейса. Драйвер должен прервать обработку всех асинхронных запросов по этому устройству и освободить относящиеся к нему ресурсы.
  • lpvInBuffer — указатель исходного буфера.
  • cbInBuffer — размер исходного буфера в байтах.
  • lpvOutBuffer — указатель буфера результата.
  • cbOutBuffer — размер буфера результата в байтах.
  • lpcbBytesReturned — поле для объема в байтах данных, занесенных драйвером в буфер результата.
  • lpoOverlapped — указатель структуры типа OVERLAPPED (описатель адреса внутри файла и/или данных для асинхронной операции).
  • hDevice — идентификатор устройства.
  • tagProcess — идентификатор запроса. Вместе с полем hDevice образует уникальный внутри системы идентификатор запроса, по которому запрос может быть найден и аварийно прерван при получении запроса CLOSEHANDLE.
Функции VxD, вызываемые из системыДиспетчер системных сообщенийДиспетчер системных сообщений драйвера представляет собой функцию, получающую параметры в регистрах и возвращающую результат во флаге процессора CF (carry flag).Код сообщения передается в регистре EAX. При возврате флаг CF должен быть сброшен, если сообщение обработано успешно, и установлен, если произошли ошибка или отказ в обслуживании. Для всех сообщений, которые не обрабатываются данным VxD, должен возвращаться сброшенный флаг CF.Все регистры, не участвующие в возврате результата, должны быть сохранены. Рекомендуется оформлять диспетчер в виде naked–функции, чтобы гарантировать сохранение состояния флага CF после возврата, либо следить за кодом, который порождается компилятором.Обработчики сервисных функций Обработчики сервисных функций обычно тоже получают параметры в регистрах и возвращают результаты в регистрах и флагах процессора, однако они могут быть оформлены и в соответствии с соглашениями языков C.Обязательной является только функция с нулевым номером, через которую выполняется запрос версии драйвера; она не получает параметров и возвращает версию в регистре EAX.Все регистры, не участвующие в возврате результата, должны быть сохранены.Обработчики вызовов API Обработчики вызовов API получают в регистре EBX идентификатор (handle) текущей виртуальной машины (VM) клиента, а в регистре EBP — адрес структуры регистров клиента.По стандартному соглашению, при общении к API драйвера в регистре AH передается номер функции, а в AL — номер подфункции. Остальные регистры могут передавать другие параметры запроса.При необходимости возвратить информацию клиенту VxD модифицирует поля соответствующих регистров клиентской структуры; в момент возврата управления клиенту значения регистров восстанавливаются из нее.Обработчик API может использовать все регистры, кроме EBP и сегментных.Системные средства поддержки VxDНекоторые системные сообщенияDEVICE_INIT - инициализация статического драйвера
  • EBX — идентификатор системной виртуальной машины.
  • ESI — адрес командной строки VMM в его PSP. Первый байт строки определяет ее длину.
Сообщение посылается после загрузки статического драйвера для его инициализации.SYS_DYNAMIC_DEVICE_INIT - инициализация динамического драйвераСообщение посылается после загрузки динамического драйвера для его инициализации.SYS_DYNAMIC_DEVICE_EXIT - завершение динамического драйвераСообщение посылается перед выгрузкой динамического драйвера для завершения его работы.CREATE_VM - создание новой виртуальной машины
  • EBX — идентификатор создаваемой виртуальной машины.
Посылается в процессе создания новой виртуальной машины (VM), но до ее фактического запуска. На этом этапе VxD может определить, сможет ли он поддерживать создаваемую виртуальную машину, и запросить необходимые для поддержки ресурсы. Возврат установленного флага CF предотвращает создание машины.VM_INIT - инициализация новой виртуальной машины
  • EBX — идентификатор виртуальной машины.
Посылается в начале работы новой виртуальной машины, при ее инициализации, в контексте этой виртуальной машины. На этом этапе VxD может инициализировать ресурсы, выделенные для поддержки новой виртуальной машины.Флаг CF всегда должен возвращаться сброшенным.VM_TERMINATE - завершение виртуальной машины
  • EBX — идентификатор завершаемой машины.
Посылается в начале процесса завершения виртуальной машины.Флаг CF всегда должен возвращаться сброшенным.DESTROY_VM - уничтожение виртуальной машины
  • EBX — идентификатор уничтожаемой машины.
Посылается в конце процесса завершения машины, перед непосредственным удалением ее из системы.Флаг CF всегда должен возвращаться сброшенным.CREATE_THREAD - создание новой задачи
  • EDI — идентификатор создаваемой задачи.
Посылается при создании в системе новой задачи. Создаваемая задача в этот момент еще не является текущей.Возврат установленного флага CF предотвращает создание задачи.THREAD_INIT - инициализация новой задачи EDI — идентификатор задачи.Посылается при инициализации задачи, в начале ее работы, в контексте задачи (новая задача является текущей).Флаг CF всегда должен возвращаться сброшенным.TERMINATE_THREAD - завершение задачи
  • EDI — идентификатор завершаемой задачи.
Посылается в начале процесса завершения задачи. Завершаемая задача еще какое-то время может оставаться в системе, пока не будут завершены все ждущие операции ввода/вывода.Флаг CF всегда должен возвращаться сброшенным.DESTROY_THREAD - уничтожение задачи
  • EDI — идентификатор уничтожаемой задачи.
Посылается в конце процесса завершения задачи, перед непосредственным удалением задачи из системы.Флаг CF всегда должен возвращаться сброшенным.SYSTEM_EXIT - завершение работы системы
  • EBX — идентификатор системной виртуальной машины.
Посылается в начале процесса завершения работы системы, при запросе закрытия системы (shutdown), перезагрузки (reboot) или при аварийном завершении.W32_DEVICEIOCONTROL - запрос от приложения Win32
  • EBX — идентификатор текущей виртуальной машины.
  • ESI — адрес блока параметров DIOCParams.
  • Сообщение всегда посылается в контексте вызвавшей задачи Win32, так что драйверу напрямую доступно адресное пространство приложения. Драйвер обрабатывает запрос, извлекая из блока параметров и исходного буфера данные запроса, и возвращает в EAX код завершения:
0 — обработка завершена успешно;-1 — начата асинхронная операция. Возвращается только в том случае, если параметру был задан ненулевой параметр lpoOverlapped.код ошибки — если операция завершена неудачно.Вместе с возвратом результата в EAX драйвер может заносить необходимую информацию в буфер результата, если он указан в блоке параметров.Некоторые сервисные функции VMMVMMCall, VMMJmp, VxDCall, VxDJmp - вызов сервисных функций VxD void xxxCall (DWORD Service);void xxxJmp (DWORD Service);Service — код сервисной функции. Старшие 16 разрядов представляют собой идентификатор VxD, младшие 15 разрядов — номер сервисной функции.Служит для обращения к сервисным функциям VMM и других VxD. Код функции одновременно определяет и VxD, к которому происходит обращение, и саму функцию этого VxD, так что конструкции VMMxxx и VxDxxx равнозначны. Константы для кодов функций определены во включаемых файлах соответствующих VxD; имена констант функций VxD, отличных от VMM, имеют уточняющие префиксы, например VPICD_Get_Version — запрос номера версии VPICD, драйвера виртуального контроллера прерываний.Сервисные функции доступны только в драйверах, имеющих идентификаторы. К драйверам без идентификаторов «честный» доступ возможен только со стороны приложений. Со стороны других VxD он возможен лишь путем непосредственного поиска данного VxD в системном списке с последующим прямым доступом к таблице его сервисных функций.Параметры для сервисной функции, как правило, передаются в регистрах; результаты возвращаются в регистрах и флагах процессора. Некоторые функции рассчитаны на вызов в стиле языков C, с помещением параметров в стек и возвратом результата в EAX. Имена функций, оформленных в стиле C, начинаются со знака подчеркивания (_).Оба вызова оформляются в виде команды прерывания int 0x20, следом за которой размещается код функции. При первой отработке вызова VMM заменяет эту конструкцию на команду far call/jmp в соответствующий шлюз, что дает экономию времени при последующих вызовах. По этой причине конструкцию Int 20, если она не опознается отладчиком как VMMxxx/VxDxxx, нельзя проходить командой типа Step Over, так как стоп-точка будет установлена отладчиком сразу за командой Int и при этом будет испорчен расположенный за нею код функции. Отладчик SoftICE корректно опознает эти конструкции.Различие вызовов Call и Jmp состоит в том, что вызов Call запоминает адрес возврата в стеке, а Jmp — нет. Методом Jmp вызываются «фатальные» функции, не требующие возврата, а также функции, после которых нужен возврат сразу к вызвавшей функции, без восстановления регистров и других завершающих действий. Без хорошего понимания механизма работы вызова Jmp лучше ограничиться использованием вызова Call._SelectorMapFlat - отображение сегментного адреса в линейный_SelectorMapFlat (
DWORD VMHandle,
DWORD Sel,
DWORD Reserved
);
  • VMHandle — идентификатор виртуальной машины, которой принадлежит селектор. Если селектор относится к GDT, идентификатор игнорируется.
  • Sel — селектор для отображения.
  • Flags — резервный параметр, должен быть нулевым.
Функция получает параметры в стеке, в стиле языков C, и возвращает в EAX линейный адрес, соответствующий началу сегмента, селектор которого задан параметром Sel, либо — 1 в случае ошибки. При помощи этой функции возможен доступ из VxD к данным приложений Win16.Полученный адрес действителен до момента возврата в VMM, после чего отображение может быть аннулировано. Чтобы сохранять отображение длительное время, необходимо использовать специальные средства работы со страницами — резервирование страниц, копирование элементов таблицы страниц и т.п.Некоторые функции-обертки, определенные в VXDWRAPSOut_Debug_String - вывод отладочного сообщения void Out_Debug_String (char *String);
  • String — указатель строки, выводимой в отладочный поток. Для перехода на новую строку используется символ '\n".
Системный отладочный поток можно просматривать отладчиками WDEB386, SoftICE, а также любым отладочным монитором._Sprintf - форматирование строки ULONG _Sprintf (char *Buffer, char *Format, ...);Функция аналогична стандартной функции sprintf языка C.К сожалению, VMM не предоставляет функции, аналогичной vsprintf, поэтому для реализации функций целевого назначения, в основе которых лежит спецификация формата и список аргументов переменной длины (например, функций отладочного вывода или формирования строк специального вида), приходится использовать _Sprintf, копируя переменную часть списка аргументов (например, 10-20 двойных слов) из стекового кадра целевой функции.Пример построения функции-оберткиПоскольку сервисная функция VMM _SelectorMapFlat не имеет стандартной обертки, возможная функция-обертка для нее могла бы выглядеть следующим образом:#pragma warning (disable: 4035) // Блокировка предупреждения о невозврате

_declspec (naked)
void *SelectorMapFlat (DWORD VM, DWORD Sel, DWORD Rsv = 0) {

VMMJmp (_SelectorMapFlat) // Передача управления VMM

(void)(VM, Sel, Rsv); // Имитация использования параметров

}

#pragma warning (default: 4035) // Восстановление предупреждений о невозврате
Квалификатор _declspec (naked) подавляет генерацию пролога/эпилога, так что от функции остается лишь конструкция VMMJmp. При вызове этой функции-обертки параметры VM, Sel и Rsv помещаются в стек, затем туда же помещается адрес возврата, управление передается в функцию-обертку, при этом VMMJmp передает управление сервисной функции VMM _SelectorMapFlat, не запоминая нового адреса возврата в стеке. VMM использует значения параметров из стека, затем выполняет возврат по адресу, находящемуся на верхушке стека, при этом управление сразу возвращается в точку за вызовом функции-обертки, где находится код, удаляющий из стека параметры и использующий значение, возвращенное VMM в EAX.Такая схема типична для построения функций-оберток, так как в полной мере использует особенности создания стекового кадра в языках C, а также возможности компилятора Visual C++ по оформлению функций. Без использования VMMJmp пришлось бы делать возврат дважды, а без использования квалификатора naked — дважды помещать в стек список параметров.Пример простого VxDВ качестве примера приводится простейший VxD, отслеживающий события создания и уничтожения задач (threads). Единственная цель проекта — иллюстрация построения VxD целиком на C++. Драйвер намеренно сделан максимально простым, чтобы продемонстрировать прозрачность и относительную несложность базового VxD.Для полного понимания всех рассмотренных вопросов, а также для разработки собственных VxD вам понадобится Windows 9x DDK — набор включаемых файлов и библиотек Microsoft. Примерно до весны 1999 года, когда появился DDK для Windows 98, DDK для Windows 95 распространялся Microsoft свободно и бесплатно; сейчас свободно можно получить только DDK для Windows 98, который гораздо менее удобен для небольших проектов. Однако DDK для Windows 95 до сих пор можно найти в Интернете при помощи поисковых систем — например, http://www.filesearch.ru/ — по ключевым словам Windows, 95, DDK. Объем архива — около 17 Мбайт (полного комплекта DDK для Windows 98 — в несколько раз больше).При желании можно обойтись без «официальной», полной установки DDK, которая создает среду для разработки, принятую в Microsoft. Достаточно лишь распаковать подкаталоги INC32 и LIB и внести пути к ним в список путей поиска включаемых и библиотечных файлов компилятора (Tools -> Options -> Directories). После этого можно строить практически любые VxD (для некоторых — например, мультимедийных — может понадобиться добавление каталогов INC16, MMEDIA\INC и других специализированных).В комплект файлов примера включены необходимые для построения файлы из DDK для Windows 95 (basedef.h, vmm.h, vxdwraps.h, vxdwraps.clb). Созданный VxD будет работоспособен под Windows 95, 98 и Me.Для загрузки и тестирования драйвера можно воспользоваться утилитой Monitor, включенной в комплект примера. Для запуска утилиты достаточно распаковать архив и запустить файл Monitor.exe; в случае возникновения проблем нужно сделать изменения в реестре, запустив файл dbgmsg.reg.



<< ВЕРНУТЬСЯ В ПОДРАЗДЕЛ

<< ВЕРНУТЬСЯ В ОГЛАВЛЕНИЕ




Материалы находятся на сайте https://exelab.ru/pro/



Оригинальный DVD-ROM: eXeL@B DVD !


Вы находитесь на EXELAB.rU
Проект ReactOS