pharos
pharos copied to clipboard
Look/merge/test issue211_vft_overwrite branch
This branch apparently has some problems for virtual bases. Basically, when we install a vftable to a virtual base, the thisptr will not match ecx:
funcParameter(0x0040247E void __thiscall std::basic_char_ostream::`vbase destructor(void), ecx, sv_12907835979890934072).
possibleVFTableWrite(0x402487, 0x0040247E void __thiscall std::basic_char_ostream::`vbase destructor(void), sv_13877673463206809612, 0, 0x0041238C const std::basic_char_ostream::`vftable').
possibleVFTableWrite(0x402490, 0x0040247E void __thiscall std::basic_char_ostream::`vbase destructor(void), sv_12907835979890934072, 0x8, 0x00412384 const std::ios_base::`vftable').
sub_40247E proc near
lea eax, [ecx+8] ; eax = & std::ios::base::vftable
mov ecx, [eax-8] ; ecx = &std::basic_char_ostream::vbtable
mov ecx, [ecx+4] ; ecx = second entry of vbtable, offset to ios_base
mov dword ptr [ecx+eax-8], offset ??_7?$basic_ostream@DU?$char_traits@D@std@@@std@@6B@ ; const std::ostream::`vftable'
push eax ; struct std::ios_base *
mov dword ptr [eax], offset ??_7ios_base@std@@6B@ ; const std::ios_base::`vftable'
call ?_Ios_base_dtor@ios_base@std@@CAXPAV12@@Z ; std::ios_base::_Ios_base_dtor(std::ios_base *)
pop ecx
retn
sub_40247E endp
class std::basic_ostream<char,struct std::char_traits<char> > size(80):
+---
0 | {vbptr}
+---
4 | (vtordisp for vbase std::basic_ios<char,struct std::char_traits<char> >)
+--- (virtual base std::basic_ios<char,struct std::char_traits<char> >)
8 | +--- (base class std::ios_base)
8 | | {vfptr}
16 | | +--- (base class std::_Iosb<int>)
| | +---
16 | | _Stdstr
20 | | _Mystate
24 | | _Except
28 | | _Fmtfl
32 | | _Prec
40 | | _Wide
48 | | _Arr
52 | | _Calls
56 | | _Ploc
| | <alignment member> (size=4)
| +---
64 | _Mystrbuf
68 | _Tiestr
72 | _Fillch
| <alignment member> (size=7)
+---
It seems that we need a way for possibleVFTableWrite
to describe vftables that are installed in a virtual base
I am sure I'll forget my progress by the time I get back from vacation, so I'll add some notes here. I added a new fact type, thisPtrDefinition, which expresses pointers as expressions.
Here is an example:
[eschwartz@pd4 Lite]$ cat oo.facts | fgrep sv_3544081266679891044
possibleVFTableWrite(0x402487, 0x40247e, sv_18024155638382103558, 0, sv_3544081266679891044, 0x41238c).
thisPtrDefinition(sv_3544081266679891044, add([read([sv(sv_2925039723046125976, 'Mem'), add([read([sv(sv_2925039723046125976, 'Mem'), sv(sv_10664833297080542982, ecx_0)]), 0x4])]), sv(sv_10664833297080542982, ecx_0)]), 0x402487, 0x40247e).
I added a hash for the "full" or "expanded" thisptr to possibleVFTableWrite, which is sv_3544081266679891044 here. Then we can see the definition of sv_3544081266679891044, which must be describing a virtual base. Notice that the "old" fact information of sv_18024155638382103558 and offset 0 is laughably wrong.
So how do we use this on the vft_overwrite branch? Perhaps by verifying that the address is an offset from ecx at some point.
This is in the thisptr-overhaul branch
This branch needs to use thisPtrDefinition from the thisptr-overhaul branch (#224)