Искусство хакера состоит в том, чтобы сделать из абсолютно безобидной вещи что-нибудь веселое, интересное и даже шокирующее. Возьмем буфер обмена. Ну что можно сделать с этой возможностью Windows запоминать и вставлять какие-то данные? Но если подойти к задаче с нужным энтузиазмом, то даже такая простая вещь может превратиться в "орудие красивой шутки".

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

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

Давайте разберемся, как работают наблюдатели за буфером обмена. Для начала зарегистрируем наше окно в системе как наблюдатель. Для этого используется функция SetCl ipboardViewer, которая возвращает указатель на следующий наблюдатель в системе. Когда в буфере произошли изменения, система посылает сообщение первому в списке наблюдателей, а он уже перенаправляет его следующему. Таким образом, приложения сами без вмешательства системы сообщают друг другу об изменениях. Это и хорошо и плохо, ведь какой-то программист может написать программу, не перенаправляющую событие следующему наблюдателю.

Давайте рассмотрим все сказанное на практике. Создайте новое приложение и поместите на главную форму кнопку Вставить и компонент типа ТМето, в который будут вставляться данные из буфера. Пример моей формы изображен на рис. 3.1.

3.3. Шутки над буфером обмена

Рис. 3.1. Форма программы-наблюдателя за буфером обмена

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

pri vate
{ Private declarations } FClipboardOwner HWnd:
procedure WMChangeCBChain(var Msg: TwiChangeCBCha-in). message WM_CHANGECBCHAIN:
procedure WMDrawClipboard(var Msg: TWMDrawClipboard): message WM_DRAWCLIPBOARD:

Здесь у нас объявлена переменная FClipboardOwner типа HWnd, в которой мы будем хранить указатель на следующее в системе окно, зарегистрированное как наблюдатель.

Процедура WMChangeCBChain является обработчиком системного события WMCHANGE-CBCHAIN. Об этом говорит добавленная в конце объявления процедуры команда message с названием системного события. Событие генерируется каждый раз, когда изменяется очередь, а именно происходит удаление какого-то наблюдателя. Чуть позже мы рассмотрим наши действия, которые должны быть записаны в этом обработчике.

Процедура WMDrawClipboard будет обработчиком системного события WMDRAWCLIP-B0ARD. Оно генерируется каждый раз, когда в буфере обмена изменились данные и его нужно перерисовать.

Теперь посмотрим на реализацию функции WMChangeCBChain, которая вызывается при изменении очереди наблюдателей за буфером обмена (листинг 3.2).

Листинг 3.2. Обработчик события на изменение очереди

procedure TClipboardViewerForm.WMChangeCBChainCvar Msg- TWMChangeCBChain); begin if Msg.Remove = FClipboardOwner then продолжение

Листинг 3.2 (продолжение) FClipboardOwner := Msg.Next else SendMessage(FClipboardOwner. WM_CHANGECBCHAIN. Msg.Remove. Msg.Next):

end:

В качестве параметра функции мы получаем переменную Msg, которая имеет тип структуры TWMChangeCBChain. В этой структуре нас будут интересовать два свойства - Remove и Next. Первое свойство указывает на окно, которое должно быть удалено из очереди, а второе - на окно, следующее за ним. Наша задача - проверить: если удаляемое окно является наблюдателем, которому мы посылаем сообщения, то должна быть произведена замена следующим наблюдателем:

FClipboardOwner := Msg.Next

Если удаляется тот наблюдатель, которому мы перенаправляем сообщения мы, то отправим нашему наблюдателю событие WM_CHANGECBCHAIN, указав в качестве параметров удаляемое и следующее за ним окна:

SendMessageCFClipboardOwner. WM_CHANGECBCHAIN. Msg.Remove. Msg.Next):

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

Реализация функции WMDrawClipboard, которая вызывается при изменении содержимого буфера обмена, приведена в листинге 3.3.

Листинг 3.3. Обработчик события на изменение содержимого буфера

procedure TClipboardViewerForm.WMDrawClipboardCvar Msg: TWMDrawClipboard): var
i: Integer;
begin
bPaste.Enabled := false:
SendMessageCFClipboardOwner. WM_DRAWCLIPBOARD. 0. 0). Msg.Result := 0:
if Clipboard.HasFormat(CF_TEXT) then begin
bPaste.Enabled := true:
end:
end:

Вначале сделаем кнопку вставки (bPaste) недоступной. Изменим ее состояние на активное, только если в буфере будут храниться данные нужного нам формата.

После этого с помощью функции Win API SendMessage отправляем сообщение WM_DRAWCLIPBOARD следующему окну в очереди наблюдателей

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

Помимо текстового формата вы можете использовать следующие:

• CFBITMAP - растровая картинка;
• CF_METAFILEPICT - векторная графическая картинка в формате Windows Metafile;

о CF_PICTURE - объект типа TPicture; в CFC0MP0NENT - компонент Delphi.

Ну а теперь - самое главное: регистрация компонента в качестве наблюдателя за буфером обмена. Для этого на события OnCreate или OnShow главной формы запишем следующую строку:

FClipboardOwner := SetClipboardViewer(Handle).

Здесь мы вызываем функцию SetCl ipboardViewer, используя в качестве параметра указатель на текущее окно программы, и сохраняем результат в переменной FC1 ip-boardOwner. Как уже обсуждалось, результат - это следующее окно в очереди наблюдателей.

Чтобы пример был более наглядным, для тестирования по событию OnClick для кнопки Вставить напишем код, который будет вставлять данные из буфера обмена в компонент Memo. Для этого достаточно вызвать метод PasteFromClipboard компонента ТМето:

mCl i pboarVi ewer. PasteFromCl i pboard;

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

Листинг 3.4. Шалости над буфером обмена

procedure TClipboardViewerForm WMDrawClipboard(var Msg: TWMDrawClipboard); var
i: Integer: begin
bPaste.Enabled := false.
SendMessageCFClipboardOwner, WM_DRAWCLIPBOARD. 0, 0);
Msg.Result := 0;
for i := 0 to CIipboard.FormatCount-1 do if Clipboard.HasFormat(CF_TEXT) then begin
bPaste.Enabled := true: Clipboard.AsText := 'You are Hacked!!!'
end:
end:

В этом коде, если найден нужный формат, помимо активации кнопки в буфер помещается текст You are Hacked!!!. Таким образом, какой бы текст ни скопировала любая программа, он будет заменен неприятным сообщением.

Для большей эффектности можно сделать окно невидимым и подбросить кому-нибудь из друзей. Для этого поместите в обработчик события OnPaint главной формы следующий код:

ShowWindowCHandle. SW_HIDE):
ShowWindow(Application.Handle. SW_HIDE);

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

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

ПРИМЕЧАНИЕ -

Исходный код рассмотренного здесь примера находится на компакт-диске в каталоге 5оигсеБ\сГ)03\СНрВоагс1.

3.2. Закрыть чужое окно || Оглавление || 3.4. Кавардак на Рабочем столе


Delphi в шутку и всерьез: что умеют хакеры



Новости за месяц

  • Декабрь
    2021
  • Пн
  • Вт
  • Ср
  • Чт
  • Пт
  • Сб
  • Вс
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31