forked from kweatherman/IDA_ClassInformer_PlugIn
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathVftable.cpp
More file actions
107 lines (93 loc) · 3.64 KB
/
Vftable.cpp
File metadata and controls
107 lines (93 loc) · 3.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
// Virtual function table parsing support
#include "stdafx.h"
#include "Main.h"
#include "Vftable.h"
#include "RTTI.h"
// Attempt to get information of and fix vftable at address.
// Return TRUE along with info if valid vftable parsed at address
BOOL vftable::getTableInfo(ea_t ea, vtinfo &info)
{
// Start of a vft should have an xref and a name (auto, or user, etc).
// Ideal flags 32bit: FF_DWRD, FF_0OFF, FF_REF, FF_NAME, FF_DATA, FF_IVL
//dumpFlags(ea);
flags_t flags = get_flags(ea);
if(has_xref(flags) && has_any_name(flags) && (plat.isEa(flags) || is_unknown(flags)))
{
ZeroMemory(&info, sizeof(info));
// Get raw (auto-generated mangled, or user named) vft name
//if (!get_name(BADADDR, ea, info.name, SIZESTR(info.name)))
// msg("%llX ** vftable::getTableInfo(): failed to get raw name!\n", ea);
// Attempt to determine the vft's method count
ea_t start = info.start = ea;
while (TRUE)
{
// Should be an pointer sized offset to a function here (could be unknown if dirty IDB)
// Ideal flags for 32bit: FF_DWRD, FF_0OFF, FF_REF, FF_NAME, FF_DATA, FF_IVL
//dumpFlags(ea);
flags_t indexFlags = get_flags(ea);
if (!(plat.isEa(indexFlags) || is_unknown(indexFlags)))
{
//msg(" ******* 1\n");
break;
}
// Look at what this (assumed vftable index) points too
ea_t memberPtr = plat.getEa(ea);
if (!(memberPtr && (memberPtr != BADADDR)))
{
// vft's some times have a trailing zero pointer (alignment, or?), fix it
if (memberPtr == 0)
fixEa(ea);
//msg(" ******* 2\n");
break;
}
// Should see code for a good vft method here, but it could be dirty
flags_t flags = get_flags(memberPtr);
if (!(is_code(flags) || is_unknown(flags)))
{
// Edge cases where IDA has unresolved bytes
// 2nd chance if points to a code segment
const SEGMENT *methodSeg = FindCachedSegment(memberPtr);
if (methodSeg && (methodSeg->type & _CODE_SEG))
{
#pragma message(__LOC2__ " >> Catch this 2nd chance fix case")
_ASSERT(FALSE);
//msg(" ******* 3\n");
//break;
}
else
{
//msg(" ******* 3.5\n");
break;
}
}
if (ea != start)
{
// If we see a ref after first index it's probably the beginning of the next vft or something else
if (has_xref(indexFlags))
{
//msg(" ******* 4\n");
break;
}
// If we see a COL here it must be the start of another vftable
if (RTTI::_RTTICompleteObjectLocator::isValid(memberPtr))
{
//msg(" ******* 5\n");
break;
}
}
// As needed fix ea_t pointer, and, or, missing code and function def here
fixEa(ea);
fixFunction(memberPtr);
ea += (ea_t) plat.ptrSize;
};
// Reached the presumed end of it
if ((info.methodCount = ((ea - start) / plat.ptrSize)) > 0)
{
info.end = ea;
//msg(" vftable: %llX-%llX, methods: %d\n", rtInfo.eaStart, rtInfo.eaEnd, rtInfo.uMethods);
return TRUE;
}
}
//dumpFlags(ea);
return FALSE;
}