Delphi面向对象编程
2021-03-28 23:26
标签:用户 编程 阅读 地址 find read idt sys border 反汇编代码如下。 调用TWorker.Create后,成功返回一个对象的实例,接着,按照fastcall调用约定,调用了Worker.SetWorker方法。 此处实际隐含了一个Self指针,即C++里的this指针。 Work.SetWorker的反汇编代码如下。 此时,Worker的内存布局如下。 00943DB0 9C DF 44 00 C8 3D 94 00 37 00 00 00 溸D.??7.....
0x943DC8指向[Marx]字符串,0x37(55)即nAge。 反汇编代码如下。 此时ClassA的内存构造如下。 00953D8C 48 27 45 00 H‘E.
0x452748的内存如下。 00452748 54 27 45 00 T‘E.
0x452754,即虚方法地址。 反汇编代码如下。 反汇编代码如下。 此时ClassB的内存构造如下。 00953D8C A0 27 45 00 ?E..
0x4527A0的内存如下。 004527A0 B4 27 45 00 E0 27 45 00 FC 27 45 00 ?E.?E.?E.TC
0x4527B4、0x4527E0、0x4527FC。这是虚方法表,分别对应了3个虚方法。其中第一个是从父类TClassA里继承下来的。 与虚方法的调用不同,动态方法使用索引调用,而且是通过CallDynaInst这个库函数实现。 而该库函数只是简单的从Self指针里取出了VMT([Self + 0]),就转给另一个库函数了。该库函数的反汇编代码如下。 代码我没有标注释,简单解释一下意思吧。首先,从[VMT– 0x30]处,得到动态方法的表起始地址。 本例中的动态方法表如下。 00452748 01 00 FF FF 58 27 45 00 .X‘E.
然后调用串操作指令对该动态方法表进行扫描,本例中ClassA.GetName动态方法的索引序号为0xFFFF。 这是拖放事件的一个小应用。 用户将Edit拖动到Memo上时,则Edit里的内容会被添加到Memo中。 反汇编代码如下。 只是取出Source的VMT进行比对。 只要得到VMT,并对其中的虚方法表进行替换就可以了。前提必须知道要HOOK的虚方法的索引位置。 本文权当抛砖引玉,如果想要更深入研究,请阅读Delphi帮助文件中和RTTI有关的内容。 Delphi面向对象编程 标签:用户 编程 阅读 地址 find read idt sys border 原文地址:https://www.cnblogs.com/galano/p/9314039.html
implementation
{$R *.dfm}
type
TWorker = class(TObject)
public
Name: string;
Age: Cardinal;
procedure SetWorker(sName: string; nAge: Cardinal);
end;
procedure TWorker.SetWorker(sName: string; nAge: Cardinal);
begin
Name := sName;
Age := nAge;
end;
procedure TForm1.Button1Click(Sender: TObject);
var
Worker: TWorker;
begin
Worker := TWorker.Create;
Worker.SetWorker(‘Marx‘, 55);
end;
CODE:0044E00C _TForm1_Button1Click proc near ; DATA XREF: CODE:0044DF10o
CODE:0044E00C mov dl, 1
CODE:0044E00E mov eax, off_44DF50
CODE:0044E013 call unknown_libname_26 ; BDS 2005-2007 and Delphi6-7 Visual Component Library ;TWorker.Create
CODE:0044E018 mov ecx, 37h ;nAge
CODE:0044E01D mov edx, offset _str_Marx.Text ;sString
CODE:0044E022 call sub_44DFB8 ;Worker.SetWorker
CODE:0044E027 retn
CODE:0044E027 _TForm1_Button1Click endp
寄存器
说明
EAX
Self
EDX
sString
ECX
nAge
CODE:0044DFB8 sub_44DFB8 proc near ; CODE XREF: _TForm1_Button1Click+16p
CODE:0044DFB8
CODE:0044DFB8 var_4 = dword ptr -4
CODE:0044DFB8
CODE:0044DFB8 push ebp
CODE:0044DFB9 mov ebp, esp
CODE:0044DFBB push ecx
CODE:0044DFBC push ebx
CODE:0044DFBD push esi
CODE:0044DFBE mov esi, ecx
CODE:0044DFC0 mov [ebp+var_4], edx
CODE:0044DFC3 mov ebx, eax ; EBX - > Self
CODE:0044DFC5 mov eax, [ebp+var_4]
CODE:0044DFC8 call @System@@LStrAddRef$qqrpv ; System::__linkproc__ LStrAddRef(void *)
CODE:0044DFCD xor eax, eax
CODE:0044DFCF push ebp
CODE:0044DFD0 push offset loc_44DFFF
CODE:0044DFD5 push dword ptr fs:[eax]
CODE:0044DFD8 mov fs:[eax], esp
CODE:0044DFDB lea eax, [ebx+4] ; EAX - > Self + 4
CODE:0044DFDE mov edx, [ebp+var_4] ; EDX - > sName
CODE:0044DFE1 call @System@@LStrAsg$qqrpvpxv ; 执行字符串拷贝工作
CODE:0044DFE6 mov [ebx+8], esi ; [Self + 8] = nAge
CODE:0044DFE9 xor eax, eax
CODE:0044DFEB pop edx
CODE:0044DFEC pop ecx
CODE:0044DFED pop ecx
CODE:0044DFEE mov fs:[eax], edx
implementation
{$R *.dfm}
type
TClassA = class(TObject)
public
procedure GetName(); virtual;
end;
procedure TClassA.GetName();
begin
ShowMessage(‘My Name is "TClassA"‘);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ClassA: TClassA;
begin
classA := TClassA.Create;
ClassA.GetName;
ClassA.Free;
end;
00452754 . B8 68274500 mov eax,Project1.00452768
00452759 . E8 2E8DFDFF call Project1.0042B48C
0045275E . C3 retn
implementation
{$R *.dfm}
type
TClassA = class(TObject)
public
procedure GetName(); virtual;
end;
TClassB = class(TClassA)
public
procedure GetAge(); virtual;
procedure GetInfor(); virtual;
end;
procedure TClassA.GetName();
begin
ShowMessage(‘My Name is "TClassA"‘);
end;
procedure TClassB.GetAge();
begin
ShowMessage(‘I am 16‘);
end;
procedure TClassB.GetInfor();
begin
ShowMessage(‘I am a senior school teacher‘);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ClassB: TClassB;
begin
ClassB := TClassB.Create;
ClassB.GetName();
ClassB.GetAge();
ClassB.GetInfor();
ClassB.Free;
end;
CODE:00452830 _TForm1_Button1Click proc near ; DATA XREF: CODE:004526BCo
CODE:00452830 push ebx
CODE:00452831 mov dl, 1
CODE:00452833 mov eax, off_452754
CODE:00452838 call unknown_libname_26 ; BDS 2005-2007 and Delphi6-7 Visual Component Library
CODE:0045283D mov ebx, eax
CODE:0045283F mov eax, ebx
CODE:00452841 mov edx, [eax]
CODE:00452843 call dword ptr [edx]
CODE:00452845 mov eax, ebx
CODE:00452847 mov edx, [eax]
CODE:00452849 call dword ptr [edx+4]
CODE:0045284C mov eax, ebx
CODE:0045284E mov edx, [eax]
CODE:00452850 call dword ptr [edx+8]
CODE:00452853 mov eax, ebx ; this
CODE:00452855 call @System@TObject@Free$qqrv ; System::TObject::Free(void)
CODE:0045285A pop ebx
CODE:0045285B retn
CODE:0045285B _TForm1_Button1Click endp
implementation
{$R *.dfm}
type
TClassA = class(TObject)
public
procedure GetName(); dynamic;
end;
procedure TClassA.GetName();
begin
ShowMessage(‘I am Mike‘);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ClassA: TClassA;
begin
ClassA := TClassA.Create;
ClassA.GetName();
ClassA.Free;
end;
反汇编代码如下。
CODE:00452778 _TForm1_Button1Click proc near ; DATA XREF: CODE:004526BCo
CODE:00452778 push ebx
CODE:00452779 push esi
CODE:0045277A mov dl, 1
CODE:0045277C mov eax, off_4526FC
CODE:00452781 call unknown_libname_26 ; BDS 2005-2007 and Delphi6-7 Visual Component Library
CODE:00452786 mov ebx, eax
CODE:00452788 mov eax, ebx
CODE:0045278A mov si, 0FFFFh
CODE:0045278E call @System@@CallDynaInst$qqrv ; System::__linkproc__ CallDynaInst(void)
CODE:00452793 mov eax, ebx ; this
CODE:00452795 call @System@TObject@Free$qqrv ; System::TObject::Free(void)
CODE:0045279A pop esi
CODE:0045279B pop ebx
CODE:0045279C retn
CODE:0045279C _TForm1_Button1Click endp
CODE:00403668 unknown_libname_28 proc near ; CODE XREF: System::__linkproc__ CallDynaInst(void)+4p
CODE:00403668 ; System::__linkproc__ FindDynaInst(void)+5p ...
CODE:00403668 push edi
CODE:00403669 xchg eax, esi
CODE:0040366A jmp short loc_40366E
CODE:0040366C ; ---------------------------------------------------------------------------
CODE:0040366C
CODE:0040366C loc_40366C: ; CODE XREF: unknown_libname_28+1Fj
CODE:0040366C mov esi, [esi]
CODE:0040366E
CODE:0040366E loc_40366E: ; CODE XREF: unknown_libname_28+2j
CODE:0040366E mov edi, [esi-30h]
CODE:00403671 test edi, edi
CODE:00403673 jz short loc_403682
CODE:00403675 movzx ecx, word ptr [edi]
CODE:00403678 push ecx
CODE:00403679 add edi, 2
CODE:0040367C repne scasw
CODE:0040367F jz short loc_40368B
CODE:00403681 pop ecx
CODE:00403682
CODE:00403682 loc_403682: ; CODE XREF: unknown_libname_28+Bj
CODE:00403682 mov esi, [esi-24h]
CODE:00403685 test esi, esi
CODE:00403687 jnz short loc_40366C
CODE:00403689 pop edi
CODE:0040368A retn
CODE:0040368B ; ---------------------------------------------------------------------------
CODE:0040368B
CODE:0040368B loc_40368B: ; CODE XREF: unknown_libname_28+17j
CODE:0040368B pop eax
CODE:0040368C add eax, eax
CODE:0040368E sub eax, ecx
CODE:00403690 mov esi, [edi+eax*2-4]
CODE:00403694 pop edi
CODE:00403695 retn
CODE:00403695 unknown_libname_28 endp
偏移
长度
说明
0x0
2
动态方法数,本例中为1
0x2
2
第一个动态方法的索引序号
0x4
4
第一个动态方法的地址
procedure TForm1.Edit1MouseDown(Sender: TObject; Button: TMouseButton;
Shift: TShiftState; X, Y: Integer);
begin
if Button = mbLeft then
(Sender as TEdit).BeginDrag(False);
end;
procedure TForm1.Memo1DragOver(Sender, Source: TObject; X, Y: Integer;
State: TDragState; var Accept: Boolean);
begin
if (Source is TEdit) then
Accept := True;
end;
procedure TForm1.Memo1DragDrop(Sender, Source: TObject; X, Y: Integer);
begin
if (Sender is TMemo) and (Source is TEdit) then
Memo1.Lines.Add((Source as TEdit).Text);
end;
CODE:0044FCF0 _TForm1_Memo1DragOver proc near ; DATA XREF: CODE:0044FC6Fo
CODE:0044FCF0
CODE:0044FCF0 arg_0 = dword ptr 8
CODE:0044FCF0
CODE:0044FCF0 push ebp
CODE:0044FCF1 mov ebp, esp
CODE:0044FCF3 push ebx
CODE:0044FCF4 mov ebx, ecx
CODE:0044FCF6 mov eax, ebx
CODE:0044FCF8 mov edx, off_425848
CODE:0044FCFE call @System@@IsClass$qqrp14System@TObjectp17System@TMetaClass ; System::__linkproc__ IsClass(System::TObject *,System::TMetaClass *)
CODE:0044FD03 test al, al
CODE:0044FD05 jz short loc_44FD0D
CODE:0044FD07 mov eax, [ebp+arg_0]
CODE:0044FD0A mov byte ptr [eax], 1
CODE:0044FD0D
CODE:0044FD0D loc_44FD0D: ; CODE XREF: _TForm1_Memo1DragOver+15j
CODE:0044FD0D pop ebx
CODE:0044FD0E pop ebp
CODE:0044FD0F retn 10h
CODE:0044FD0F _TForm1_Memo1DragOver endp
CODE:00403628 test eax, eax
CODE:0040362A jz short locret_403642
CODE:0040362C mov ecx, eax
CODE:0040362E
CODE:0040362E loc_40362E: ; CODE XREF: System::__linkproc__ AsClass(System::TObject *,System::TMetaClass *)+11j
CODE:0040362E mov ecx, [ecx]
CODE:00403630 cmp ecx, edx
CODE:00403632 jz short locret_403642
CODE:00403634 mov ecx, [ecx-24h]
CODE:00403637 test ecx, ecx
CODE:00403639 jnz short loc_40362E
CODE:0040363B mov al, 0Ah
CODE:0040363D jmp @System@Error$qqr20System@TRuntimeError ; System::Error(System::TRuntimeError)
CODE:00403642 ; ---------------------------------------------------------------------------
CODE:00403642
CODE:00403642 locret_403642: ; CODE XREF: System::__linkproc__ AsClass(System::TObject *,System::TMetaClass *)+2j
CODE:00403642 ; System::__linkproc__ AsClass(System::TObject *,System::TMetaClass *)+Aj
CODE:00403642 retn
implementation
{$R *.dfm}
type
TClassA = class(TObject)
public
procedure GetName(); virtual;
end;
procedure TClassA.GetName();
begin
ShowMessage(‘我是ClassA‘);
end;
procedure MyGetName(Self: Cardinal);
begin
ShowMessage(‘我才不是什么ClassA‘);
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ClassA: TClassA;
pVMT: Pointer;
dwFlag: Cardinal;
begin
ClassA := TClassA.Create;
ClassA.GetName(); //第一次正常调用
//开始HOOK
pVMT := Pointer(PCardinal(ClassA)^); //得到VMT
VirtualProtect(pVMT, 4, PAGE_READWRITE, dwFlag); //修改VMT的内存属性为可写
PCardinal(pVMT)^ := Cardinal(@MyGetName); //替换
VirtualProtect(pVMT, 4, dwFlag, dwFlag); //还原VMT的内存属性
ClassA.GetName(); //第二次非正常调用
ClassA.Free;
end;