|
Package Libs ::
Module immvcglib
|
|
1
2
3 """
4 Reads vcg buffer and creates the graph using Immunity Debugger lib
5
6 (c) Immunity, Inc. 2004-2007
7
8
9 U{Immunity Inc.<http://www.immunityinc.com>}
10
11
12 """
13
14 __VERSION__ = '1.2'
15
16
17 """
18 NOTES:
19 need to divide graph in layers
20 save max layer in graph
21 every set of childs [unique and different part vertex] E a different layer
22 save vertex of layer in each layer
23 mark blank path points in each layer [i preffer path points to dummy vertices]
24
25 for layer in layers:
26 move east and west vertices, depending on their type *
27
28 pathfinder(graph)
29 search empy spots where edge lines might travel
30
31
32 a cool thing might be mark the whole graph as east-slanted or west-slanted, according the graph
33 the n east or n west it will move
34
35 if the graph is slanting too much to east from center point, we can start thinking on going west
36 that can be too fuzzy, but will try to make an aproach for human eye
37
38
39 new lib against old lib:
40 orphan vertices from old lib has been solved, now every vertex has at least 1 relationship saved
41 parent<->child type of vertex are correctly relationed now
42
43 """
44
45 import graphclass
46
47 import immlib
48 import debugger
49
50
51
52
53 from random import randint
54
55
56 PALETTE = []
57
58 PALETTE.append("manhattan_edges: yes\r\n")
59 PALETTE.append("layoutalgorithm: mindepth\r\n")
60 PALETTE.append("finetuning: no\r\n")
61 PALETTE.append("layout_downfactor: 100\r\n")
62 PALETTE.append("layout_upfactor: 0\r\n")
63 PALETTE.append("layout_nearfactor: 0\r\n")
64 PALETTE.append("xlspace: 12\r\n")
65 PALETTE.append("yspace: 30\r\n")
66 PALETTE.append("colorentry 32: 0 0 0\r\n")
67 PALETTE.append("colorentry 33: 0 0 255\r\n")
68 PALETTE.append("colorentry 34: 0 0 255\r\n")
69 PALETTE.append("colorentry 35: 128 128 128\r\n")
70 PALETTE.append("colorentry 36: 128 128 128\r\n")
71 PALETTE.append("colorentry 37: 0 0 128\r\n")
72 PALETTE.append("colorentry 38: 0 0 128\r\n")
73 PALETTE.append("colorentry 39: 0 0 255\r\n")
74 PALETTE.append("colorentry 40: 0 0 255\r\n")
75 PALETTE.append("colorentry 41: 0 0 128\r\n")
76 PALETTE.append("colorentry 42: 0 128 0\r\n")
77 PALETTE.append("colorentry 43: 0 255 0\r\n")
78 PALETTE.append("colorentry 44: 0 128 0\r\n")
79 PALETTE.append("colorentry 45: 255 128 0\r\n")
80 PALETTE.append("colorentry 46: 0 128 0\r\n")
81 PALETTE.append("colorentry 47: 128 128 255\r\n")
82 PALETTE.append("colorentry 48: 255 0 0\r\n")
83 PALETTE.append("colorentry 49: 128 128 0\r\n")
84 PALETTE.append("colorentry 50: 1 1 1\r\n")
85 PALETTE.append("colorentry 51: 192 192 192\r\n")
86 PALETTE.append("colorentry 52: 0 0 255\r\n")
87 PALETTE.append("colorentry 53: 0 0 255\r\n")
88 PALETTE.append("colorentry 54: 0 0 255\r\n")
89 PALETTE.append("colorentry 55: 128 128 128\r\n")
90 PALETTE.append("colorentry 56: 128 128 255\r\n")
91 PALETTE.append("colorentry 57: 0 128 0\r\n")
92 PALETTE.append("colorentry 58: 0 0 128\r\n")
93 PALETTE.append("colorentry 59: 0 0 255\r\n")
94 PALETTE.append("colorentry 60: 128 0 128\r\n")
95 PALETTE.append("colorentry 61: 0 128 0\r\n")
96 PALETTE.append("colorentry 62: 0 128 0\r\n")
97 PALETTE.append("colorentry 63: 0 128 64\r\n")
98 PALETTE.append("colorentry 64: 0 0 128\r\n")
99 PALETTE.append("colorentry 65: 0 0 128\r\n")
100 PALETTE.append("colorentry 66: 255 0 255\r\n")
101 PALETTE.append("colorentry 67: 128 128 0\r\n")
102 PALETTE.append("colorentry 68: 0 0 128\r\n")
103 PALETTE.append("colorentry 69: 0 0 255\r\n")
104 PALETTE.append("colorentry 70: 0 0 128\r\n")
105 PALETTE.append("colorentry 71: 0 0 255\r\n")
106 PALETTE.append("colorentry 72: 0 0 0\r\n")
107 PALETTE.append("colorentry 73: 255 255 255\r\n")
108 PALETTE.append("colorentry 74: 192 192 192\r\n")
109 PALETTE.append("colorentry 75: 0 255 255\r\n")
110 PALETTE.append("colorentry 76: 0 0 0\r\n")
111 PALETTE.append("colorentry 77: 128 0 0\r\n")
112 PALETTE.append("colorentry 78: 128 128 128\r\n")
113 PALETTE.append("colorentry 79: 128 128 0\r\n")
114 PALETTE.append("colorentry 80: 255 0 255\r\n")
115 PALETTE.append("colorentry 81: 0 0 0\r\n")
116 PALETTE.append("colorentry 82: 0 0 255\r\n")
117 PALETTE.append("colorentry 83: 0 0 0\r\n")
118
120
122 """ Init the graphing object """
123 self.imm = imm
124 self.callTree = imm.getCallTree(address)
125 self.address = address
126
128 """ return a call ordered list of nodes """
129
130
131
132
133
134
135
136
137
138 TARGET = []
139 PARENTS = []
140 CHILDREN = []
141
142 for call in self.callTree:
143 if call[3]:
144 if "0x%X"%call[3] not in TARGET:
145 TARGET.append("0x%X"% call[3])
146 if call[4]:
147 if "0x%X"%call[4] not in PARENTS:
148 PARENTS.append("0x%X"% call[4])
149 if call[5]:
150 if "0x%X"%call[5] not in CHILDREN:
151 CHILDREN.append("0x%X"% call[5])
152
153 return TARGET, PARENTS, CHILDREN
154
155 - def makeNode(self, title, content = "", vertical_order = 0):
156 """ build a simple node VCG buf entry """
157 node = []
158 node.append('node: {\r\n')
159 node.append('title: "%s"\r\n'% title)
160 node.append('vertical_order: %d\r\n'% vertical_order)
161 if content != "":
162 node.append('label: "\x0c69%s\x0c31\r\n%s"\r\n'% (title, content))
163 else:
164 node.append('label: "\x0c69%s\x0c31\r\n'% title)
165 node.append('}\r\n')
166 return node
167
168 - def makeEdge(self, source, target, label = "", color = "green"):
169 """ work out the relations between the boxies """
170
171 edge = []
172
173 edge.append('edge: {\r\n')
174 edge.append('sourcename: "%s"\r\n'% source)
175 edge.append('targetname: "%s"\r\n'% target)
176 if label != "":
177 edge.append('label: "%s"\r\n'% label)
178 edge.append('color: %s\r\n'% color)
179 edge.append('}\r\n')
180
181 return edge
182
183 - def makeVCG(self, title, nodes = [], edges = []):
184 """ build a simple node tree VCG buffer """
185 vcg = []
186
187 vcg.append('graph: {\r\n')
188
189 vcg.append('title: "%s"\r\n'% title)
190
191
192 for line in PALETTE:
193 vcg.append(line)
194
195
196 for node in nodes:
197 for line in node:
198 vcg.append(line)
199
200
201 for edge in edges:
202 for line in edge:
203 vcg.append(line)
204
205
206 vcg.append('}\r\n')
207
208 return vcg
209
211 """ pop up a call tree graph for this address """
212 TARGET, PARENTS, CHILDREN = self.orderNodesFromTree()
213
214 nodes = []
215 unique = []
216
217 for title in TARGET+PARENTS+CHILDREN:
218 if title not in unique:
219 unique.append(title)
220
221
222 for title in unique:
223
224 if title in PARENTS:
225 order = 0
226 if title in TARGET:
227 order = 1
228 if title in CHILDREN:
229 order = 2
230
231
232 node_content = self.imm.decodeAddress(int(title, 16))
233 nodes.append(self.makeNode(title, content = node_content, vertical_order = order))
234
235 edges = []
236
237 target = TARGET[0]
238
239 for parent in PARENTS:
240
241 edges.append(self.makeEdge(parent, target))
242 for child in CHILDREN:
243 edges.append(self.makeEdge(target, child))
244
245
246 vcg = self.makeVCG("Call Graph <-for-> %s [0x%X]"% (self.imm.decodeAddress(self.address), self.address), nodes, edges)
247
248
249 fd = open("CALLTREE.vcg", "w")
250 for line in vcg:
251 fd.write(line)
252 fd.close()
253
254
255 generateGraphFromBuf(vcg)
256
258 """ recursive VCG parser """
259
261 """ pre-process our shiznit """
262 self.sep = '!SEP!'
263 self.DEBUG = False
264
265
266
267
268
269 self.MODETOKENS = [ 'graph:', 'node:', 'edge:' ]
270
271 self.VARTOKENS = [ 'title:', 'label:', 'vertical_order:', 'horizontal_order:', 'manhattan_edges:', 'layoutalgorithm:' ]
272 self.VARTOKENS += [ 'finetuning:', 'layout_downfactor:', 'layout_upfactor:' ]
273 self.VARTOKENS += [ 'layout_nearfactor:', 'xlspace:', 'yspace:' ]
274 self.VARTOKENS += [ 'sourcename:', 'targetname:', 'color:' ]
275
276
277 cleanVCG = []
278
279 sMode = False
280
281 for line in vcgList:
282
283
284 if line[:2] == "//":
285 continue
286
287 clean = []
288 lineList = list(line)
289
290 for c in lineList:
291 if c == '"':
292
293 sMode = not sMode
294
295 if sMode == True:
296 clean.append(c)
297 else:
298 if c in ['\r']:
299 continue
300 if c in ['\n', ' ']:
301 clean.append(self.sep)
302 else:
303 clean.append(c)
304
305 line = ''.join(clean)
306
307 if len(line):
308 cleanVCG.append(line)
309
310 self.vcgText = ''.join(cleanVCG)
311
312 self.nodeList = []
313 self.edgeList = []
314 self.graphList = []
315
316 self.lastMode = ""
317
319 """ raise an error exception """
320 raise error
321
322 - def reParse(self, vcgItems, mode = ""):
323 """ used for recursive parse """
324
325
326 if self.DEBUG:
327 logger = immlib.Debugger()
328 logger.Log(repr(vcgItems))
329
330
331 if vcgItems:
332
333 if vcgItems[0] in self.MODETOKENS:
334 mode = vcgItems[0]
335 self.lastMode = mode
336 self.reParse(vcgItems[1:], mode = mode)
337
338 elif vcgItems[0] in self.VARTOKENS or 'colorentry' in vcgItems[0]:
339
340
341 if 'colorentry' in vcgItems[0]:
342 vcgItems[0] = " ".join([vcgItems[0], vcgItems[1]])
343 del vcgItems[1]
344
345 args = []
346 key = vcgItems[0]
347
348 i = 1
349 while vcgItems[i] not in self.VARTOKENS and vcgItems[i] not in self.MODETOKENS and 'colorentry' not in vcgItems[i]:
350 if '}' in vcgItems[i]:
351 break
352 args.append(vcgItems[i])
353 i += 1
354
355 if mode == 'node:' and len(self.nodeList):
356 self.nodeList[len(self.nodeList)-1][key] = " ".join(args)
357
358 if mode == 'edge:' and len(self.edgeList):
359 self.edgeList[len(self.edgeList)-1][key] = " ".join(args)
360
361 if mode == 'graph:' and len(self.graphList):
362 self.graphList[len(self.graphList)-1][key] = " ".join(args)
363
364 self.reParse(vcgItems[i:], mode = self.lastMode)
365
366 elif '{' in vcgItems[0]:
367
368
369 if mode == 'graph:':
370 self.graphList.append({})
371 elif mode == 'node:':
372 self.nodeList.append({})
373 elif mode == 'edge:':
374 self.edgeList.append({})
375
376 self.reParse(vcgItems[1:], mode = mode)
377
378
379 elif '}' in vcgItems[0]:
380 self.reParse(vcgItems[1:], mode = '')
381
382
383 return self.graphList, self.nodeList, self.edgeList
384
386 """ Parse a VCG graph .. not 100% proper .. but proper enough """
387 vcgItems = self.vcgText.split(self.sep)
388 return self.reParse(vcgItems)
389
391 """ test our new VCG parsing logic """
392 vcgList = []
393
394 fd = open(path, 'r')
395 for line in fd:
396 vcgList.append(line)
397 fd.close()
398
399 parser = ParseVCGList(vcgList)
400
401
402 graph, nodes, edges = parser.parseGraph()
403
404 logger = immlib.Debugger()
405
406 logger.Log("GRAPH:")
407 for gDict in graph:
408 for key in gDict:
409 logger.Log("KeyVal: %s"% key)
410 logger.Log(repr(gDict[key]))
411 logger.Log("EDGES:")
412 for eDict in edges:
413 for key in eDict:
414 logger.Log("KeyVal: %s"% key)
415 logger.Log(repr(eDict[key]))
416 logger.Log("NODES:")
417 for nDict in nodes:
418 for key in nDict:
419 logger.Log("KeyVal: %s"% key)
420 logger<