Как редактировать таблицы виртуальных и динамических методов?

Previous  Top  Next

    
 

 

 

Code:

unit EditorVMTandDMTTables;

 

interface

 

// функция служит для выяснения существования 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    EBX

       MOV     ECX, 8

       MOV     EBX, -1

       MOV     EDX, vmtSelfPtr

@@cycle:

       ADD     EDX, 4

       CMP     [EAX + EDX], EAX

       JE      @@vmt_not_found

       JB      @@continue

       CMP     [EAX + EDX], EBX

       JAE     @@continue

       MOV     EBX, [EAX + EDX]

@@continue:

       DEC     ECX

       JNZ     @@cycle

       MOV     EAX, EBX

       JMP     @@exit

@@vmt_not_found:

       XOR     EAX, EAX

@@exit:

       POP     EBX

end;

 

function IsVMTExist(Cls: TClass): Boolean;

asm

       // Вход: Cls --> EAX

       // Выход: Result --> AL

 

       CALL    GetVMTEnd

       TEST    EAX, EAX

       JZ      @@vmt_not_found

       MOV     AL, 1

@@vmt_not_found:

end;

 

procedure VirtMethodReplace(Cls: TClass; Offset: LongWord; NewMet: Pointer); overload;

asm

      // Вход: Cls --> EAX, Offset --> EDX, NewMet --> ECX

       MOV     [EAX + EDX], ECX

end;

 

procedure VirtMethodReplace(Cls: TClass; OldMet, NewMet: Pointer); overload;

asm

       // Вход: Cls --> EAX, OldMet --> EDX, NewMet --> ECX

       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/

©Drkb::00104