cmu-sei / pharos

Automated static analysis tools for binary programs
Other
1.5k stars 185 forks source link

Look/merge/test issue211_vft_overwrite branch #222

Open sei-eschwartz opened 2 years ago

edmcman commented 2 years ago

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)
    +---
edmcman commented 2 years ago

It seems that we need a way for possibleVFTableWrite to describe vftables that are installed in a virtual base

edmcman commented 2 years ago

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.

sei-eschwartz commented 2 years ago

This is in the thisptr-overhaul branch

sei-eschwartz commented 2 years ago

This branch needs to use thisPtrDefinition from the thisptr-overhaul branch (#224)