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


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



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/





DELPHI FAQ




EOMY TOP 100      Рейтинг@Mail.ru      Rambler's Top100