Club Delphi  
    FTP   CCD     Buscar   Trucos   Trabajo   Foros

Retroceder   Foros Club Delphi > Principal > API de Windows
Registrarse FAQ Miembros Calendario Guía de estilo Buscar Temas de Hoy Marcar Foros Como Leídos

Respuesta
 
Herramientas Buscar en Tema Desplegado
  #1  
Antiguo 09-01-2017
angelp4492 angelp4492 is offline
Miembro
 
Registrado: dic 2007
Posts: 99
Poder: 0
angelp4492 cantidad desconocida en este momento
SetWindowsHookEx

Hola, como están.

Estoy intentado hacer un hook al mouse tengo una dll con el siguiente code.
Código Delphi [-]
library hook;


uses
  Windows,
  Messages,
  sysutils,
  dialogs;
const
      WH_MOUSE_LL = 14;
      var
      HookHandle: Cardinal;
   

 
{$R *.res}

function StopMouseHook: Boolean;stdcall;
begin
  UnhookWindowsHookEx(HookHandle);
  if HookHandle = 0 then
    Result := False
  else
   Result := True;
end;

function LowLevelMouseProc(nCode: Integer; wParam: wParam; lParam: lParam): LRESULT; stdcall;
Type
  tagMSLLHOOKSTRUCT = record
    POINT: TPoint;
    mouseData: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
  end;
  TMSLLHOOKSTRUCT = tagMSLLHOOKSTRUCT;
  PMSLLHOOKSTRUCT = ^TMSLLHOOKSTRUCT;
var
 Delta:Smallint;
 posx:Integer;
 posy:integer;
begin
   
  if (nCode >= 0) then
  begin
   
    if wParam = WM_LButtonDOWN then
    begin
           
           //hacer lo que queramos al detectar.
            showmessage('Me has pulsado');
    end;
  end;
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
end;

function startMouseHook: Boolean;stdcall;
 var
   msg:TMsg;
begin
  Result := false;
  if HookHandle = 0 then
  begin
     HookHandle := SetWindowsHookExW(WH_MOUSE_LL, @LowLevelMouseProc, HInstance, 0);
     Result := HookHandle <> 0;
  end;
end;

procedure DLLEntryPoint(dwReasonWORD);
begin
  case dwReason of
    DLL_PROCESS_ATTACH:
    begin

      startMouseHook;

     
    end;
    DLL_PROCESS_DETACH:
    begin

       StopMouseHook;
      
    end;

    end;
end;



begin
   DllProc:=@DLLEntryPoint;
  DLLEntryPoint(DLL_PROCESS_ATTACH);
end.

Esta dll si la cargo normal funciona bien, pero por el contrario si la inyecto en un proceso no me funciona. La inyección se realiza por que lo he comprobado por medio de un messagebox, he leido que SetwindowsHookex no funciona desde una dll inyectada. alguien a tenido el mismo problema.

Última edición por angelp4492 fecha: 09-01-2017 a las 18:44:16.
Responder Con Cita
  #2  
Antiguo 10-01-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 1.881
Poder: 12
escafandra Va camino a la famaescafandra Va camino a la fama
Si se puede inyectar la dll y funcionará. El hook sólo funciona en el contexto del thread que hace la llamada a SetWindowsHookEx. El problema es que si inyectas con CreateRemoteThread para provocar un LoarLibrary en un proceso remoto, el thread creado termina tras la inyección y por eso dejará de funcionar el hook al mouse.

La solución es crear un nuevo Thread que se mantenga en el proceso inyectado y listo:
Código Delphi [-]
library hook;


uses
  Windows,
  Messages,
  sysutils,
  dialogs;

const
  WH_MOUSE_LL = 14;

var
  HookHandle: Cardinal;
  TID: DWORD;

{$R *.res}

function StopMouseHook: Boolean;stdcall;
begin
  UnhookWindowsHookEx(HookHandle);
  if HookHandle = 0 then
    Result := False
  else
   Result := True;
end;

function LowLevelMouseProc(nCode: Integer; wParam: wParam; lParam: lParam): LRESULT; stdcall;
Type
  tagMSLLHOOKSTRUCT = record
    POINT: TPoint;
    mouseData: DWORD;
    flags: DWORD;
    time: DWORD;
    dwExtraInfo: DWORD;
  end;
  TMSLLHOOKSTRUCT = tagMSLLHOOKSTRUCT;
  PMSLLHOOKSTRUCT = ^TMSLLHOOKSTRUCT;
var
 Delta:Smallint;
 posx:Integer;
 posy:integer;
begin
  if (nCode >= 0) then
  begin
    if wParam = WM_LButtonDOWN then
    begin
      //hacer lo que queramos al detectar.
      //showmessage('Me has pulsado');
      Windows.Beep(1000, 100);
    end;
  end;
  Result := CallNextHookEx(HookHandle, nCode, wParam, lParam);
end;

function startMouseHook: Boolean;stdcall;
 var
   msg:TMsg;
begin
  Result := false;
  if HookHandle = 0 then
  begin
     HookHandle := SetWindowsHookEx(WH_MOUSE_LL, @LowLevelMouseProc, Hinstance, 0);
     Result := HookHandle <> 0;
  end;
end;

procedure ThreadHook;
var
  msg: TMsg;
begin
  startMouseHook;
  repeat
    PeekMessage(msg,0,0,0, PM_REMOVE);
  until (msg.message = WM_QUIT);
  StopMouseHook;
end;

procedure DLLEntryPoint(dwReason: integer);
begin
  case dwReason of
    DLL_PROCESS_ATTACH:
    begin
      CloseHandle(CreateThread(nil, 0, @ThreadHook, nil, 0, TID));
    end;
    DLL_PROCESS_DETACH:
    begin
      PostThreadMessage(TID, WM_QUIT, 0, 0);
    end;
  end;
end;

begin
  DllProc:=@DLLEntryPoint;
  DLLEntryPoint(DLL_PROCESS_ATTACH);
end.

Este problema no aparece si realizas la técnica de inyección por suspensión de thread, más compleja y que requiere inyección directa.
Ten en cuenta que si tu S.O. es de 64bits, no puedes inyectar una dll 32bits en procesos 64bits. Para eso debes compilar tu dll y tu inyector a 64bits.


Saludos.
Responder Con Cita
  #3  
Antiguo 10-01-2017
angelp4492 angelp4492 is offline
Miembro
 
Registrado: dic 2007
Posts: 99
Poder: 0
angelp4492 cantidad desconocida en este momento
Gracias escafandra, lo pruebo en cuanto llegue a casa. Precisamente estoy siguiendo un tutorial tuyo sobre Api_hook espectacular por cierto.

la técnica que utizo para la inyección es como tu bien dices CreateremoteThread (seguro que alguna función publicada por tí), voy a buscar la técnica que me indicas de suspender el thread.

Tengo un poco de lio con la inyección en 64 bit y de 32 bit.

a ver yo tengo un pc con windows 7 de 64 bits y hay procesos que corren en 32 bits (firefox.exe *32) por ejemplo y otros en 64 bits.

con esta inyección me funciona en un pc con windows 7 32 bit, pero no me funciona en windows 7 64 bits en proceso de 32 bits. (ni compilando la dll y el injector en el pc de 64 bits, CreateremoteThread me devuelve 0 y sale).

Código Delphi [-]
function InjectLib(ProcessID: Integer): Boolean;
var
  Process: HWND;
  ThreadRtn: FARPROC;
  DllPath: AnsiString;
  RemoteDll: Pointer;
  BytesWriten: DWORD;
  Thread: DWORD;
  ThreadId: DWORD;

  aux:string;
begin
  Result := False;
  Process := OpenProcess(PROCESS_CREATE_THREAD or PROCESS_VM_OPERATION or PROCESS_VM_WRITE,
                         True,
                         ProcessID);
  if Process = 0 then Exit; 
  try

   
    DllPath := AnsiString(ExtractFilePath(ParamStr(0)) + DLLName) + #0;
   

    RemoteDll := VirtualAllocEx(Process,
                                nil,
                                Length(DllPath),
                                MEM_COMMIT or MEM_TOP_DOWN, PAGE_READWRITE);
    if RemoteDll = nil then Exit;
    try
     
      if not WriteProcessMemory(Process,
                                RemoteDll,
                                PChar(DllPath),
                                Length(DllPath),
                                BytesWriten)      then Exit;
      if BytesWriten <> DWORD(Length(DllPath)) then Exit;
      
      ThreadRtn := GetProcAddress(GetModuleHandle('Kernel32.dll'),
                                                  'LoadLibraryA');
      
      if ThreadRtn = nil then Exit;
    
      Thread := CreateRemoteThread(Process,
                                   nil,
                                   0,
                                   ThreadRtn,
                                   RemoteDll,
                                   0,
                                   ThreadId);
      if Thread = 0 then Exit;
      try
       
        Result := WaitForSingleObject(Thread,
                                      INFINITE) = WAIT_OBJECT_0;
      finally
        CloseHandle(Thread);
      end;
    finally
      VirtualFreeEx(Process,
                    RemoteDll,
                    0,
                    MEM_RELEASE);
    end;
  finally
    CloseHandle(Process);
  end;
end;

function GetPID(ExeFileName: string): dword;
var
  ContinueLoop, ffound: boolean;
  FSnapshotHandle: THandle;
  FProcessEntry32: TProcessEntry32;
  UpEFN: string;
begin
  result := 0;
  ffound := false;
  UpEFN := UpperCase(ExeFileName);
  FSnapshotHandle := CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
  FProcessEntry32.dwSize := SizeOf(FProcessEntry32);
  ContinueLoop := Process32First(FSnapshotHandle, FProcessEntry32);
  while integer(ContinueLoop) <> 0 do
  begin
    if ((UpperCase(ExtractFileName(FProcessEntry32.szExeFile)) = UpEFN) or
        (UpperCase(FProcessEntry32.szExeFile) = UpEFN)) then
    begin
      result := FProcessEntry32.th32ProcessID;
      ffound := true;
      break;
    end;
    ContinueLoop := Process32Next(FSnapshotHandle, FProcessEntry32);
  end;
  CloseHandle(FSnapshotHandle);
  if not ffound then
    ShowMessage(ExeFileName+'is not runing');
end;



var
  PID: dword;
begin

  PID := GetPID('notepad.exe');
 
  if (PID > 0) then

  if InjectLib(PID) = True then
       Application.MessageBox('Inyección OK', 'Application.Title', MB_OK +
       MB_ICONINFORMATION);

Última edición por angelp4492 fecha: 10-01-2017 a las 13:42:23.
Responder Con Cita
  #4  
Antiguo 10-01-2017
Avatar de Casimiro Notevi
Casimiro Notevi Casimiro Notevi is offline
Moderador
 
Registrado: sep 2004
Ubicación: En algún lugar.
Posts: 27.488
Poder: 10
Casimiro Notevi Tiene un aura espectacularCasimiro Notevi Tiene un aura espectacular
Cita:
Empezado por angelp4492 Ver Mensaje
con esta inyección me funciona en un pc con windows 7 32 bit, pero no me funciona en windows 7 64 bits en proceso de 32 bits.
Seguramente tendrás que crearla compilando 64 bits, con las versiones nuevas de delphi, o con lazarus.
Responder Con Cita
  #5  
Antiguo 10-01-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 1.881
Poder: 12
escafandra Va camino a la famaescafandra Va camino a la fama
Reglas básicas:

1. No puedes inyectar código 32 bits en un proceso de 64bits
2. No puedes inyectar código 64bits en un proceso de 32bits.
3. Si puedes inyectar 32->32 y 64->64
4. Para inyectar en 32bits necesitas un inyector compilado a 32bits
5. Para inyectar 64bits necesitas un inyector compilado a 64bits.
6. Las dos últimas reglas pueden solucionarse teóricamente con técnicas complejas.

Saludos.
Responder Con Cita
  #6  
Antiguo 10-01-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 1.881
Poder: 12
escafandra Va camino a la famaescafandra Va camino a la fama
Código Delphi [-]
function InjectCRT(Pid: integer; dll: PCHAR): BOOL;
var
   hThread:  THANDLE;
   ExitCode: DWORD;
   hLib:     Pointer;//LPTHREAD_START_ROUTINE;
   hProc:    THANDLE;
   Buffer:   Pointer;
begin
   Result:= false;
   if(dll^ = #0) then exit;
 
   hThread:= 0;
   ExitCode:= 0;
   hProc:= OpenProcess(PROCESS_ALL_ACCESS, false, Pid);
   if hProc<>0 then
   begin
     Buffer:= VirtualAllocEx(hProc, nil, lstrlen(dll)+1, MEM_COMMIT or MEM_RESERVE, PAGE_READWRITE);
     if Buffer<>nil then
     begin
       if WriteProcessMemory(hProc, Buffer, dll, lstrlen(dll)+1, PDWORD(0)^) then
       begin
         hLib:= GetProcAddress(GetModuleHandle('Kernel32.dll'), 'LoadLibraryA');
         if hLib <> nil then
         begin
           hThread:= CreateRemoteThread(hProc, nil, 0, hLib, Buffer, 0, PDWORD(0)^);
           if hThread <> 0 then
           begin
             // libero la memoria localizada...
             WaitForSingleObject(hThread, INFINITE);  // Espero a que se cree y termine el Thread
             GetExitCodeThread(hThread, ExitCode);    // Extraigo el código de terminación del Thread
             CloseHandle(hThread);                    // Cierro el Handle hThread
           end;
         end;
       end;
       VirtualFreeEx(hProc, Buffer, 0, MEM_RELEASE);  // Libero memoria
     end;
     CloseHandle(hProc);                       // Cierro el Handle hProc
   end;
   Result:= (ExitCode <> 0);
end;


Saludos.
Responder Con Cita
  #7  
Antiguo 10-01-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 1.881
Poder: 12
escafandra Va camino a la famaescafandra Va camino a la fama
Cita:
Empezado por angelp4492 Ver Mensaje
Gracias escafandra, lo pruebo en cuanto llegue a casa. Precisamente estoy siguiendo un tutorial tuyo sobre Api_hook espectacular por cierto.

la técnica que utizo para la inyección es como tu bien dices CreateremoteThread (seguro que alguna función publicada por tí), voy a buscar la técnica que me indicas de suspender el thread.
Aquí tienes dos tutoriales sobre la inyección directa de código, recuerda que son vigentes las 6 normas básicas:
Inyección directa de código en C y en delphi
Inyección directa de código II


Saludos.
Responder Con Cita
  #8  
Antiguo 10-01-2017
angelp4492 angelp4492 is offline
Miembro
 
Registrado: dic 2007
Posts: 99
Poder: 0
angelp4492 cantidad desconocida en este momento
Funciono Perfecto. Gracias escafandra, voy a revisar los enlaces que me has puesto.
Responder Con Cita
  #9  
Antiguo 11-01-2017
angelp4492 angelp4492 is offline
Miembro
 
Registrado: dic 2007
Posts: 99
Poder: 0
angelp4492 cantidad desconocida en este momento
Hola me surgió una nueva duda. ahora que todo va bien con la inyección y el hook al mouse, intento capturar el titulo de la ventana activa al pulsar un boton pero no me sale. Lo he intentado con GetwindowsText pero en la MSDN dice que si estamos en otro proceso utilizar SendMessage con WM_GETTEXT.
este es el codigo en condiciones normales si funciona.

Código Delphi [-]
function GetWindowText: WideString;
var
  TextLength: Integer;
  Text: PWideChar;
  wnd: HWND;
begin
  Result := '';
  if wnd = 0 then
    Exit;
    wnd:=GetActiveWindow;;
  TextLength := SendMessageW(wnd, WM_GETTEXTLENGTH, 0, 0);
  if TextLength <> 0 then
  begin
    GetMem(Text, TextLength * 2 + 1);
    SendMessageW(wnd, WM_GETTEXT, TextLength + 1, Integer(Text));
    Result := Text;
    FreeMem(Text);
  end;
end;

que estoy haciendo mal, donde se me ha perdido el handle

Última edición por angelp4492 fecha: 11-01-2017 a las 19:05:00.
Responder Con Cita
  #10  
Antiguo 11-01-2017
Avatar de escafandra
[escafandra] escafandra is offline
Miembro Premium
 
Registrado: nov 2007
Posts: 1.881
Poder: 12
escafandra Va camino a la famaescafandra Va camino a la fama
Código Delphi [-]
function GetWindowText: WideString;
var
  TextLength: Integer;
  Text: PWideChar;
  Wnd: HWND;
begin
  Wnd:= GetActiveWindow;
  TextLength:= SendMessageW(Wnd, WM_GETTEXTLENGTH, 0, 0);
  if TextLength <> 0 then
  begin
    GetMem(Text, TextLength * 2 + 2);
    SendMessageW(Wnd, WM_GETTEXT, WPARAM(TextLength*2 + 2), LPARAM(Text));
    Result := Text;
    FreeMem(Text);
  end;
end;


Saludos.
Responder Con Cita
  #11  
Antiguo 11-01-2017
angelp4492 angelp4492 is offline
Miembro
 
Registrado: dic 2007
Posts: 99
Poder: 0
angelp4492 cantidad desconocida en este momento
Gracias, escafandra casi lo tenia
Responder Con Cita
Respuesta


Herramientas Buscar en Tema
Buscar en Tema:

Búsqueda Avanzada
Desplegado

Normas de Publicación
no Puedes crear nuevos temas
no Puedes responder a temas
no Puedes adjuntar archivos
no Puedes editar tus mensajes

El código vB está habilitado
Las caritas están habilitado
Código [IMG] está habilitado
Código HTML está deshabilitado
Saltar a Foro

Temas Similares
Tema Autor Foro Respuestas Último mensaje
Sobre SetWindowsHookEx dec Trucos 0 01-07-2006 00:31:30


La franja horaria es GMT +2. Ahora son las 08:59:37.


Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2017, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi
Copyright 1996-2007 Club Delphi