unit HookUnit;
interface
uses
Windows, PEStuff, Classes;
type
TCreateMutex =
function(lpMutexAttributes: PSecurityAttributes; bInitialOwner: BOOL; lpName: PChar): THandle;
stdcall;
TCreateMutexA =
function(lpMutexAttributes: PSecurityAttributes; bInitialOwner: BOOL; lpName: PAnsiChar): THandle;
stdcall;
//Todo: TCreateMutexW ...
PPointer = ^Pointer;
TImportCode =
packed record
JumpInstruction: word;
// should be $25FF
AddressOfPointerToFunction: PPointer;
end;
PImportCode = ^TImportCode;
procedure HookFunctions;
procedure UnHookFunctions;
implementation
var
OldCreateMutex: TCreateMutex =
nil;
OldCreateMutexA: TCreateMutexA =
nil;
function NewCreateMutex(lpMutexAttributes: PSecurityAttributes; bInitialOwner: BOOL; lpName: PChar): THandle;
stdcall;
begin
Result := 0;
if Windows.MessageBox(0, lpName, '
[CreateMutex Hooked]', MB_OKCANCEL) = IDOK
then
Result := OldCreateMutex(lpMutexAttributes, bInitialOwner, lpName);
end;
function NewCreateMutexA(lpMutexAttributes: PSecurityAttributes; bInitialOwner: BOOL; lpName: PAnsiChar): THandle;
stdcall;
begin
Result := 0;
if Windows.MessageBox(0, lpName, '
[CreateMutexA Hooked]', MB_OKCANCEL) = IDOK
then
Result := OldCreateMutexA(lpMutexAttributes, bInitialOwner, lpName);
end;
function PointerToFunctionAddress(Code: Pointer): PPointer;
var
func: PImportCode;
begin
Result :=
nil;
if Code =
nil then Exit;
try
func := code;
if (func.JumpInstruction = $25FF)
then
begin
Result := func.AddressOfPointerToFunction;
end;
except
Result :=
nil;
end;
end;
function FinalFunctionAddress(Code: Pointer): Pointer;
var
func: PImportCode;
begin
Result := Code;
if Code =
nil then Exit;
try
func := code;
if (func.JumpInstruction = $25FF)
then
begin
Result := func.AddressOfPointerToFunction^;
end;
except
Result :=
nil;
end;
end;
function PatchAddress(OldFunc, NewFunc: Pointer): integer;
var
BeenDone: TList;
function PatchAddressInModule(hModule: THandle; OldFunc, NewFunc: Pointer): integer;
var
Dos: PImageDosHeader;
NT: PImageNTHeaders;
ImportDesc: PImage_Import_Entry;
rva: DWORD;
Func: PPointer;
DLL:
string;
f: Pointer;
written: DWORD;
begin
Result := 0;
Dos := Pointer(hModule);
if BeenDone.IndexOf(Dos) >= 0
then Exit;
BeenDone.Add(Dos);
OldFunc := FinalFunctionAddress(OldFunc);
if IsBadReadPtr(Dos, SizeOf(TImageDosHeader))
then Exit;
if Dos.e_magic <> IMAGE_DOS_SIGNATURE
then Exit;
NT := Pointer(integer(Dos) + dos._lfanew);
// if IsBadReadPtr(NT,SizeOf(TImageNtHeaders)) then exit;
RVA := NT^.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress;
if RVA = 0
then Exit;
ImportDesc := Pointer(integer(Dos) + RVA);
while (ImportDesc^.
Name <> 0)
do
begin
DLL := PChar(integer(Dos) + ImportDesc^.
Name);
PatchAddressInModule(GetModuleHandle(PChar(
DLL)), OldFunc, NewFunc);
Func := Pointer(integer(DOS) + ImportDesc.LookupTable);
while Func^ <>
nil do
begin
f := FinalFunctionAddress(Func^);
if f = OldFunc
then
begin
WriteProcessMemory(GetCurrentProcess, Func, @NewFunc, 4, written);
if Written > 0
then Inc(Result);
end;
Inc(Func);
end;
Inc(ImportDesc);
end;
end;
begin
BeenDone := TList.Create;
try
Result := PatchAddressInModule(GetModuleHandle(
nil), OldFunc, NewFunc);
finally
BeenDone.Free;
end;
end;
procedure HookFunctions;
begin
if @OldCreateMutex =
nil then
@OldCreateMutex := FinalFunctionAddress(@CreateMutex);
if @OldCreateMutexA =
nil then
@OldCreateMutexA := FinalFunctionAddress(@CreateMutexA);
PatchAddress(@OldCreateMutex, @NewCreateMutex);
PatchAddress(@OldCreateMutexA, @NewCreateMutexA);
end;
procedure UnhookFunctions;
begin
if @OldCreateMutex <>
nil then
PatchAddress(@NewCreateMutex, @OldCreateMutex);
if @OldCreateMutexA <>
nil then
PatchAddress(@NewCreateMutexA, @OldCreateMutexA);
end;
initialization
finalization
UnhookFunctions;
end.