// функция служит для выяснения существования VMT у класса // возвращает True, если класс имеет VMT и False - если нет function IsVMTExist(Cls: TClass): Boolean;
// процедура служит для замены адреса метода в VMT класса со смещением // Offset(должно быть кратно 4) новым адресом, хранящимся в NewMet // примечание: перед вызовом этой процедуры проверяйте существование // VMT у класса функцией IsVMTExist procedure VirtMethodReplace(Cls: TClass; Offset: LongWord; NewMet: Pointer); overload;
// процедура служит для замены адреса метода, хранящегося в OldMet, // в VMT класса новым адресом, хранящимся в NewMet // примечание: перед вызовом этой процедуры проверяйте существование // VMT у класса функцией IsVMTExist procedure VirtMethodReplace(Cls: TClass; OldMet, NewMet: Pointer); overload;
// функция служит для замены адреса динамического метода класса с индексом, // хранящимся в Index, новым адресом, хранящимся в NewMet // возвращает True, если метод с данным индексом найден и False - если нет function DynMethodReplace(Cls: TClass; Index: Word; NewMet: Pointer): Boolean; overload;
// функция служит для замены адреса динамического метода класса, хранящегося // в OldMet, новым адресом, хранящимся в NewMet // возвращает True, если метод с данным адресом найден и False - если нет function DynMethodReplace(Cls: TClass; OldMet, NewMet: Pointer): Boolean; overload;
implementation
// функция служит для получения указателя на байт, следующий за адресом // последнего метода в VMT класса // возвращает nil в случае, если у класса нет VMT // функция является "внутренней" в модуле // (используется другими подпрограммами и не объявлена в секции interface) // , поэтому используйте её только если // Вы полностью уверены в своих действиях(она изменяет "рабочие" регистры // ECX и EDX) function GetVMTEnd(Cls: TClass): Pointer; asm // Вход: Cls --> EAX // Выход: Result --> EAX
PUSH EDI MOV EDI, EAX PUSH ECX PUSH EDX PUSH EAX CALL GetVMTEnd POP EDX SUB EAX, EDX SHR EAX, 2 POP EDX POP ECX PUSH ECX MOV ECX, EAX MOV EAX, EDX POP EDX REPNE SCASD JNE @@OldMet_not_found MOV [EDI - 4], EDX @@OldMet_not_found: POP EDI
end;
function DynMethodReplace(Cls: TClass; Index: Word; NewMet: Pointer): Boolean; overload; asm // Вход: Cls --> EAX, Index --> DX, NewMet --> ECX // Выход: Result --> AL
PUSH EDI PUSH ESI MOV ESI, ECX XOR EAX, EDX XOR EDX, EAX XOR EAX, EDX JMP @@start @@cycle: MOV EDX, [EDX] @@start: MOV EDI, [EDX].vmtDynamicTable TEST EDI, EDI JZ @@get_parent_dmt MOVZX ECX, WORD PTR [EDI] PUSH ECX ADD EDI, 2 REPNE SCASW JE @@Index_found POP ECX @@get_parent_dmt: MOV EDX, [EDX].vmtParent TEST EDX, EDX JNZ @@cycle JMP @@Index_not_found @@Index_found: POP EAX SHL EAX, 1 SUB EAX, ECX MOV [EDI + EAX * 2 - 4], ESI MOV AL, 1 JMP @@exit @@Index_not_found: XOR AL, AL @@exit: POP ESI POP EDI
end;
function DynMethodReplace(Cls: TClass; OldMet, NewMet: Pointer): Boolean; overload; asm // Вход: Cls --> EAX, OldMet --> EDX, NewMet --> ECX // Выход: Result --> AL
PUSH EDI PUSH ESI MOV ESI, ECX XOR EAX, EDX XOR EDX, EAX XOR EAX, EDX JMP @@start @@cycle: MOV EDX, [EDX] @@start: MOV EDI, [EDX].vmtDynamicTable TEST EDI, EDI JZ @@get_parent_dmt MOVZX ECX, WORD PTR [EDI] LEA EDI, EDI + 2 * ECX + 2 REPNE SCASD JE @@OldMet_found @@get_parent_dmt: MOV EDX, [EDX].vmtParent TEST EDX, EDX JNZ @@cycle JMP @@OldMet_not_found @@OldMet_found: MOV [EDI - 4], ESI MOV AL, 1 JMP @@exit @@OldMet_not_found: XOR AL, AL @@exit: POP ESI POP EDI
end;
end. Автор ___ALex___ Форум: http://forum.pascal.dax.ru/