Hook Keyboard

  • Автор темы niello
  • Дата начала
N

niello

Мне необходимо получить перехват на окно, и если окно нажато в 1окне() значит передаю нажатие клавиши другому окну, делаю длл вот так :
Код:
procedure SetDllWindow1(wnd:hwnd);
begin
DllWindow1:=wnd;
end;
procedure SetDllWindow2(wnd:hwnd);
begin
DllWindow2:=wnd;
end;


function KeyboardProc(code : integer; wParam : word;
lParam : longint) : longint; stdcall;
begin


//Проверяем сообщение
Result:=CallNextHookEx(SysHook, Code, wParam, lParam);// сообщение не обрабатывать
if (DllWindow1<>0)and(DllWindow2<>0)then
begin
//Получаем идентификатор окна, сгенерировавшего сообщение
DllPromo:=TMsg(Pointer(lParam)^).hwnd;
if DllPromo=DllWindow1 then
begin
PostMessage(DllWindow2,TMsg(Pointer(lParam)^).message,Code,0);
end;
if DllPromo=DllWindow2 then
begin
PostMessage(DllWindow1,TMsg(Pointer(lParam)^).message,Code,0);
end;
end;

end;

exports KeyboardProc;
exports SetDllWindow2,SetDllWindow1;
 
N

niello

То есть если было нажата клавиша при окне1, передадим окну2 это сообщение, и наоборот
 
Z

zubr

Хэндлы DllWindow1 и DllWindow2 передавай через файлмаппинг или через расшаренную память. А так как у тебя - работать не будет, вернее будет только в пределах твоего же процесса.
 
N

niello

Я подумал, все можно запихнуть в одну длл, я и попробовал, но почему то не пашет, я вот даже попробовал если выполняется хук, то окно просто закрыть - не закрывает(( где ошибка, подскажите.
Код:
var
wndPromo,Wnd1,Wnd2:Hwnd;
Hook:HHook;
function SysProc(code:integer;wParam:word;lParam:Longint):longint;stdcall;
begin

Result:=CallNextHookEx(Hook,Code,wParam,lParam);
// SendMessage(wnd2, WM_DESTROY, 0,0);
if code=HC_ACTION then begin
wndPromo:=TMsg(Pointer(lParam)^).hwnd;
if wndPromo=wnd1 then
begin
SendMessage(wnd2, WM_DESTROY, 0,0);
end;
if wndPromo=wnd2 then
begin
SendMessage(wnd1, WM_DESTROY, 0,0);
end;

end;
end;
procedure RunStopHook(bol : boolean);
begin
if bol then 
begin

Wnd1:=FindWindow(nil,WindowName);
SendMessage (Wnd1, WM_SETTEXT, 0,LParam(WinName1));
Wnd2:=FindWindow(nil,WindowName);
SendMessage (Wnd2, WM_SETTEXT, 0,LParam(WinName2));
Hook:=SetWindowsHookEx(WH_KEYBOARD,@SysProc,Hinstance,0);

end;

if not bol then
begin
UnhookWindowsHookEx(Hook);
Hook:=0;
end;


end;
А оно че то не пашет. Я хотел бы хотябы для начала, что если я нажимаю какую то клавишу на окне,то чтобы другому окну посылалось сообщение нажатия определенной клавиши(но пока просто закрытие окна).
Может подскажите где все таки я ошиппся?
 
Z

zubr

Я тебе собственно уже ответил в предыдущем посте. А ты наступаешь на те же грабли. Процедура RunStopHook у тебя вызывается только в экземпляре хукdll, загруженной в адрессное пространство твоего процесса, соответственно переменные Wnd1 и Wnd2 инициализируются только здесь. При возникновении хукового события в каком либо другом процессе, туда загружается твоя хуковая dll, но процедура RunStopHook здесь не вызывается. Советую почитать литературу по хукам, в интернете полно примеров хуков, по моему и здесь на форуме, даже недавно были вопросы по хукам, воспользуйся поиском.
 
N

niello

Второй код, который я писал, как раз и был длл, то есть:
Код:
library Project_X_dll;
uses
Windows,Messages;
const
WindowName = 'Безымянный - Блокнот';


WinName1 :Pchar='1';
WinName2 :Pchar='2';
var
DC1,DC2:HDC;
pic1,pic2:HBITMAP;

wndPromo,Wnd1,Wnd2:Hwnd;
Hook:HHook;/
function SysProc(code:integer;wParam:word;lParam:Longint):longint;stdcall;
begin


Result:=CallNextHookEx(Hook,Code,wParam,lParam);
SendMessage(wnd2, WM_DESTROY, 0,0);
if code=HC_ACTION then begin
wndPromo:=TMsg(Pointer(lParam)^).hwnd;
if wndPromo=wnd1 then
begin
SendMessage(wnd2, WM_DESTROY, 0,0);
//  Ellipse(DC1,30,70,80,80);
end;
if wndPromo=wnd2 then
begin
SendMessage(wnd1, WM_DESTROY, 0,0);
//  Ellipse(DC2,30,70,80,80);

end;

end;
end;
procedure RunStopHook(bol : boolean);
begin
if bol then 
begin

Wnd1:=FindWindow(nil,WindowName);
SendMessage (Wnd1, WM_SETTEXT, 0,LParam(LPCTSTR(WinName1)));
Wnd2:=FindWindow(nil,WindowName);
SendMessage (Wnd2, WM_SETTEXT, 0,LParam(LPCTSTR(WinName2)));
DC1:=GetDc(wnd1);
Dc2:=GetDC(Wnd2);
if (DC1<>0)and(DC2<>0)then
begin


end;


Hook:=SetWindowsHookEx(WH_GETMESSAGE,@SysProc,Hinstance,0);

end;

if not bol then
begin
UnhookWindowsHookEx(Hook);
Hook:=0;
end;


end;
exports RunStopHook index 1;
begin

end.
А вызываю я ее из другогой екзехи примерно вот так:
Код:
program ProjectX;

{$APPTYPE CONSOLE}

uses
SysUtils,
Messages,
Dialogs,
Windows;

procedure RunStopHook(bol : Boolean) stdcall;external 'Project_X_dll.dll' index 1;
var
Done:boolean=false;
begin
RunStopHook(true);
while done=false do begin


end;


RunStopHook(false);

end.
Что - то похожее я смотрел в Книге "Делфи глазами хакера", или я чето не то сморозил щас??
Вроде я ж окно определяю в длл, и к нему не обращаюсь в главной программе?
 
Z

zubr

Еще раз пытаюсь объяснить. Во всех процессах в которых пользователь нажимает на клавишу клавиатуры возникает хуковое событие и данный процесс подгружает твою дллку (новый экземпляр). Но выполнение процедуры RunStopHook внутри твоей длл происходит только в экземпляре длл, который подгружает твой экзешник. Соответственно переменные Wnd1 и Wnd2 определяются только в одном экземпляре. В других же процессах, окна которых ты хочешь закрывать эти переменные равны 0. Можешь проверить вставив MtssageBox:
Код:
function SysProc(code:integer;wParam:word;lParam:Longint):longint;stdcall;
begin


Result:=CallNextHookEx(Hook,Code,wParam,lParam);
SendMessage(wnd2, WM_DESTROY, 0,0);
if code=HC_ACTION then begin
MessageBox(0, PChar(IntToStr(wnd1)), '', MB_OK);
MessageBox(0, PChar(IntToStr(wnd2)), '', MB_OK);

wndPromo:=TMsg(Pointer(lParam)^).hwnd;
if wndPromo=wnd1 then
begin
SendMessage(wnd2, WM_DESTROY, 0,0);
//  Ellipse(DC1,30,70,80,80);
end;
if wndPromo=wnd2 then
begin
SendMessage(wnd1, WM_DESTROY, 0,0);
//  Ellipse(DC2,30,70,80,80);

end;

end;
end;
Выход:
1. Определил хендлы в своем экзешнике
2. Передал их через структуру в отображение в память (файлмаппинг).
3. В длл прочитал значения этих хендлов из файлмаппинга.
 
Мы в соцсетях:

Обучение наступательной кибербезопасности в игровой форме. Начать игру!