The previous article introduced GCC to the member function pointer to do the thunk processing, this article introduces the VC to member function pointer how to handle, also has the dynamic binding related processing.
The same example is used to return the previous article:
structPoint {floatx, y;};structobj{Virtual~obj {}voidFooint) {} voidFoo (point) {}Virtual voidVfoo () {}};structObjobj: Publicobj{Virtual~Objobj {}Virtual voidVfoo () {}};voidMain () {obj o; Objobj Oo; //void* POFP = (void*) (void (obj::*) (point)) &obj::foo; //error C2440: "Type conversion": Cannot convert from "void (__cdecl obj::*) (point)" to "void *" void(obj::* pi) (int) = &Obj::foo; void(obj::* pp) (point) = &Obj::foo; void(Objobj: VP:*) () = &Objobj::vfoo; NOOP ((&oo)->*VP) (); NOOP ((&oo)->*pi) (1); NOOP ((&o)->*PP) (PT);}
The member function pointer definition and the code that is called, the corresponding disassembly:
00000001' 3f461159 488d05e6feffffLearax,[Test! ilt+ $(? fooobjqeaaxhz) (00000001' 3f461046)]00000001' 3f461160 48898424d8000000movQword ptr [Rsp+0d8h],rax;void (obj::* pi) (int) = &obj::foo;00000001' 3f461168 488d05b4feffffLearax,[Test! ilt+ -(? fooobjqeaaxupointz) (00000001' 3f461023)]00000001' 3f46116f 48898424e0000000movQword ptr [Rsp+0e0h],rax;void (obj::* pp) (point) = &obj::foo;00000001' 3f461177 488d05b9feffffLearax,[Test! ilt+ -(?? _9OBJOBJ$B7AA) (00000001' 3f461037)]00000001' 3f46117e 48898424e8000000movQword ptr [Rsp+0e8h],rax;void (objobj::* vp) = &objobj::vfoo;00000001' 3f461186 488d8c2498000000Learcx,[rsp+98h]00000001' 3f46118e ff9424e8000000PagerQword ptr [rsp+0e8h];( (&oo)->*VP) (); test! Ilt+50 (?? _9OBJOBJ$B7AA) (00000001 ' 3f461037)00000001' 3f461195 ba01000000movEdX100000001' 3f46119a 488d8c2498000000Learcx,[rsp+98h]00000001' 3f4611a2 ff9424d8000000PagerQword ptr [rsp+0d8h];( (&oo)->*pi) (1); test! Ilt+65 (fooobjqeaaxhz) (00000001 ' 3f461046)
There are three pointers assigned to the address, and the respective information is as follows:
Test! ilt+ $(? fooobjqeaaxhz):00000001' 3f461046 e955020000jmp Test!obj:: Foo (00000001' 3f4612a0)0: the> dt00000001' 3f4612a0obj:: foo voidTest!obj:: foo+0( int)Test! ilt+ -(? fooobjqeaaxupointz):00000001' 3f461023 e9a8020000jmp Test!obj:: Foo (00000001' 3f4612d0)0: the> dt00000001' 3f4612d0obj:: foo voidTest!obj:: foo+0(point)Test! ilt+ -(?? _9OBJOBJ$B7AA):00000001' 3f461037 e964050000jmp Test!Objobj:: ' Vcall'{8}'(00000001' 3f4615a0)0: the> dt00000001' 3f4615a0Objobj:: ' Vcall'{8}'Symbol notfound.0: the> U00000001' 3f4615a0 L3Test!Objobj:: ' Vcall'{8}':00000001' 3f4615a0 488b01movRax,qword ptr [RCX]00000001' 3f4615a3 ff6008jmpQword ptr [rax+8];+- jmp test!objobj::vfoo
Functions are called by an indirect jump, which is the basis of the hook, born with the M attribute, this is not the subject of this article. Ignoring this indirect jump (or as a short-circuit), we think that the non-virtual member function pointer directly points to the member function body, but the virtual function pointer points to a small block of thunk-like processing code. Virtual functions are dynamically bound, and thunk related processing is necessary. VC compiler in the case can correctly parse out the binding, this section of thunk processing inline to the call.
Where to use thunk in the SDK are also, Atlthunk.h, Olecall_.s, Oledisp1.cpp, Qithunk.s, Stdcallthunk.s. Most of the places that use thunk are related to COM and have different purposes. For example, QITHUNK.S is QueryInterface Thunk, which is used to debug COM, with an ulterior motive to imitate IUnknown call virtual function of the process, so that the COM method is called before all must go through qithunk virtual function, This can be interrupted without knowing which specific COM is being executed. When you do not know the debug information of COM, you can also break into every method entry of COM. Qithunk is in this I think it is easier to analyze, as long as the understanding of the Iuknown interface and virtual function table can be analyzed.
And as IDispatch is an interface for dynamic binding, both VBScript and the objects used in JScript implement this interface. When a property or method of an object is called in a script, the execution function of COM is bound by a property name or method name. In this way, the message calls to OBJC are somewhat similar in form. Window.getelementbyid ("form"), the call is Window.invoke (GetDispID ("getElementById"), ..., args ("form"),...); In OBJC [window getElementById: "Form"], the call is objc_sendmsg (window, "getElementById:", "form");
This article briefly mentions the thunk and the dynamic binding, after having the perceptual knowledge, the analysis OBJC in the SEL dynamic binding will not be too unfamiliar. Analyze OBJC's articles also please pay attention in the coming days.
member function pointers, dynamic binding (VC platform)