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
I hope that you can help me :)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.