Откуда приложение извлекает очередное сообщение

Обновлено: 08.07.2024

В отличие от приложений для MS-DOS, приложения для Windows управляются событиями. В таких приложениях нет возможности вызывать функцию для получения ввода. Вместо этого эти приложения дожидаются, чтобы система самостоятельно передавала им входящую информацию.

Вводимые данные направляются системой для каждого окна отдельно. В этих целях каждое окно связано с функцией называемой ОКОННОЙ ПРОЦЕДУРОЙ. Если для какого-либо из окон есть какая-то входящая информация, то система запускает (вызывает) соответствующую оконную процедуру, передавая ей введенную информацию. Оконная процедура должна обработать полученную информацию и вернуть управление обратно системе.

MSG msg;
BOOL bRet;

Оконная процедура

Тупиковые ситуации

Перечень функций, которые могут не вернуть управление потоку:
DialogBox
DialogBoxIndirect
DialogBoxIndirectParam
DialogBoxParam
GetMessage
MessageBox
PeekMessage
SendMessage

PostQuitMessage - показывает системе, что поток сделал запрос на свое завершение.

SendAsyncProc - функция используемая совместно с функцией SendMessageCallback

оглавление

Создание Windows Forms делится на три этапа: объявление экземпляра WNDCLASS, регистрация формы и создание формы.


Функция регистрации формы - это RegisterClass или RegisterClassEx, который является классом окна, используемым при вызове функции CreateWindow () или CreatewindowEx после регистрации. Прототип выглядит следующим образом:


Для создания окна используется функция CreateWindow () или CreatewindowEx. Эта функция основана на классе окна, поэтому вам нужно указать несколько параметров, чтобы указать конкретное окно. И как создать несколько окон без рамок, тоже довольно умело, то есть создавать окна без заголовков и рамок, а затем самостоятельно рисовать содержимое программы в клиентской области, чтобы создавать персонализированные приложения. Прототип функции выглядит следующим образом: обратите внимание, что возвращаемое значение функции - дескриптор для создания формы, который требует особого внимания.




Этот код реализует простейшую форму. Эффект такой:



Выбранное окно данных является структурой WNDCLASS. Последние четыре байта - это адрес имени класса окна, адрес 0xF3A000, и окно данных следует для проверки, результат согласован, результат будет следующим:


Адрес функции оконной обработки - вторые четыре байта структуры WNDCLASS, то есть 0XF31352. Установите точку останова на этой функции. Продолжайте отладку.


Соответствующие параметры можно увидеть в разделе стека, где класс формы называется Register. Отладка еще на один шаг:


Возвращаемое значение регистра EAX - это дескриптор 0XB1346. Форма просмотра:


Вы можете видеть, что дескриптор и имя класса в первой строке согласованы. Продолжайте нажимать F9 для отладки.


Можно обнаружить, что программа останавливается на 0XF31352, что означает, что это вход оконной функции.


Только что представленный небольшой пример представляет собой простой анализ без углубленного анализа, особенно позиционирования функций обработки окна. Позвольте мне взять CrackMe в качестве примера для анализа. На форуме Wuai я нашел для анализа очень простой CM (без сложного алгоритма, без оболочки). Вам необходимо ввести правильный регистрационный код и нажать кнопку для взлома. Эффект такой:



В соответствии с обычной процедурой вызовите точку останова между двумя модулями RegisterClass и CreateWindow:









Наблюдая за структурой WNDCLASS в двух функциях RegisterClass, было обнаружено, что адрес функции процедуры формы трех форм - 0X77782280, а код расположен в сегменте системного кода (ntdll.dll), что не соответствует интуитивному пониманию. . Почему это?? Во-первых, решите первый вопрос, а именно, почему функции процедуры формы для двух функций регистрации формы одинаковы. Это связано с тем, что класс окна имеет только одну функцию окна, и все окна, созданные с помощью этого класса окна, используют одну и ту же функцию окна , если позже функция окна не была изменена с помощью SetWindowLong. Окно просмотра выглядит следующим образом, вы можете видеть, что все окна созданы с помощью WTWindow.



С помощью IDA может быть более интуитивно понятно:


Возвращаясь к функции DispatchMessage, прототип функции выглядит следующим образом:


Вышеупомянутый обычный анализ, теперь основное внимание уделяется тому, как найти настоящую функцию оконной обработки для взлома CM?


Все приведенные выше коды в 0X45AB89 являются сегментами системного кода, так что не беспокойтесь. Используйте IDA для отслеживания 0X45AB89 во фрагменте кода:



Далее продолжаем анализ функции sub_45AB89. Функция sub_45AB04 выглядит следующим образом:


Мы используем OD, чтобы установить точку останова на 0X45A912 для просмотра значений параметров.


Вы можете видеть, что v5 [7] = 0X321336, что соответствует ожиданиям. Давайте воспользуемся IDA для анализа функции sub_45A912:


Красные кружки - это ключевые функции, на которых нужно сосредоточиться. Используйте OD, чтобы установить там точку останова и наблюдать за функцией и параметрами. Можно догадаться, что Cwnd - это значение адреса, а адрес функции находится путем добавления смещения к адресу.



Пока основные функции обработки в основном определены, и затем пошаговый анализ может точно определить местонахождение приговора.

LONG DispatchMessage(const MSG FAR* lpmsg);

BOOL TranslateMessage(const MSG FAR* lpmsg);

Завершение работы приложения

Фрагмент кода функции WinMain, в котором осуществляется завершение работы приложения:

while( GetMessage(&msg, NULL, 0, 0))

// завершается после получения WM_QUIT

return TRUE; // завершение работы приложения

Оконная процедура

Реальная работа приложения происходит в оконных функциях. Именно оконная процедура определяет то, что выводится в рабочую область окна, и то, как окно реагирует на пользовательский ввод. Оконной процедуре можно назначать любое имя, в программе Windows может содержаться более одной оконной процедуры.

Оконная процедура всегда связана с определенным классом окна, который регистрируется при помощи функции RegisterClass. Функция CreateWindow создает окно на основе определенного класса окна. На основе одного и того же класса можно создать несколько окон.

Оконная процедура всегда определяется следующим образом:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);




Функция окна имеет одно очень важное свойство: она вызывается непосредственно Windows и не может вызываться приложением напрямую. Как и большинство функций Windows, в функции окна используется соглашение о связях языка Паскаль, поэтому объявление функции CALLBACK обязательно.

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

return( DefWindowProc(hWnd, message, wParam, lParam));

BOOL GetMessage(MSG FAR* lpmsg,HWND hwnd, UINT uMsgFilterMin,UINT uMsgFilterMax);

LONG DispatchMessage(const MSG FAR* lpmsg);

BOOL TranslateMessage(const MSG FAR* lpmsg);

Завершение работы приложения

Фрагмент кода функции WinMain, в котором осуществляется завершение работы приложения:

while( GetMessage(&msg, NULL, 0, 0))

// завершается после получения WM_QUIT

return TRUE; // завершение работы приложения

Оконная процедура

Реальная работа приложения происходит в оконных функциях. Именно оконная процедура определяет то, что выводится в рабочую область окна, и то, как окно реагирует на пользовательский ввод. Оконной процедуре можно назначать любое имя, в программе Windows может содержаться более одной оконной процедуры.

Оконная процедура всегда связана с определенным классом окна, который регистрируется при помощи функции RegisterClass. Функция CreateWindow создает окно на основе определенного класса окна. На основе одного и того же класса можно создать несколько окон.

Оконная процедура всегда определяется следующим образом:

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);

Функция окна имеет одно очень важное свойство: она вызывается непосредственно Windows и не может вызываться приложением напрямую. Как и большинство функций Windows, в функции окна используется соглашение о связях языка Паскаль, поэтому объявление функции CALLBACK обязательно.

LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)

return( DefWindowProc(hWnd, message, wParam, lParam));

При проектировании микросервисов часто возникает вопрос: какой способ связи между ними выбрать.

Многие отдают предпочтение RESTful API. Однако этот подход не всегда эффективен, так как в отдельных случаях чреват долгим ожиданием на клиентской стороне и потерей информации в случае сбоев.

Sync vs Async: синхронное и асинхронное взаимодействие




Однако сами очереди также необходимо масштабировать, и это может создать дополнительные сложности.

Правда, при этом очередь сама приобретает статус SPoF (Single Point Of Failure), поэтому необходимо заранее предусмотреть действия на случай ее аварийного отключения.

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

Очереди можно использовать в качестве буфера для некоторой массовой обработки, например пакетной вставки данных в БД или HDFS. Очевидно, что гораздо эффективнее добавлять сто записей за раз, чем по одной сто раз, так как сокращаются накладные расходы на инициализацию и завершение каждой операции. Но для стандартной архитектуры может стать проблемой генерация данных клиентской службой быстрее, чем их может обработать получатель. Очередь же предоставляет временное хранилище для пакетов с данными, где они будут храниться до завершения обработки принимающей стороной.

Помещая данные в очередь, вы можете быть уверены, что данные будут сохранены и в конечном итоге обработаны, даже если это займет немного больше времени, чем обычно, из-за большого скачка трафика. Увеличить скорость обработки в таких случаях также возможно — за счет масштабирования нужных обработчиков.

Многие брокеры поддерживают очереди FIFO, полезные в системах, где важно сохранить порядок транзакций. Если 1000 человек размещают заказ на вашем веб-сайте одновременно, это может создать некоторые проблемы с параллелизмом и не будет гарантировать, что первый заказ будет выполнен первым. С помощью очереди можно определить порядок их обработки.

Это обработка финансовых транзакций, бронирование авиабилетов, обновление записей о пациентах в сфере здравоохранения и так далее.

В каких случаях очереди неэффективны

Конечно, очереди не являются универсальным средством для любых приложений. Рассмотрим варианты, когда очереди не будут самым эффективным решением:

Если вы заинтересованы в использовании очередей, но опасаетесь, что команда не справится с их конфигурированием и последующей поддержкой самостоятельно, всегда можно воспользоваться одним из Managed-решений, представленных на рынке.

Читайте также: