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

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/

Отправить комментарий

Проверка
Антиспам проверка
Image CAPTCHA
...