Module bytecode
[hide private]
[frames] | no frames]

Source Code for Module bytecode

  1  # This file is part of Androguard. 
  2  # 
  3  # Copyright (C) 2010, Anthony Desnos <desnos at t0t0.org> 
  4  # All rights reserved. 
  5  # 
  6  # Androguard is free software: you can redistribute it and/or modify 
  7  # it under the terms of the GNU Lesser General Public License as published by 
  8  # the Free Software Foundation, either version 3 of the License, or 
  9  # (at your option) any later version. 
 10  # 
 11  # Androguard is distributed in the hope that it will be useful, 
 12  # but WITHOUT ANY WARRANTY; without even the implied warranty of 
 13  # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 14  # GNU Lesser General Public License for more details. 
 15  # 
 16  # You should have received a copy of the GNU Lesser General Public License 
 17  # along with Androguard.  If not, see <http://www.gnu.org/licenses/>. 
 18   
 19  from struct import unpack, pack 
 20   
 21  from misc import Color 
 22  from error import warning, error 
 23   
 24  global PRETTY_SHOW 
 25  PRETTY_SHOW = 0 
 26   
 27  # Handle exit message 
28 -def Exit( msg ):
29 warning("Error : " + msg) 30 raise("oops")
31 32 # Print arg into a correct format
33 -def _Print(name, arg) :
34 buff = name + " " 35 36 if type(arg).__name__ == 'int' : 37 buff += "0x%x" % arg 38 elif type(arg).__name__ == 'long' : 39 buff += "0x%x" % arg 40 elif type(arg).__name__ == 'str' : 41 buff += "%s" % arg 42 elif isinstance(arg, SV) : 43 buff += "0x%x" % arg.get_value() 44 elif isinstance(arg, SVs) : 45 buff += arg.get_value().__str__() 46 47 print buff
48
49 -def set_pretty_show( val ) :
50 global PRETTY_SHOW 51 PRETTY_SHOW = val
52
53 -def PrettyShow( basic_blocks ) :
54 if PRETTY_SHOW == 0 : 55 PrettyShow0( basic_blocks ) 56 elif PRETTY_SHOW == 1 : 57 PrettyShow1( basic_blocks ) 58 elif PRETTY_SHOW == 2 : 59 PrettyShow1bis( basic_blocks )
60
61 -def PrettyShow0( basic_blocks ) :
62 paths = [] 63 for i in basic_blocks : 64 val = 0 65 if len(i.childs) > 1 : 66 val = 1 67 elif len(i.childs) == 1 : 68 val = 2 69 70 for j in i.childs : 71 paths.append( ( j[0], j[1], val ) ) 72 if val == 1 : 73 val = 0 74 75 nb = 0 76 idx = 0 77 for bb in basic_blocks : 78 for ins in bb.ins : 79 p = [] 80 for j in paths : 81 way = Color.green 82 if j[2] == 1 : 83 way = Color.red 84 elif j[2] == 2 : 85 way = Color.blue 86 87 m_in = j[0] 88 m_ax = j[1] 89 if j[0] > j[1] : 90 m_in = j[1] 91 m_ax = j[0] 92 93 if idx >= m_in and idx <= m_ax : 94 if idx == j[0] : 95 p.append( j[1] ) 96 print "o", 97 if idx == j[1] : 98 print "%s>%s" % (way, Color.normal), 99 100 if idx != j[0] and idx != j[1] : 101 print "%s|%s" % (way, Color.normal), 102 else : 103 print " ", 104 105 print "%s%d%s(%s%x%s)" % (Color.yellow, nb, Color.normal, Color.yellow, idx, Color.normal), 106 ins.show( idx ) 107 108 if p != [] : 109 print "%s[" % Color.green, ' '.join("%x" % i for i in p), "]%s" % Color.normal, 110 print 111 112 idx += ( ins.get_length() ) 113 nb += 1
114 115
116 -def PrettyShow1( basic_blocks ) :
117 idx = 0 118 nb = 0 119 for i in basic_blocks : 120 121 print "%s%s%s : " % (Color.purple, i.name, Color.normal) 122 for ins in i.ins : 123 print "\t%s%d%s(%s%x%s)" % (Color.yellow, nb, Color.normal, Color.yellow, idx, Color.normal), 124 ins.show( idx ) 125 126 if ins == i.ins[-1] and i.childs != [] : 127 if len(i.childs) == 2 : 128 print "%s[ %s%s " % (Color.red, i.childs[0][2].name, Color.green), 129 print ' '.join("%s" % c[2].name for c in i.childs[1:]), "]%s" % Color.normal, 130 else : 131 print "%s[" % Color.blue, ' '.join("%s" % c[2].name for c in i.childs), "]%s" % Color.normal, 132 133 idx += ins.get_length() 134 nb += 1 135 136 print 137 print
138
139 -def PrettyShow1bis( basic_blocks ) :
140 idx = 0 141 nb = 0 142 for i in basic_blocks : 143 144 print "%s : " % (i.name) 145 for ins in i.ins : 146 print "\t%d(%x)" % (nb, idx), 147 ins.show( idx ) 148 149 if ins == i.ins[-1] and i.childs != [] : 150 print "[", ' '.join("%s" % c[2].name for c in i.childs), "]", 151 152 idx += ins.get_length() 153 nb += 1 154 155 print 156 print
157 158 # Use to print diff basic blocks !
159 -def PrettyShow2( basic_blocks ) :
160 idx = 0 161 nb = 0 162 for i in basic_blocks : 163 if i.bb_tag == 1 : 164 print "%sDIFF%s" % (Color.cyan, Color.normal), 165 elif i.bb_tag == 2 : 166 print "%sNEW%s" %(Color.cyan, Color.normal), 167 168 print "%s%s%s : " % (Color.purple, i.name, Color.normal) 169 for ins in i.ins : 170 print "\t%s%d%s(%s%x%s)" % (Color.yellow, nb, Color.normal, Color.yellow, idx, Color.normal), 171 172 try : 173 tag = getattr(ins, "diff_tag") 174 except AttributeError : 175 tag = 0 176 177 if tag == 1 : 178 print "%s" % Color.green, 179 elif tag == 2 : 180 print "%s" % Color.red, 181 182 ins.show( idx ) 183 184 childs = None 185 try : 186 childs = getattr( ins, "childs" ) 187 except AttributeError : 188 if ins == i.ins[-1] : 189 if i.childs != [] : 190 childs = i.childs 191 192 if childs != None and childs != [] : 193 if len(childs) == 2 : 194 print "%s[ %s%s " % (Color.red, childs[0][2].name, Color.green), 195 print ' '.join("%s" % c[2].name for c in childs[1:]), "]%s" % Color.normal, 196 else : 197 print "%s[" % Color.blue, ' '.join("%s" % c[2].name for c in childs), "]%s" % Color.normal, 198 199 if tag == 0 : 200 idx += ins.get_length() 201 202 nb += 1 203 204 print 205 print
206
207 -def method2dot( mx ) :
208 """ 209 210 """ 211 buff = "" 212 for i in mx.basic_blocks.get() : 213 val = "green" 214 if len(i.childs) > 1 : 215 val = "red" 216 elif len(i.childs) == 1 : 217 val = "blue" 218 219 for j in i.childs : 220 buff += "\"%s\" -> \"%s\" [color=\"%s\"];\n" % ( i.get_name(), j[-1].get_name(), val ) 221 if val == "red" : 222 val = "green" 223 224 idx = i.start 225 label = "" 226 for ins in i.ins : 227 label += "%x %s\l" % (idx, ins.show_buff(idx)) 228 idx += ins.get_length() 229 230 buff += "\"%s\" [color=\"lightgray\", label=\"%s\"]\n" % (i.get_name(), label) 231 return buff
232
233 -def method2format( output, _format="png", mx = None, raw = False ) :
234 """ 235 236 """ 237 try : 238 import pydot 239 except ImportError : 240 error("module pydot not found") 241 242 buff = "digraph code {\n" 243 buff += "graph [bgcolor=white];\n" 244 buff += "node [color=lightgray, style=filled shape=box fontname=\"Courier\" fontsize=\"8\"];\n" 245 246 if raw == False : 247 buff += method2dot( mx ) 248 else : 249 buff += raw 250 251 buff += "}" 252 253 d = pydot.graph_from_dot_data( buff ) 254 255 getattr(d, "write_" + _format)( output )
256
257 -def method2png( output, mx = None, raw = False ) :
258 """ 259 260 """ 261 buff = raw 262 if raw == False : 263 buff = method2dot( mx ) 264 265 method2format( output, "png", mx, buff )
266
267 -class SV :
268 """SV is used to handle more easily a value"""
269 - def __init__(self, size, buff) :
270 self.__size = size 271 self.__value = unpack(self.__size, buff)[0]
272
273 - def _get(self) :
274 return pack(self.__size, self.__value)
275
276 - def __str__(self) :
277 return "0x%x" % self.__value
278
279 - def __int__(self) :
280 return self.__value
281
282 - def get_value_buff(self) :
283 return self._get()
284
285 - def get_value(self) :
286 return self.__value
287
288 - def set_value(self, attr) :
289 self.__value = attr
290
291 -class SVs :
292 """SVs is used to handle more easily a structure of different values"""
293 - def __init__(self, size, ntuple, buff) :
294 self.__size = size 295 296 self.__value = ntuple._make( unpack( self.__size, buff ) )
297
298 - def _get(self) :
299 l = [] 300 for i in self.__value._fields : 301 l.append( getattr( self.__value, i ) ) 302 return pack( self.__size, *l)
303
304 - def _export(self) :
305 return [ x for x in self.__value._fields ]
306
307 - def get_value_buff(self) :
308 return self._get()
309
310 - def get_value(self) :
311 return self.__value
312
313 - def set_value(self, attr) :
314 self.__value = self.__value._replace( **attr )
315
316 - def __str__(self) :
317 return self.__value.__str__()
318
319 -class MethodBC(object) :
320 - def show(self, value) :
321 getattr(self, "show_" + value)()
322
323 -class BuffHandle :
324 - def __init__(self, buff) :
325 self.__buff = buff 326 self.__idx = 0
327
328 - def read_b(self, size) :
329 return self.__buff[ self.__idx : self.__idx + size ]
330
331 - def read(self, size) :
332 if isinstance(size, SV) : 333 size = size.value 334 335 buff = self.__buff[ self.__idx : self.__idx + size ] 336 self.__idx += size 337 338 return buff
339
340 - def end(self) :
341 return self.__idx == len(self.__buff)
342
343 -class Buff :
344 - def __init__(self, offset, buff) :
345 self.offset = offset 346 self.buff = buff 347 348 self.size = len(buff)
349
350 -class _Bytecode(object) :
351 - def __init__(self, buff) :
352 try : 353 pass 354 #import psyco 355 #psyco.full() 356 except ImportError : 357 warning("module psyco not found") 358 359 self.__buff = buff 360 self.__idx = 0
361 362
363 - def read(self, size) :
364 if isinstance(size, SV) : 365 size = size.value 366 367 buff = self.__buff[ self.__idx : self.__idx + size ] 368 self.__idx += size 369 370 return buff
371
372 - def readat(self, off) :
373 if isinstance(off, SV) : 374 off = off.value 375 376 return self.__buff[ off : ]
377
378 - def read_b(self, size) :
379 return self.__buff[ self.__idx : self.__idx + size ]
380
381 - def set_idx(self, idx) :
382 if isinstance(idx, SV) : 383 self.__idx = idx.value 384 else : 385 self.__idx = idx
386
387 - def get_idx(self) :
388 return self.__idx
389
390 - def add_idx(self, idx) :
391 self.__idx += idx
392
393 - def register(self, type_register, fct) :
394 self.__registers[ type_register ].append( fct )
395
396 - def get_buff(self) :
397 return self.__buff
398
399 - def length_buff(self) :
400 return len( self.__buff )
401
402 - def save(self, filename) :
403 fd = open(filename, "w") 404 buff = self._save() 405 fd.write( buff ) 406 fd.close()
407
408 -def FormatClassToJava(input) :
409 """ 410 Transofmr a typical xml format class into java format 411 412 @param input : the input class name 413 """ 414 return "L" + input.replace(".", "/") + ";"
415
416 -def FormatClassToPython(input) :
417 i = input[:-1] 418 i = i.replace("/", "_") 419 i = i.replace("$", "_") 420 421 return i
422
423 -def FormatNameToPython(input) :
424 i = input.replace("<", "") 425 i = i.replace(">", "") 426 i = i.replace("$", "_") 427 428 return i
429
430 -def FormatDescriptorToPython(input) :
431 i = input.replace("/", "_") 432 i = i.replace(";", "") 433 i = i.replace("[", "_") 434 i = i.replace("(", "_") 435 i = i.replace(")", "__") 436 i = i.replace(" ", "") 437 438 return i
439 440 ####################### class/method/field export ########################
441 -def ExportVMToPython(vm) :
442 for _class in vm.get_classes() : 443 ### Class 444 name = "CLASS_" + FormatClassToPython( _class.get_name() ) 445 setattr( vm, name, _class ) 446 447 ### Methods 448 m = {} 449 for method in _class.get_methods() : 450 if method.get_name() not in m : 451 m[ method.get_name() ] = [] 452 m[ method.get_name() ].append( method ) 453 454 for i in m : 455 if len(m[i]) == 1 : 456 j = m[i][0] 457 name = "METHOD_" + FormatNameToPython( j.get_name() ) 458 setattr( _class, name, j ) 459 else : 460 for j in m[i] : 461 name = "METHOD_" + FormatNameToPython( j.get_name() ) + FormatDescriptorToPython( j.get_descriptor() ) 462 setattr( _class, name, j ) 463 464 ### Fields 465 f = {} 466 for field in _class.get_fields() : 467 if field.get_name() not in f : 468 f[ field.get_name() ] = [] 469 f[ field.get_name() ].append( field ) 470 471 for i in f : 472 if len(f[i]) == 1 : 473 j = f[i][0] 474 name = "FIELD_" + FormatNameToPython( j.get_name() ) 475 setattr( _class, name, j ) 476 else : 477 for j in f[i] : 478 name = "FIELD_" + FormatNameToPython( j.get_name() ) + FormatDescriptorToPython( j.get_descriptor() ) 479 setattr( _class, name, j )
480