Page 1 of 1

How hook EnumWindows() to prevent target application enumerate any window of my software?

PostPosted:Wed Apr 10, 2019 11:21 pm
by pointer
I have the following code able to hook EnumWindows() function and works fine. But target application (3rd's application) crash when the dll is injected. Then this could be solved, for example, making this code prevent the target application enumerate only all windows of my software and then call original EnumWindows() function to enumerate others windows?
Code: Select all
library Project1;

uses
  Windows,
  SysUtils,
  Classes,
  Patch;

{$R *.res}

var
  ThreadId: LongWord;
  ThreadHandle: Integer;

function ThreadFunc(Parameter: Pointer): Integer;
begin
  PatchEnumWindows(True);
  Result := 0;
end;

procedure DLLEntryPoint(dwReason: DWORD);
begin
  case dwReason of
    DLL_PROCESS_ATTACH:
      begin
        ThreadHandle := BeginThread(nil, 0, @ThreadFunc, nil, 0, ThreadId);
      end;

  end;
end;

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

end.
----------------------------------------------------------------------------------------------------------------------------------------------
Code: Select all
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)
  : BOOL; stdcall;
begin
  // You have to replace original EnumWindowsProc to yourself
  Result := True;
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 <> EnumWindowsPatched 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.
I hope that you can help me :)

Re: How hook EnumWindows() to prevent target application enumerate any window of my software?

PostPosted:Mon Apr 15, 2019 4:01 pm
by Codefuser
Most likely calling convention issues, you don't seem to be using C so whatever language that is might be using the wrong calling convention.

Use C instead and use __stdcall.

Re: How hook EnumWindows() to prevent target application enumerate any window of my software?

PostPosted:Tue Apr 16, 2019 12:42 pm
by Brock
Why are you creating a thread in DLLMain just to patch an API? Do this directly in DLLMain and get rid of your handle leaking BeginThread call. Threads also don't run until DLLMain is complete because loader lock is held, so no sense in delaying the patch either. Also, inside the ugly patch routine at the very least check result of first VirtualProtect call and then after re-protect VirtualProtect call use FlushInstructionCache. Plenty of good Delphi examples of this online even