VB6 VTable LayoutAuthor: David Zimmer Date: 09.26.22 - 10:06pm to see the vtable layout of a vb6 COM object compile a native exe with debug symbols, in form load do something like Dim c As New Class1 InputBox "", "", Hex(ObjPtr(c)) Endattach ollydbg, in the bottom dump window right click view Long - as address then ctrl-g to go to the address copied from the inputbox. for me it was 4EB260 offset value @ address symbols resolved as ------------------------------------------------------- 004EB260 00403354 OFFSET Project1.___vba@07F1B854 004EB264 00000000 (class based variables can be stored in memory below here)follow that pointer to get to the vtable 00403354 6F2A306E MSVBVM60.BASIC_CLASS_QueryInterface 00403358 6F2A2F45 MSVBVM60.Zombie_AddRef 0040335C 6F2A2D18 MSVBVM60.Zombie_Release 00403360 6F352FE1 MSVBVM60.BASIC_DISPINTERFACE_GetTICount 00403364 6F2E3ADC MSVBVM60.BASIC_DISPINTERFACE_GetTypeInfo 00403368 6F2AF26C MSVBVM60.BASIC_CLASS_GetIDsOfNames 0040336C 6F2AF141 MSVBVM60.BASIC_CLASS_Invoke 00403370 00401484 Project1.00401484 ;first user function on class (+0x1c) 00403374 00000000 00403378 00000000403370 holds a pointer to code offset instruction byte dump disassembly -------------------------------------------------------- 00401484 . E9 A7090000 JMP Project1.Class1::x (resolves to 0x401E30 could patch to hook here..)actual function body 00401E30 55 PUSH EBP 00401E31 . 8BEC MOV EBP,ESP 00401E33 . 83EC 0C SUB ESP,0C 00401E36 . 68 F6104000 PUSH Project1.___vbaExceptHandler ...For a form the vtable is different such as: Public a As Long Private Sub Form_Load() a = &H11223344 InputBox "", "", Hex(ObjPtr(Me)) End End Sub Function x(a) DoEvents End FunctionObjPtr(form) $ ==> >004032E4 OFFSET Project1.___vba@0763FC74 $+4 >00000000 $+8 >00689784 $+C >02C0CA34 $+10 >02C0C9BC $+14 >00000000 $+18 >00000000 $+1C >6F2BAE80 MSVBVM60.6F2BAE80 $+20 >00000007 $+24 >00000001 $+28 >00000000 $+2C >0000100F $+30 >00000000 $+34 >11223344 <-- variable a Code: $4032E4 6F2A306E MSVBVM60.BASIC_CLASS_QueryInterface $+4 >6F2A2F45 MSVBVM60.Zombie_AddRef $+8 >6F2A2D18 MSVBVM60.Zombie_Release $+C >6F352FE1 MSVBVM60.BASIC_DISPINTERFACE_GetTICount $+10 >6F2E3ADC MSVBVM60.BASIC_DISPINTERFACE_GetTypeInfo $+14 >6F2AF26C MSVBVM60.BASIC_CLASS_GetIDsOfNames $+18 >6F2AF141 MSVBVM60.BASIC_CLASS_Invoke $+1C >6F3A6C14 MSVBVM60.6F3A6C14 ... $+6F8 >00401508 Project1.095D7F30 \__ get / let for public a as long $+6FC >00401517 Project1.00401517 / $+700 >0040153B Project1.0040153B ; 0040153B . E9 40070000 JMP Project1.Form1::x $+704 >0040152E Project1.0040152E ; 0040152E . E9 4D050000 JMP Project1.Form1::Form_Load $+708 >00000000 $+70C >00000000so vtable changes based on what kind of object it is with housekeeping stuff. (form vrs class) and what public variables you have plus methods implemented. If you have a private variable in a form or class, and set its value in native code, the compiler will generate this: 0040199B |. C746 34 443322>MOV DWORD PTR DS:[ESI+34],11223344Where esi is the this pointer and local instance variables are stored at this+x with first slot being +34 If you instead declare the variable as Public a As Long a = &H11223344You get the same thing in asm..However if you do Public a As Long me.a = &H11223344Now COM comes into play and you get this.. 00401A1B |. 8B16 MOV EDX,DWORD PTR DS:[ESI] 00401A1D |. 68 44332211 PUSH 11223344 00401A22 |. 56 PUSH ESI 00401A23 |. FF92 FC060000 CALL DWORD PTR DS:[EDX+6FC] ;in a form so huge default vtable 0040149F . 814424 04 3400>ADD DWORD PTR SS:[ESP+4],34 ;offset of instance var this+34 as above.. 004014A7 . B9 60114000 MOV ECX,And the abbreviated vtable for the form $ ==> >6F23306E MSVBVM60.BASIC_CLASS_QueryInterface $+4 >6F232F45 MSVBVM60.Zombie_AddRef $+8 >6F232D18 MSVBVM60.Zombie_Release $+C >6F2E2FE1 MSVBVM60.BASIC_DISPINTERFACE_GetTICount $+10 >6F273ADC MSVBVM60.BASIC_DISPINTERFACE_GetTypeInfo $+14 >6F23F26C MSVBVM60.BASIC_CLASS_GetIDsOfNames $+18 >6F23F141 MSVBVM60.BASIC_CLASS_Invoke $+1C >6F336C14 MSVBVM60.6F336C14 ... $+6F8 >00401490 Project1.00401490 ;get a using GetMem4 $+6FC >0040149F Project1.0040149F ;let a using PutMem4 $+700 >004014B6 Project1.004014B6 ;form_load $+704 >00000000And just to clarify objptr(me) $ ==> >004022F0 Project1.004022F0 ;points to vtable $+4 >00000000 $+8 >005B5B0C ;points to $+1C $+C >0227C9EC -> 66068960 MSVBVM60.??_7CUnkDesk@@6B@ $+10 >0227C974 -> 0224C170 -> obj3 $+14 >00000000 $+18 >00000000 $+1C >660682E0 MSVBVM60.??_7PRIVATE_UNKNOWN@BASIC_CLASS@@6B@ $+20 >00000006 ; com obj reference count (AddRef@CEnumConPnts) $+24 >00000001 $+28 >00000000 $+2C >0000100F $+30 >00000000 $+34 >00000000 ;first user variable data slot 660682E0 >66007ED0 MSVBVM60.?QueryInterface@PRIVATE_UNKNOWN@BASIC_CLASS@@UAGJABU_GUID@@PAPAX@Z $+4 >66001B4B MSVBVM60.?AddRef@CEnumConPnts@@UAGKXZ $+8 >66002F60 MSVBVM60.?Release@PRIVATE_UNKNOWN@BASIC_CLASS@@UAGKXZ $+C >660E2930 MSVBVM60.?GetClassInfoA@PRIVATE_UNKNOWN@BASIC_CLASS@@UAGJPAPAUITypeInfo@@@ZSo the objptr is a data block that actually contains pointers to several COM interfaces, along with the reference count and then local class variables, each stored per instance. The vtable itself is stored independently of the instance data makes sense. Comments: (0) |
About Me More Blogs Main Site
|
||||||||||||||||||||||||||