delphicallbackdelphi-10-seattleapi-hook

Is possible hook EnumWindowsProc callback function?


I want know if is possible hook a callback function for example like EnumWindowsProc() using inline hook approach? and if yes, could provide a code snippet (example) please?

Thank you.


EDITION:

EnumWindowsProc is a callback implemented in other app. I not call it inside my app.

And i want hook EnumWindowsProc in this other app, by dll injection.


Solution

  • You have to handle EnumWindows at first, then you have to replace pointer to original EnumWindowsProc to yourself.

    My example is valid fow win32

    unit Patch;
    
    interface
    
    procedure PatchEnumWindows(Patch: Boolean);
    
    implementation
    uses SysUtils, SyncObjs, Windows;
    
    const
      INSTR_SIZE = 6;
    
    var
      OldEnumWindows: array [0..INSTR_SIZE-1] of Byte;
      EnumWindowsPatched: Boolean = False;
    
    function PatchedEnumWindows(EnumWindowsProc: Pointer; Param: Pointer); stdcall;
    begin
      // You have to replace original EnumWindowsProc to yourself
    end;
    
    
    procedure ApiRedirect(OrigFunction, NewFunction: Pointer; var Old);
    const
      TEMP_JMP: array[0..INSTR_SIZE-1] of Byte = ($E9,$90,$90,$90,$90,$C3);
    var
      JmpSize: DWORD;
      JMP: array [0..INSTR_SIZE-1] of Byte;
      OldProtect: DWORD;
    begin
      Move(TEMP_JMP, JMP, INSTR_SIZE);
      JmpSize := DWORD(NewFunction) - DWORD(OrigFunction) - 5;
      if not VirtualProtect(LPVOID(OrigFunction), INSTR_SIZE, PAGE_EXECUTE_READWRITE,         OldProtect) then
        raise Exception.CreateFmt('%s', [SysErrorMessage(GetLastError)]);
      Move(OrigFunction^, Old, INSTR_SIZE);
      Move(JmpSize, JMP[1], 4);
      Move(JMP, OrigFunction^, INSTR_SIZE);
      VirtualProtect(LPVOID(OrigFunction), INSTR_SIZE, OldProtect, nil);
    end;
    
    procedure PatchEnumWindows(Patch: Boolean);
    var
      OrigEnumWindows: Pointer;
    begin
      if Patch <> EnumWindowsProcPatched then begin
        OrigEnumWindows := GetProcAddress(GetModuleHandle('user32.dll'), 'EnumWindows');
        if Patch then begin
          ApiRedirect(OrigEnumWindows, @PatchedEnumWindows, OldEnumWindows);
        end
        else begin
          Move(OldEnumWindows, OrigEnumWindows, INSTR_SIZE);
        end;
        EnumWindowsPatched := Patch;
      end;
    end;
    
    
    end.