Программирование на C++ глазами хакера

Динамическая библиотека для расшифровки паролей


Для этого примера я написал DLL-файл, процесс создания которого будет сейчас расписан на ваших глазах. Создайте новый проект Win32 Project в Visual C++ и назовите его OpenPassDLL. В Мастере настроек приложения (Application Settings) выберите тип приложения — DLL ( 3.12).

3.12. Окно Мастера настроек нового приложения DLL

В новом проекте у вас будет только один файл OpenPassDLL.cpp (не считая стандартного stdafx.cpp ), но заголовочного файла для него не будет. В заголовочных файлах принято писать все объявления, а нам они понадобятся, поэтому давайте создадим такой файл. Для этого щелкните правой кнопкой мыши в окне Solution Explorer по пункту Header Files и в появившемся меню выберите пункт Add/Add New Item. Перед вами должно открыться окно, как на рисунке 3.13. Выберите в правой части окна тип файла Header File (.h), а в поле Name укажите OpenPassDLL.h. Нажмите кнопку Open, чтобы добавить новый файл к проекту.

3.13. Окно создания заголовочного файла

Щелкните дважды по созданному файлу, чтобы открыть его в редакторе, и напишите в нем следующий код:

// Macro for DLL exports in Win32, replaces Win16 __export

// (Макрос для экспорта DLL в Win32 вместо 16-битной версии)

#define DllExport extern "С" __declspec(dllexport)

// Prototype

// (Прототип)

DllExport void RunStopHook(bool State, HINSTANCE hInstance);



Сначала описывается макрос DllExport, с помощью которого можно указывать, какие процедуры будут экспортироваться (можно вызывать из других приложений).

Во второй строке кода описывается сама экспортируемая процедура. Как видите, объявление похоже на реализацию, но отсутствует сам код процедуры, а есть только название и передаваемые значения. Сама процедура должна быть написана в файле OpenPassDLL.cpp.

Переходим к файлу OpenPassDLL.cpp. Его содержимое вы можете увидеть в листинге 3.6. Повторите этот код в своем файле и внимательно изучите.

Листинг 3.6. Код файла OpenPassDLL.cpp
// OpenPassDLL.cpp : Defines the entry point for the DLL application // OpenPassDLL.cpp : Определяет точку входа для DLL-приложение


#include windows.h #include "stdafx.h" #include "OpenPassDLL.h"

HHOOK SysHook; HWND Wnd; HINSTANCE hInst;

BOOL APIENTRY DllMain( HANDLE hModule, DWORD ul_reason_for_call, LPVOID lpReserved ) { hInst=(HINSTANCE)hModule; return TRUE; }

LRESULT CALLBACK SysMsgProc(

int code, // hook code (код ловушки) WPARAM wParam, // removal flag (флаг) LPARAM lParam // address of structure with message // (адрес структуры с сообщением) ) { //Передать сообщение другим ловушкам в системе CallNextHookEx(SysHook, code, wParam, lParam);

//Проверяю сообщение if (code == HC_ACTION) { //Получаю идентификатор окна сгенерировавшего сообщение Wnd=((tagMSG*)lParam)-hwnd;

//Проверяю тип сообщения. //Если была нажата левая кнопка мыши if (((tagMSG*)lParam)-message == WM_RBUTTONDOWN) { SendMessage(Wnd, EM_SETPASSWORDCHAR, 0, 0); InvalidateRect(Wnd, 0, true); } }

return 0; }

///////////////////////////////////////////////////////////////////

DllExport void RunStopHook(bool State, HINSTANCE hInstance) { if (true) SysHook = SetWindowsHookEx(WH_GETMESSAGE, SysMsgProc, hInst, 0); else UnhookWindowsHookEx(SysHook); }

Разберем подробно исходный код динамической библиотеки. В самом начале подключаются заголовочные файлы. OpenPassDLL.h — это созданный нами файл, в котором объявлены макрос и функция, которая будет экспортирована.

Далее идет определение глобальных переменных библиотеки. Их будет три:

SysHook — идентификатор ловушки системных сообщений;

Wnd — указатель на окно (со звездочками), в котором щелкнул пользователь. Эту переменную можно было сделать и локальной, но я решил ее вынести в глобальную область для последующего использования;

HInst — идентификатор экземпляра библиотеки.

Описания закончены. В области программы первой идет функция DllMain. Это стандартная функция, которая выполняется при загрузке библиотеки. В ней можно производить действия по начальной инициализации. В нашем случае ничего инициализировать не надо, но в качестве первого параметра этой функции мы получаем экземпляр библиотеки, который сохраняем в переменной hInst.



Теперь рассмотрим функцию RunStopHook. Она будет запускать и останавливать системную ловушку. В качестве параметров нужно передать два значения:

логический параметр — значение true, если надо запустить ловушку, иначе — остановить;

идентификатор экземпляра приложения, вызвавшего эту функцию, — пока не будем использовать этот параметр.

Если в качестве первого параметра передано значение true , то регистрируется ловушка, которая будет принимать все сообщения Windows на себя. Для этого используется функция SetWindowsHookEx. У этой функции должно быть четыре параметра:

тип ловушки — в данном случае WH_GETMESSAGE;

указатель на функцию, которой будут пересылаться сообщения Windows;

указатель на экземпляр приложения — переменная, в которой сохранен экземпляр библиотеки;

идентификатор потока — если указан ноль, то используются все существующие потоки.

В качестве второго параметра указано имя функции SysMsgProc. Она также описана в этой библиотеке. Но ее мы рассмотрим чуть позже.

Значение, которое возвращает функция SetWindowsHookEx, сохраняется в переменной SysHook. Оно понадобится при отключении ловушки.

Если процедура RunStopHook получила в качестве параметра значение false, то нужно отключить ловушку. Для этого вызывается процедура UnhookWindowsHookEx, которой передается значение переменной SysHook. Это то значение, которое было получено при создании ловушки.

Теперь давайте посмотрим на функцию SysMsgProc, которая будет вызываться при наступлении системных событий.

В первой строке пойманное сообщение передается остальным ловушкам, установленным в системе с помощью CallNextHookEx. Если этого не сделать, то другие обработчики не смогут узнать о наступившем событии, и система будет работать некорректно.

Далее проверяется тип полученного сообщения. Нам нужно обрабатывать событие нажатия кнопки мышки, значит, параметр code должен быть равен HC_ACTION; сообщения другого типа нам нет смысла обрабатывать.

После этого определяется окно, сгенерировавшее событие, и проверяется тип события. Указатель на окно можно получить так: ((tagMSG*)lParam)-hwnd. На первый взгляд запись абсолютно непонятная, но попробуем в ней разобраться. Основа этой записи — переменная lParam, которая получена в качестве последнего параметра нашей функции-ловушки SysMsgProc. Запись ((tagMSG*)lParam) обозначает, что структура типа tagMSG находится по адресу памяти, указатель на который передан через параметр lParam. У этой структуры есть параметр hwnd, в котором находится указатель на окно, сгенерировавшее сообщение.



Следующим этапом проверяется событие нажатия кнопки мыши: если была нажата правая кнопка мышки, то в этом окне нужно убрать звездочки. Для этого проверяется содержимое поля message все той же структуры ((tagMSG*)lParam).

Если это свойство равно WM_RBUTTONDOWN, т o нажата правая кнопка мыши, и надо убрать звездочки. Для этого окну посылается сообщение SendMessage со следующими параметрами:

Wnd — окно, которому предназначено сообщение;

EM_SETPASSWORDCHAR — тип сообщения. Этот тип говорит о том, что надо изменить символ, который будет использоваться для того, чтобы спрятать пароль;

0 — новый символ, при отправке которого текущий символ-маска просто исчезнет, и будет восстановлен реальный текст;

0 — зарезервировано.

Напоследок вызывается функция InvalidateRect, которая заново прорисует указанное в первом параметре окно. Это все то же окно, в котором произведен щелчок. Во втором параметре указывается область, которую надо прорисовать, значение 0 равносильно прорисовке всего окна. Если последний параметр равен true, то надо перерисовать и фон.

Примечание
Исходный код библиотеки вы можете найти на компакт - диске в каталоге \Demo\Chapter3\OpenPassDLL.

Содержание раздела