Repository navigation
Expand file tree
/
Copy pathmsvc.py
More file actions
164 lines (149 loc) · 7.46 KB
/
Copy pathmsvc.py
File metadata and controls
164 lines (149 loc) · 7.46 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
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
from idaapi import BADADDR, FF_DATA, FF_DWRD, FF_0OFF, get_struc_size, FF_ASCI, do_unknown_range, DOUNK_DELNAMES, doStruct, get_member_by_name, get_32bit, get_ascii_contents, demangle_name, doDwrd, op_offset
from idc import *
from ida_struct import get_struc_id, del_struc, get_struc, add_struc, add_struc_member
from utils import utils
u = utils()
classes = {}
vtables = {}
class RTTIStruc:
tid = 0
struc = 0
size = 0
def strip(name):
if name.startswith("class ") and name.endswith("`RTTI Type Descriptor'"):
return name[6:-23]
elif name.startswith("struct ") and name.endswith("`RTTI Type Descriptor'"):
return name[7:-23]
else:
return name
class RTTICompleteObjectLocator(RTTIStruc):
# Init class statics
msid = get_struc_id("RTTICompleteObjectLocator")
if msid != BADADDR:
del_struc(get_struc(msid))
msid = add_struc(0xFFFFFFFF, "RTTICompleteObjectLocator", False)
add_struc_member(get_struc(msid), "signature", BADADDR, FF_DATA|FF_DWRD, None, 4)
add_struc_member(get_struc(msid), "offset", BADADDR, FF_DATA|FF_DWRD, None, 4)
add_struc_member(get_struc(msid), "cdOffset", BADADDR, FF_DATA|FF_DWRD, None, 4)
add_struc_member(get_struc(msid), "pTypeDescriptor", BADADDR, FF_DATA|FF_DWRD|FF_0OFF, u.mt_rva(), 4)
add_struc_member(get_struc(msid), "pClassDescriptor", BADADDR, FF_DATA|FF_DWRD|FF_0OFF, u.mt_rva(), 4)
if u.x64:
add_struc_member(get_struc(msid), "pSelf", BADADDR, FF_DATA|FF_DWRD|FF_0OFF, u.mt_rva(), 4)
tid = msid
struc = get_struc(tid)
size = get_struc_size(tid)
print "Completed Registering RTTICompleteObjectLocator"
def __init__(self, ea, vtable):
do_unknown_range(ea, self.size, DOUNK_DELNAMES)
if doStruct(ea, self.size, self.tid):
# Get adress of type descriptor from CompleteLocator
print "Complete Object Locator at: 0x%x" % ea
offset = get_member_by_name(self.struc, "pTypeDescriptor").soff
typeDescriptor = get_32bit(ea+offset) + u.x64_imagebase()
print "Looking for type Descriptor at: 0x%x" % typeDescriptor
rtd = RTTITypeDescriptor(typeDescriptor)
if rtd.class_name:
print "Type Descriptor at: 0x%x" % typeDescriptor
offset = get_member_by_name(self.struc, "pClassDescriptor").soff
classHierarchyDes = get_32bit(ea+offset) + u.x64_imagebase()
rchd = RTTIClassHierarchyDescriptor(classHierarchyDes)
# filter out None entries
rchd.bases = filter(lambda x: x, rchd.bases)
className = strip(rtd.class_name)
classes[className] = [strip(b) for b in rchd.bases]
vtables[className] = vtable
MakeNameEx(vtable, "vtable__" + className, SN_NOWARN)
else:
# if the RTTITypeDescriptor doesn't have a valid name for us to
# read, then this wasn't a valid RTTICompleteObjectLocator
MakeUnknown(ea, self.size, DOUNK_SIMPLE)
class RTTITypeDescriptor(RTTIStruc):
class_name = None
msid = get_struc_id("RTTITypeDescriptor")
if msid != BADADDR:
del_struc(get_struc(msid))
msid = add_struc(0xFFFFFFFF, "RTTITypeDescriptor", False)
add_struc_member(get_struc(msid), "pVFTable", BADADDR, FF_DATA|u.PTR_TYPE|FF_0OFF, u.mt_address(), u.PTR_SIZE)
add_struc_member(get_struc(msid), "spare", BADADDR, FF_DATA|u.PTR_TYPE, None, u.PTR_SIZE)
add_struc_member(get_struc(msid), "name", BADADDR, FF_DATA|FF_ASCI, u.mt_ascii(), 0)
tid = msid
struc = get_struc(tid)
size = get_struc_size(tid)
print "Completed Registering RTTITypeDescriptor"
def __init__(self, ea):
name = ea + get_member_by_name(get_struc(self.tid), "name").soff
strlen = u.get_strlen(name)
if strlen is None:
# not a real vtable
return
self.size = self.size + strlen
mangled = get_ascii_contents(name, strlen, 0)
if mangled is None:
# not a real function name
return
print "Mangled: " + mangled
demangled = demangle_name('??_R0' + mangled[1:] , 0)
if demangled:
do_unknown_range(ea, self.size, DOUNK_DELNAMES)
if doStruct(ea, self.size, self.tid):
print " Made td at 0x%x: %s" % (ea, demangled)
self.class_name = demangled
return
print " FAIL :("
return
class RTTIClassHierarchyDescriptor(RTTIStruc):
bases = None
msid = get_struc_id("RTTIClassHierarchyDescriptor")
if msid != BADADDR:
del_struc(get_struc(msid))
msid = add_struc(0xFFFFFFFF, "RTTIClassHierarchyDescriptor", False)
add_struc_member(get_struc(msid), "signature", BADADDR, FF_DWRD|FF_DATA, None, 4)
add_struc_member(get_struc(msid), "attribute", BADADDR, FF_DWRD|FF_DATA, None, 4)
add_struc_member(get_struc(msid), "numBaseClasses", BADADDR, FF_DWRD|FF_DATA, None, 4)
add_struc_member(get_struc(msid), "pBaseClassArray", BADADDR, FF_DATA|FF_DWRD|FF_0OFF, u.mt_rva(), 4)
tid = msid
struc = get_struc(tid)
print "Completed Registering RTTIClassHierarchyDescriptor"
def __init__(self, ea):
print "Processing Class Hierarchy Descriptor at 0x%x" % ea
do_unknown_range(ea, get_struc_size(self.tid), DOUNK_DELNAMES)
if doStruct(ea, get_struc_size(self.tid), self.tid):
baseClasses = get_32bit(ea+get_member_by_name(get_struc(self.tid), "pBaseClassArray").soff) + u.x64_imagebase()
nb_classes = get_32bit(ea+get_member_by_name(get_struc(self.tid), "numBaseClasses").soff)
print "Baseclasses array at 0x%x" % baseClasses
# Skip the first base class as it is itself (could check)
self.bases = []
for i in range(1, nb_classes):
baseClass = get_32bit(baseClasses+i*4) + u.x64_imagebase()
print "base class 0x%x" % baseClass
doDwrd(baseClasses+i*4, 4)
op_offset(baseClasses+i*4, -1, u.REF_OFF|REFINFO_RVA, -1, 0, 0)
doStruct(baseClass, RTTIBaseClassDescriptor.size, RTTIBaseClassDescriptor.tid)
typeDescriptor = get_32bit(baseClass) + u.x64_imagebase()
self.bases.append(RTTITypeDescriptor(typeDescriptor).class_name)
class RTTIBaseClassDescriptor(RTTIStruc):
msid = get_struc_id("RTTIBaseClassDescriptor")
if msid != BADADDR:
del_struc(get_struc(msid))
msid = add_struc(0xFFFFFFFF, "RTTIBaseClassDescriptor", False)
add_struc_member(get_struc(msid), "pTypeDescriptor", BADADDR, FF_DATA|FF_DWRD|FF_0OFF, u.mt_rva(), 4)
add_struc_member(get_struc(msid), "numContainerBases", BADADDR, FF_DWRD|FF_DATA, None, 4)
add_struc_member(get_struc(msid), "PMD", BADADDR, FF_DATA|FF_DWRD|FF_0OFF, u.mt_rva(), 4)
add_struc_member(get_struc(msid), "attributes", BADADDR, FF_DWRD|FF_DATA, None, 4)
tid = msid
struc = get_struc(tid)
size = get_struc_size(tid)
print "Completed Registering RTTIBaseClassDescriptor"
def run_msvc():
start = u.rdata.startEA
end = u.rdata.endEA
rdata_size = end-start
for offset in xrange(0, rdata_size-u.PTR_SIZE, u.PTR_SIZE):
vtable = start+offset
if u.isVtable(vtable):
print "vtable at : " + hex(vtable)[:-1]
col = u.get_ptr(vtable-u.PTR_SIZE)
if u.within(col, u.valid_ranges):
rcol = RTTICompleteObjectLocator(col, vtable)
u.add_missing_classes(classes)
return classes, vtables