1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92
|
type
TDynamicIndexList = array[0..MaxInt div 16] of Word;
PDynamicIndexList = ^TDynamicIndexList;
TDynamicAddressList = array[0..MaxInt div 16] of Pointer;
PDynamicAddressList = ^TDynamicAddressList;
function GetDynamicMethodCount(AClass: TClass): Integer;
asm
MOV EAX, [EAX].vmtDynamicTable
TEST EAX, EAX
JE @@exit
MOVZX EAX, Word ptr [EAX]
@@exit:
end;
function GetDynamicIndexList(AClass: TClass): PDynamicIndexList;
asm
MOV EAX, [EAX].vmtDynamicTable
ADD EAX, 2
end;
function GetDynamicAddressList(AClass: TClass): PDynamicAddressList;
asm
MOV EAX, [EAX].vmtDynamicTable
MOVZX EDX, Word ptr [EAX]
ADD EAX, EDX
ADD EAX, EDX
ADD EAX, 2
end;
function GetDynMethodPatch(AClass : TClass; idx : Word) : PPointer;
var
nb : integer;
i : integer;
IndexList : PDynamicIndexList;
MethodList : PDynamicAddressList;
begin
repeat
nb := GetDynamicMethodCount(AClass);
if nb >0
then begin
IndexList := GetDynamicIndexList(AClass);
MethodList := GetDynamicAddressList(AClass);
for i := 0 to nb-1 do
begin
if IndexList[i] = idx
then begin
result := @(MethodList[i]);
exit;
end;
end;
end;
AClass := AClass.ClassParent;
until not Assigned(AClass);
result := nil;
end;
procedure InstallIntercept(AClass : TClass);
var
nb : integer;
IndexList : PDynamicIndexList;
MethodList : PDynamicAddressList;
i : integer;
idx : integer;
Original : pointer;
PatchOriginal : PPointer;
PatchIntercept : PPointer;
oldProtect : cardinal;
begin
nb := GetDynamicMethodCount(AClass);
IndexList := GetDynamicIndexList(AClass);
MethodList := GetDynamicAddressList(AClass);
for i := 0 to nb-1 do
begin
idx := IndexList[i];
PatchOriginal := GetDynMethodPatch(AClass.ClassParent, idx);
PatchIntercept := @(MethodList[i]);
Original := PatchOriginal^;
VirtualProtect(PatchOriginal, sizeof(pointer), PAGE_READWRITE, @oldProtect);
PatchOriginal^ := PatchIntercept^;
VirtualProtect(PatchOriginal, sizeof(pointer), oldProtect, nil);
VirtualProtect(PatchIntercept, sizeof(pointer), PAGE_READWRITE, @oldProtect);
PatchIntercept^ := Original;
VirtualProtect(PatchIntercept, sizeof(pointer), oldProtect, nil);
end;
end; |
Partager