
Перехват буфера обмена на Ассемблере

Перехват буфера обмена на Ассемблере
Сегодня разберем интересную тему - перехват буфера обмена. Применений этому перехвату можно найти много: менеджеры буфера обмена, хранящие последние несколько скопированных текстов; программы, выполняющие заданные действия, если в буфере обмена появилось кодовое слово; кейлоггеры, перехватывающие пароли и тексты пользователя; одно время были популярны трояны, подменяющие в буфере обмена номера электронных кошельков на свои собственные. Область применения любой технологии, как обычно, ограничивается только вашей фантазией. Но это все лирика, пора переходить к программированию.
Для того, чтобы ваше приложение узнавало об изменении содержимого буфера обмена, оно должно встроиться в цепочку обработчиков буфера обмена ("наблюдателей"). Существует два основных способа это сделать. Первый способ поддерживается операционными системами от Windows 2000 и выше, он основан на использовании функции SetClipboardViewer.
Code (Assembler) : Убрать нумерацию
- wm_init:
- ; Добавить наше окно в список наблюдателей
- invoke SetClipboardViewer, [hwnddlg]
- mov [hNextW], eax
- ...
- wm_close:
- ; Убрать наше окно из списка наблюдателей
- invoke ChangeClipboardChain, [hwnddlg], [hNextW]
- ...
Code (Assembler) : Убрать нумерацию
- ; Отправить сообщение следующему окну
- invoke SendMessage, [hNextW], WM_DRAWCLIPBOARD, 0, 0
Code (Assembler) : Убрать нумерацию
- ; Удаляется известное нам окно?
- mov eax,[wparam]
- cmp eax,[hNextW]
- jne unknown_handle
- ; Запомнить новый хэндл следующего обработчика
- mov eax,[lparam]
- mov [hNextW],eax
Code (Assembler) : Убрать нумерацию
- unknown_handle:
- ; Передать сообщение следующему окну
- invoke SendMessage, [hNextW], WM_CHANGECBCHAIN, [wparam], [lparam]
Второй, более современный способ, доступен в операционных системах, начиная с Windows Vista. Здесь используется функция AddClipboardFormatListener.
Code (Assembler) : Убрать нумерацию
- wm_init:
- ; Добавить наше окно в список наблюдателей
- invoke AddClipboardFormatListener,[hwnddlg]
- ...
- wm_close:
- ; Убрать наше окно из списка наблюдателей
- invoke RemoveClipboardFormatListener,[hwnddlg]
- ...
При написании статьи я попробовал одновременно запустить два приложения, одно из которых использует первый (старый) способ перехвата, а другой второй способ (новый). Как ни странно, в этом случае победил первый способ перехвата. Второму приложению не доставалось ничего до того момента, как было закрыто первое. Дальше я запустил параллельно две копии первого перехватчика, они оба отрабатывали перехват без каких-либо проблем. А вот при запуске двух копии приложения с новым перехватом, данные доставались только тому, которое было запущено позднее. Такие дела.
Осталось выяснить еще один вопрос. Как узнать, что именно содержится в буфере обмена? Например, нас интересуют только текстовые строчки, а картинки и всякие эксельные таблицы должны пролетать мимо. Для этого есть функция IsClipboardFormatAvailable.
Code (Assembler) : Убрать нумерацию
- ; В буфере обмена находится текст?
- invoke IsClipboardFormatAvailable,CF_TEXT
- or eax,eax
- jz not_text
Просмотров: 6172 | Комментариев: 4

Внимание! Статья опубликована больше года назад, информация могла устареть!
Комментарии
Отзывы посетителей сайта о статье
Марат
(24.08.2013 в 12:52):
...Спасибо Вам...

brute
(23.08.2013 в 20:04):
да стебусь я по случаю пятницы) Давно хотел на любимом PB переводчик в стиле QDictionary запилить(самодельные словари есть), поэтому статья весьма полезна!

ManHunter
(23.08.2013 в 19:46):
А зачем копировать текст из окна самой программы? Можно добавить проверку владельца окна, но это уже выходит за рамки примера.

brute
(23.08.2013 в 19:01):
первый пример не работает, если копировать текст из самого окна примера. Если запустить две копии первой программы и копировать текст в одной из них, то корректно отображает его только одна.. жаль, что второй пример на XP не запускается..:)

Добавить комментарий
Заполните форму для добавления комментария
