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

Source Code for Module analysis

   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  import re, random, string, cPickle 
  20   
  21  from error import error, warning 
  22  import jvm, dvm 
  23  from api_permissions import DVM_PERMISSIONS_BY_PERMISSION, DVM_PERMISSIONS_BY_ELEMENT 
  24   
25 -class ContextField :
26 - def __init__(self, mode) :
27 self.mode = mode 28 self.details = []
29
30 - def set_details(self, details) :
31 for i in details : 32 self.details.append( i )
33
34 -class ContextMethod :
35 - def __init__(self) :
36 self.details = []
37
38 - def set_details(self, details) :
39 for i in details : 40 self.details.append( i )
41
42 -class ExternalFM :
43 - def __init__(self, class_name, name, descriptor) :
44 self.class_name = class_name 45 self.name = name 46 self.descriptor = descriptor
47
48 - def get_class_name(self) :
49 return self.class_name
50
51 - def get_name(self) :
52 return self.name
53
54 - def get_descriptor(self) :
55 return self.descriptor
56
57 -class ToString :
58 - def __init__(self, tab) :
59 self.__tab = tab 60 self.__re_tab = {} 61 62 for i in self.__tab : 63 self.__re_tab[i] = [] 64 for j in self.__tab[i] : 65 self.__re_tab[i].append( re.compile( j ) ) 66 67 self.__string = ""
68
69 - def push(self, name) :
70 for i in self.__tab : 71 for j in self.__re_tab[i] : 72 if j.match(name) != None : 73 if len(self.__string) > 0 : 74 if i == 'O' and self.__string[-1] == 'O' : 75 continue 76 self.__string += i
77
78 - def get_string(self) :
79 return self.__string
80
81 -class BreakBlock(object) :
82 - def __init__(self, _vm, idx) :
83 self._vm = _vm 84 self._start = idx 85 self._end = self._start 86 87 self._ins = [] 88 89 self._ops = [] 90 91 self._fields = {} 92 self._methods = {}
93 94
95 - def get_ops(self) :
96 return self._ops
97
98 - def get_fields(self) :
99 return self._fields
100
101 - def get_methods(self) :
102 return self._methods
103
104 - def push(self, ins) :
105 self._ins.append(ins) 106 self._end += ins.get_length()
107
108 - def get_start(self) :
109 return self._start
110
111 - def get_end(self) :
112 return self._end
113
114 - def show(self) :
115 for i in self._ins : 116 print "\t\t", 117 i.show(0)
118 119 ##### DVM ###### 120 121 MATH_DVM_RE = [] 122 for i in dvm.MATH_DVM_OPCODES : 123 MATH_DVM_RE.append( (re.compile( i ), dvm.MATH_DVM_OPCODES[i]) ) 124 125 DVM_TOSTRING = { "O" : dvm.MATH_DVM_OPCODES.keys(), 126 "I" : dvm.INVOKE_DVM_OPCODES, 127 "G" : dvm.FIELD_READ_DVM_OPCODES, 128 "P" : dvm.FIELD_WRITE_DVM_OPCODES, 129 } 130
131 -class DVMBreakBlock(BreakBlock) :
132 - def __init__(self, _vm) :
133 super(DVMBreakBlock, self).__init__(_vm)
134
135 - def analyze(self) :
136 for i in self._ins : 137 for mre in MATH_DVM_RE : 138 if mre[0].match( i.get_name() ) : 139 self._ops.append( mre[1] ) 140 break
141 142 ##### JVM ###### 143 FIELDS = { 144 "getfield" : "R", 145 "getstatic" : "R", 146 "putfield" : "W", 147 "putstatic" : "W", 148 } 149 150 METHODS = [ "invokestatic", "invokevirtual", "invokespecial" ] 151 152 JVM_TOSTRING = { "O" : jvm.MATH_JVM_OPCODES.keys(), 153 "I" : jvm.INVOKE_JVM_OPCODES, 154 "G" : jvm.FIELD_READ_JVM_OPCODES, 155 "P" : jvm.FIELD_WRITE_JVM_OPCODES, 156 } 157 158 BREAK_JVM_OPCODES_RE = [] 159 for i in jvm.BREAK_JVM_OPCODES : 160 BREAK_JVM_OPCODES_RE.append( re.compile( i ) ) 161
162 -class Stack :
163 - def __init__(self) :
164 self.__elems = []
165
166 - def gets(self) :
167 return self.__elems
168
169 - def push(self, elem) :
170 self.__elems.append( elem )
171
172 - def get(self) :
173 return self.__elems[-1]
174
175 - def pop(self) :
176 return self.__elems.pop(-1)
177
178 - def nil(self) :
179 return len(self.__elems) == 0
180
181 - def insert_stack(self, idx, elems) :
182 if elems != self.__elems : 183 for i in elems : 184 self.__elems.insert(idx, i) 185 idx += 1
186
187 - def show(self) :
188 nb = 0 189 190 if len(self.__elems) == 0 : 191 print "\t--> nil" 192 193 for i in self.__elems : 194 print "\t-->", nb, ": ", i 195 nb += 1
196
197 -class StackTraces :
198 - def __init__(self) :
199 self.__elems = []
200
201 - def save(self, idx, i_idx, ins, stack_pickle, msg_pickle) :
202 self.__elems.append( (idx, i_idx, ins, stack_pickle, msg_pickle) )
203
204 - def get(self) :
205 for i in self.__elems : 206 yield (i[0], i[1], i[2], cPickle.loads( i[3] ), cPickle.loads( i[4] ) )
207
208 - def show(self) :
209 for i in self.__elems : 210 print i[0], i[1], i[2].get_name() 211 212 cPickle.loads( i[3] ).show() 213 print "\t", cPickle.loads( i[4] )
214
215 -def push_objectref(_vm, ins, special, stack, res, ret_v) :
216 value = "OBJ_REF_@_%s" % str(special) 217 stack.push( value )
218
219 -def push_objectref_l(_vm, ins, special, stack, res, ret_v) :
220 stack.push( "VARIABLE_LOCAL_%d" % special )
221
222 -def push_objectref_l_i(_vm, ins, special, stack, res, ret_v) :
223 stack.push( "VARIABLE_LOCAL_%d" % ins.get_operands() )
224
225 -def pop_objectref(_vm, ins, special, stack, res, ret_v) :
226 ret_v.add_return( stack.pop() )
227
228 -def multi_pop_objectref_i(_vm, ins, special, stack, res, ret_v) :
229 for i in range(0, ins.get_operands()[1]) : 230 stack.pop()
231
232 -def push_objectres(_vm, ins, special, stack, res, ret_v) :
233 value = "" 234 235 if special[0] == 1 : 236 value += special[1] + "(" + str( res.pop() ) + ") " 237 else : 238 for i in range(0, special[0]) : 239 value += str( res.pop() ) + special[1] 240 241 value = value[:-1] 242 243 stack.push( value )
244
245 -def push_integer_i(_vm, ins, special, stack, res, ret_v) :
246 value = ins.get_operands() 247 stack.push( value )
248
249 -def push_integer_d(_vm, ins, special, stack, res, ret_v) :
250 stack.push( special )
251
252 -def push_float_d(_vm, ins, special, stack, res, ret_v) :
253 stack.push( special )
254
255 -def putfield(_vm, ins, special, stack, res, ret_v) :
256 ret_v.add_return( stack.pop() )
257
258 -def putstatic(_vm, ins, special, stack, res, ret_v) :
259 stack.pop()
260
261 -def getfield(_vm, ins, special, stack, res, ret_v) :
262 ret_v.add_return( stack.pop() ) 263 stack.push( "FIELD" )
264
265 -def getstatic(_vm, ins, special, stack, res, ret_v) :
266 stack.push( "FIELD_STATIC" )
267
268 -def new(_vm, ins, special, stack, res, ret_v) :
269 stack.push( "NEW_OBJ" )
270
271 -def dup(_vm, ins, special, stack, res, ret_v) :
272 l = [] 273 274 for i in range(0, special+1) : 275 l.append( stack.pop() ) 276 l.reverse() 277 278 l.insert( 0, l[-1] ) 279 for i in l : 280 stack.push( i )
281
282 -def dup2(_vm, ins, special, stack, res, ret_v) :
283 l = [] 284 285 for i in range(0, special+1) : 286 l.append( stack.pop() ) 287 l.reverse() 288 289 l.insert( 0, l[-1] ) 290 l.insert( 1, l[-2] ) 291 for i in l : 292 stack.push( i )
293 294 #FIXME
295 -def ldc(_vm, ins, special, stack, res, ret_v) :
296 #print ins.get_name(), ins.get_operands(), special 297 stack.push( "STRING" )
298
299 -def invoke(_vm, ins, special, stack, res, ret_v) :
300 desc = ins.get_operands()[-1] 301 param = desc[1:desc.find(")")] 302 ret = desc[desc.find(")")+1:] 303 304 # print "DESC --->", param, calc_nb( param ), ret, calc_nb( ret ) 305 306 for i in range(0, calc_nb( param )) : 307 stack.pop() 308 309 # objectref : static or not 310 for i in range(0, special) : 311 stack.pop() 312 313 for i in range(0, calc_nb( ret )): 314 stack.push( "E" )
315
316 -def set_arrayref(_vm, ins, special, stack, res, ret_v) :
317 ret_v.add_msg( "SET VALUE %s %s @ ARRAY REF %s %s" % (special, str(stack.pop()), str(stack.pop()), str(stack.pop())) )
318
319 -def set_objectref(_vm, ins, special, stack, res, ret_v) :
320 ret_v.add_msg( "SET OBJECT REF %d --> %s" % (special, str(stack.pop())) )
321
322 -def set_objectref_i(_vm, ins, special, stack, res, ret_v) :
323 ret_v.add_msg( "SET OBJECT REF %d --> %s" % (ins.get_operands(), str(stack.pop())) )
324
325 -def swap(_vm, ins, special, stack, res, ret_v) :
326 l = stack.pop() 327 l2 = stack.pop() 328 329 stack.push(l2) 330 stack.push(l)
331
332 -def calc_nb(info) :
333 if info == "" or info == "V" : 334 return 0 335 336 if ";" in info : 337 n = 0 338 for i in info.split(";") : 339 if i != "" : 340 n += 1 341 return n 342 else : 343 return len(info) - info.count('[')
344 345 INSTRUCTIONS_ACTIONS = { 346 "aaload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 347 "aastore" : [ { set_arrayref : None } ], 348 "aconst_null" : [ { push_objectref : "null" } ], 349 "aload" : [ { push_objectref_l_i : None } ], 350 "aload_0" : [ { push_objectref_l : 0 } ], 351 "aload_1" : [ { push_objectref_l : 1 } ], 352 "aload_2" : [ { push_objectref_l : 2 } ], 353 "aload_3" : [ { push_objectref_l : 3 } ], 354 "anewarray" : [ { pop_objectref : None }, { push_objectref : [ 1, "ANEWARRAY" ] } ], 355 "areturn" : [ { pop_objectref : None } ], 356 "arraylength" : [ { pop_objectref : None }, { push_objectres : [ 1, 'LENGTH' ] } ], 357 "astore" : [ { set_objectref_i : None } ], 358 "astore_0" : [ { set_objectref : 0 } ], 359 "astore_1" : [ { set_objectref : 1 } ], 360 "astore_2" : [ { set_objectref : 2 } ], 361 "astore_3" : [ { set_objectref : 3 } ], 362 "athrow" : [ { pop_objectref : None }, { push_objectres : [ 1, "throw" ] } ], 363 "baload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 364 "bastore" : [ { set_arrayref : "byte" } ], 365 "bipush" : [ { push_integer_i : None } ], 366 "caload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 367 "castore" : [ { set_arrayref : "char" } ], 368 "checkcast" : [ { pop_objectref : None }, { push_objectres : [ 1, "checkcast" ] } ], 369 "d2f" : [ { pop_objectref : None }, { push_objectres : [ 1, 'float' ] } ], 370 "d2i" : [ { pop_objectref : None }, { push_objectres : [ 1, 'integer' ] } ], 371 "d2l" : [ { pop_objectref : None }, { push_objectres : [ 1, 'long' ] } ], 372 "dadd" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '+' ] } ], 373 "daload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 374 "dastore" : [ { set_arrayref : "double" } ], 375 "dcmpg" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 376 "dcmpl" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 377 "dconst_0" : [ { push_float_d : 0.0 } ], 378 "dconst_1" : [ { push_float_d : 1.0 } ], 379 "ddiv" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '&' ] } ], 380 "dload" : [ { push_objectref_l_i : None } ], 381 "dload_0" : [ { push_objectref_l : 0 } ], 382 "dload_1" : [ { push_objectref_l : 1 } ], 383 "dload_2" : [ { push_objectref_l : 2 } ], 384 "dload_3" : [ { push_objectref_l : 3 } ], 385 "dmul" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '*' ] } ], 386 "dneg" : [ { pop_objectref : None }, { push_objectres : [ 1, '-' ] } ], 387 "drem" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, 'rem' ] } ], 388 "dreturn" : [ { pop_objectref : None } ], 389 "dstore" : [ { set_objectref_i : None } ], 390 "dstore_0" : [ { set_objectref : 0 } ], 391 "dstore_1" : [ { set_objectref : 1 } ], 392 "dstore_2" : [ { set_objectref : 2 } ], 393 "dstore_3" : [ { set_objectref : 3 } ], 394 "dsub" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '-' ] } ], 395 "dup" : [ { dup : 0 } ], 396 "dup_x1" : [ { dup : 1 } ], 397 "dup_x2" : [ { dup : 2 } ], 398 "dup2" : [ { dup2 : 0 } ], 399 "dup2_x1" : [ { dup2 : 1 } ], 400 "dup2_x2" : [ { dup2 : 2 } ], 401 "f2d" : [ { pop_objectref : None }, { push_objectres : [ 1, 'double' ] } ], 402 "f2i" : [ { pop_objectref : None }, { push_objectres : [ 1, 'integer' ] } ], 403 "f2l" : [ { pop_objectref : None }, { push_objectres : [ 1, 'long' ] } ], 404 "fadd" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '+' ] } ], 405 "faload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 406 "fastore" : [ { set_arrayref : "float" } ], 407 "fcmpg" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 408 "fcmpl" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 409 "fconst_0" : [ { push_float_d : 0.0 } ], 410 "fconst_1" : [ { push_float_d : 1.0 } ], 411 "fconst_2" : [ { push_float_d : 2.0 } ], 412 "fdiv" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '&' ] } ], 413 "fload" : [ { push_objectref_l_i : None } ], 414 "fload_0" : [ { push_objectref_l : 0 } ], 415 "fload_1" : [ { push_objectref_l : 1 } ], 416 "fload_2" : [ { push_objectref_l : 2 } ], 417 "fload_3" : [ { push_objectref_l : 3 } ], 418 "fmul" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '*' ] } ], 419 "fneg" : [ { pop_objectref : None }, { push_objectres : [ 1, '-' ] } ], 420 "freturn" : [ { pop_objectref : None } ], 421 "fstore" : [ { set_objectref_i : None } ], 422 "fstore_0" : [ { set_objectref : 0 } ], 423 "fstore_1" : [ { set_objectref : 1 } ], 424 "fstore_2" : [ { set_objectref : 2 } ], 425 "fstore_3" : [ { set_objectref : 3 } ], 426 "fsub" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '-' ] } ], 427 "getfield" : [ { getfield : None } ], 428 "getstatic" : [ { getstatic : None } ], 429 "goto" : [ {} ], 430 "goto_w" : [ {} ], 431 "i2b" : [ { pop_objectref : None }, { push_objectres : [ 1, 'byte' ] } ], 432 "i2c" : [ { pop_objectref : None }, { push_objectres : [ 1, 'char' ] } ], 433 "i2d" : [ { pop_objectref : None }, { push_objectres : [ 1, 'double' ] } ], 434 "i2f" : [ { pop_objectref : None }, { push_objectres : [ 1, 'float' ] } ], 435 "i2l" : [ { pop_objectref : None }, { push_objectres : [ 1, 'long' ] } ], 436 "i2s" : [ { pop_objectref : None }, { push_objectres : [ 1, 'string' ] } ], 437 "iadd" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '+' ] } ], 438 "iaload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 439 "iand" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '&' ] } ], 440 "iastore" : [ { set_arrayref : "int" } ], 441 "iconst_m1" : [ { push_integer_d : -1 } ], 442 "iconst_0" : [ { push_integer_d : 0 } ], 443 "iconst_1" : [ { push_integer_d : 1 } ], 444 "iconst_2" : [ { push_integer_d : 2 } ], 445 "iconst_3" : [ { push_integer_d : 3 } ], 446 "iconst_4" : [ { push_integer_d : 4 } ], 447 "iconst_5" : [ { push_integer_d : 5 } ], 448 "idiv" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '/' ] } ], 449 "if_acmpeq" : [ { pop_objectref : None }, { pop_objectref : None } ], 450 "if_acmpne" : [ { pop_objectref : None }, { pop_objectref : None } ], 451 "if_icmpeq" : [ { pop_objectref : None }, { pop_objectref : None } ], 452 "if_icmpne" : [ { pop_objectref : None }, { pop_objectref : None } ], 453 "if_icmplt" : [ { pop_objectref : None }, { pop_objectref : None } ], 454 "if_icmpge" : [ { pop_objectref : None }, { pop_objectref : None } ], 455 "if_icmpgt" : [ { pop_objectref : None }, { pop_objectref : None } ], 456 "if_icmple" : [ { pop_objectref : None }, { pop_objectref : None } ], 457 "ifeq" : [ { pop_objectref : None } ], 458 "ifne" : [ { pop_objectref : None } ], 459 "iflt" : [ { pop_objectref : None } ], 460 "ifge" : [ { pop_objectref : None } ], 461 "ifgt" : [ { pop_objectref : None } ], 462 "ifle" : [ { pop_objectref : None } ], 463 "ifnonnull" : [ { pop_objectref : None } ], 464 "ifnull" : [ { pop_objectref : None } ], 465 "iinc" : [ {} ], 466 "iload" : [ { push_objectref_l_i : None } ], 467 "iload_1" : [ { push_objectref_l : 1 } ], 468 "iload_2" : [ { push_objectref_l : 2 } ], 469 "iload_3" : [ { push_objectref_l : 3 } ], 470 "imul" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '*' ] } ], 471 "ineg" : [ { pop_objectref : None }, { push_objectres : [ 1, '-' ] } ], 472 "instanceof" : [ { pop_objectref : None }, { push_objectres : [ 1, 'instanceof' ] } ], 473 "invokeinterface" : [ { invoke : 1 } ], 474 "invokespecial" : [ { invoke : 1 } ], 475 "invokestatic" : [ { invoke : 0 } ], 476 "invokevirtual": [ { invoke : 1 } ], 477 "ior" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '|' ] } ], 478 "irem" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, 'REM' ] } ], 479 "ireturn" : [ { pop_objectref : None } ], 480 "ishl" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '<<' ] } ], 481 "ishr" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '>>' ] } ], 482 "istore" : [ { set_objectref_i : None } ], 483 "istore_0" : [ { set_objectref : 0 } ], 484 "istore_1" : [ { set_objectref : 1 } ], 485 "istore_2" : [ { set_objectref : 2 } ], 486 "istore_3" : [ { set_objectref : 3 } ], 487 "isub" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '-' ] } ], 488 "iushr" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '>>' ] } ], 489 "ixor" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '^' ] } ], 490 "jsr" : [ { push_integer_i : None } ], 491 "jsr_w" : [ { push_integer_i : None } ], 492 "l2d" : [ { pop_objectref : None }, { push_objectres : [ 1, 'double' ] } ], 493 "l2f" : [ { pop_objectref : None }, { push_objectres : [ 1, 'float' ] } ], 494 "l2i" : [ { pop_objectref : None }, { push_objectres : [ 1, 'integer' ] } ], 495 "ladd" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '+' ] } ], 496 "laload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 497 "land" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '&' ] } ], 498 "lastore" : [ { set_arrayref : "long" } ], 499 "lcmp" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 500 "lconst_0" : [ { push_float_d : 0.0 } ], 501 "lconst_1" : [ { push_float_d : 1.0 } ], 502 "ldc" : [ { ldc : None } ], 503 "ldc_w" : [ { ldc : None } ], 504 "ldc2_w" : [ { ldc : None } ], 505 "ldiv" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '/' ] } ], 506 "lload" : [ { push_objectref_l_i : None } ], 507 "lload_0" : [ { push_objectref_l : 0 } ], 508 "lload_1" : [ { push_objectref_l : 1 } ], 509 "lload_2" : [ { push_objectref_l : 2 } ], 510 "lload_3" : [ { push_objectref_l : 3 } ], 511 "lmul" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '*' ] } ], 512 "lneg" : [ { pop_objectref : None }, { push_objectres : [ 1, '-' ] } ], 513 "lookupswitch" : [ { pop_objectref : None } ], 514 "lor" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '|' ] } ], 515 "lrem" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, 'REM' ] } ], 516 "lreturn" : [ { pop_objectref : None } ], 517 "lshl" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '<<' ] } ], 518 "lshr" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '>>' ] } ], 519 "lstore" : [ { set_objectref_i : None } ], 520 "lstore_0" : [ { set_objectref : 0 } ], 521 "lstore_1" : [ { set_objectref : 1 } ], 522 "lstore_2" : [ { set_objectref : 2 } ], 523 "lstore_3" : [ { set_objectref : 3 } ], 524 "lsub" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '-' ] } ], 525 "lushr" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '>>' ] } ], 526 "lxor" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '^' ] } ], 527 "monitorenter" : [ { pop_objectref : None } ], 528 "monitorexit" : [ { pop_objectref : None } ], 529 "multianewarray" : [ { multi_pop_objectref_i : None }, { push_objectref : 0 } ], 530 "new" : [ { new : None } ], 531 "newarray" : [ { pop_objectref : None }, { push_objectref : [ 1, "NEWARRAY" ] } ], 532 "nop" : [ {} ], 533 "pop" : [ { pop_objectref : None } ], 534 "pop2" : [ { pop_objectref : None }, { pop_objectref : None } ], 535 "putfield" : [ { putfield : None }, { pop_objectref : None } ], 536 "putstatic" : [ { putstatic : None } ], 537 "ret" : [ {} ], 538 "return" : [ {} ], 539 "saload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ], 540 "sastore" : [ { set_arrayref : "short" } ], 541 "sipush" : [ { push_integer_i : None } ], 542 "swap" : [ { swap : None } ], 543 "tableswitch" : [ { pop_objectref : None } ], 544 "wide" : [ {} ], 545 } 546 547
548 -class ReturnValues :
549 - def __init__(self) :
550 self.__elems = [] 551 self.__msgs = []
552
553 - def add_msg(self, e) :
554 self.__msgs.append( e )
555
556 - def add_return(self, e) :
557 self.__elems.append( e )
558
559 - def get_msg(self) :
560 return self.__msgs
561
562 - def get_return(self) :
563 return self.__elems
564
565 -class ExternalMethod :
566 - def __init__(self, class_name, name, descriptor) :
567 self.__class_name = class_name 568 self.__name = name 569 self.__descriptor = descriptor
570
571 - def get_name(self) :
572 return "M@[%s][%s]-[%s]" % (self.__class_name, self.__name, self.__descriptor)
573
574 - def set_fathers(self, f) :
575 pass
576
577 -class JVMBasicBlock :
578 - def __init__(self, start, _vm, _method, _context) :
579 self.__vm = _vm 580 self.__method = _method 581 self.__context = _context 582 583 self.__stack = Stack() 584 self.stack_traces = StackTraces() 585 586 self.ins = [] 587 588 self.fathers = [] 589 self.childs = [] 590 591 self.start = start 592 self.end = self.start 593 594 self.break_blocks = [] 595 596 self.free_blocks_offsets = [] 597 598 self.name = "%s-BB@0x%x" % (self.__method.get_name(), self.start)
599
600 - def get_stack(self) :
601 return self.__stack.gets()
602
603 - def get_method(self) :
604 return self.__method
605
606 - def get_name(self) :
607 return self.name
608
609 - def get_start(self) :
610 return self.start
611
612 - def get_end(self) :
613 return self.end
614
615 - def get_last(self) :
616 return self.ins[-1]
617
618 - def push(self, i) :
619 self.ins.append( i ) 620 self.end += i.get_length()
621
622 - def set_fathers(self, f) :
623 self.fathers.append( f )
624
625 - def set_childs(self, values) :
626 # print self, self.start, self.end, values, self.ins[-1].get_name() 627 if values == [] : 628 next_block = self.__context.get_basic_block( self.end + 1 ) 629 if next_block != None : 630 self.childs.append( ( self.end - self.ins[-1].get_length(), self.end, next_block ) ) 631 else : 632 for i in values : 633 #print i, self.__context.get_basic_block( i ) 634 if i != -1 : 635 self.childs.append( ( self.end - self.ins[-1].get_length(), i, self.__context.get_basic_block( i ) ) ) 636 637 for c in self.childs : 638 if c[2] != None : 639 c[2].set_fathers( ( c[1], c[0], self ) )
640
641 - def prev_free_block_offset(self, idx=0) :
642 last = -1 643 644 #print "IDX", idx, self.free_blocks_offsets 645 646 if self.free_blocks_offsets == [] : 647 return -1 648 649 for i in self.free_blocks_offsets : 650 if i <= idx : 651 last = i 652 else : 653 return last 654 655 return last
656
657 - def random_free_block_offset(self) :
658 return self.free_blocks_offsets[ random.randint(0, len(self.free_blocks_offsets) - 1) ]
659
660 - def next_free_block_offset(self, idx=0) :
661 #print idx, self.__free_blocks_offsets 662 for i in self.free_blocks_offsets : 663 if i > idx : 664 return i 665 return -1
666
668 return self.free_blocks_offsets[ random.randint(0, len(self.free_blocks_offsets) - 1) ]
669
670 - def get_random_break_block(self) :
671 return self.break_blocks[ random.randint(0, len(self.break_blocks) - 1) ]
672
673 - def get_break_block(self, idx) :
674 for i in self.break_blocks : 675 if idx >= i.get_start() and idx <= i.get_end() : 676 return i 677 return None
678
679 - def analyze_break_blocks(self) :
680 idx = self.get_start() 681 682 current_break = JVMBreakBlock( self.__vm, idx ) 683 self.break_blocks.append(current_break) 684 for i in self.ins : 685 name = i.get_name() 686 687 ##################### Break Block ######################## 688 match = False 689 for j in BREAK_JVM_OPCODES_RE : 690 if j.match(name) != None : 691 match = True 692 break 693 694 current_break.push( i ) 695 if match == True : 696 current_break.analyze() 697 current_break = JVMBreakBlock( self.__vm, current_break.get_end() ) 698 699 self.break_blocks.append( current_break ) 700 ######################################################### 701 702 idx += i.get_length()
703
704 - def analyze(self) :
705 idx = 0 706 for i in self.ins : 707 ################### TAINTED LOCAL VARIABLES ################### 708 if "load" in i.get_name() or "store" in i.get_name() : 709 action = i.get_name() 710 711 access_flag = [ "R", "load" ] 712 if "store" in action : 713 access_flag = [ "W", "store" ] 714 715 if "_" in action : 716 name = i.get_name().split(access_flag[1]) 717 value = name[1][-1] 718 else : 719 value = i.get_operands() 720 721 variable_name = "%s-%s" % (i.get_name()[0], value) 722 723 self.__context.get_tainted_variables().add( variable_name, TAINTED_LOCAL_VARIABLE, self.__method ) 724 self.__context.get_tainted_variables().push_info( TAINTED_LOCAL_VARIABLE, variable_name, (access_flag[0], idx, self, self.__method) ) 725 ######################################################### 726 727 ################### TAINTED FIELDS ################### 728 elif i.get_name() in FIELDS : 729 o = i.get_operands() 730 desc = getattr(self.__vm, "get_field_descriptor")(o[0], o[1], o[2]) 731 732 # It's an external 733 if desc == None : 734 desc = ExternalFM( o[0], o[1], o[2] ) 735 736 # print "RES", res, "-->", desc.get_name() 737 self.__context.get_tainted_variables().push_info( TAINTED_FIELD, desc, (FIELDS[ i.get_name() ][0], idx, self, self.__method) ) 738 ######################################################### 739 740 ################### TAINTED PACKAGES ################### 741 elif "new" in i.get_name() or "invoke" in i.get_name() or "getstatic" in i.get_name() : 742 if "new" in i.get_name() : 743 self.__context.get_tainted_packages()._push_info( i.get_operands(), (TAINTED_PACKAGE_CREATE, idx, self, self.__method) ) 744 else : 745 self.__context.get_tainted_packages()._push_info( i.get_operands()[0], (TAINTED_PACKAGE_CALL, idx, self, self.__method, i.get_operands()[1], i.get_operands()[2]) ) 746 ######################################################### 747 748 ################### TAINTED INTEGERS ################### 749 if "ldc" == i.get_name() : 750 o = i.get_operands() 751 752 if o[0] == "CONSTANT_Integer" : 753 self.__context.get_tainted_integers().push_info( i, (o[1], idx, self, self.__method) ) 754 755 elif "sipush" in i.get_name() : 756 self.__context.get_tainted_integers().push_info( i, (i.get_operands(), idx, self, self.__method) ) 757 758 elif "bipush" in i.get_name() : 759 self.__context.get_tainted_integers().push_info( i, (i.get_operands(), idx, self, self.__method) ) 760 761 ######################################################### 762 763 idx += i.get_length()
764 765 # FIXME : create a recursive function to follow the cfg, because it does not work with obfuscator
766 - def analyze_code(self) :
767 self.analyze_break_blocks() 768 769 #print "ANALYZE CODE -->", self.name 770 d = {} 771 for i in self.fathers : 772 # print "\t FATHER ->", i[2].get_name(), i[2].get_stack(), i[0], i[1] 773 d[ i[0] ] = i[2] 774 775 self.free_blocks_offsets.append( self.get_start() ) 776 777 idx = 0 778 for i in self.ins : 779 # print i.get_name(), self.start + idx, idx 780 # i.show(idx) 781 782 if self.start + idx in d : 783 self.__stack.insert_stack( 0, d[ self.start + idx ].get_stack() ) 784 785 ret_v = ReturnValues() 786 787 res = [] 788 try : 789 #print i.get_name(), i.get_name() in INSTRUCTIONS_ACTIONS 790 791 if INSTRUCTIONS_ACTIONS[ i.get_name() ] == [] : 792 print "[[[[ %s is not yet implemented ]]]]" % i.get_name() 793 raise("ooops") 794 795 i_idx = 0 796 for actions in INSTRUCTIONS_ACTIONS[ i.get_name() ] : 797 for action in actions : 798 action( self.__vm, i, actions[action], self.__stack, res, ret_v ) 799 for val in ret_v.get_return() : 800 res.append( val ) 801 802 #self.__stack.show() 803 self.stack_traces.save( idx, i_idx, i, cPickle.dumps( self.__stack ), cPickle.dumps( ret_v.get_msg() ) ) 804 i_idx += 1 805 806 except KeyError : 807 print "[[[[ %s is not in INSTRUCTIONS_ACTIONS ]]]]" % i.get_name() 808 except IndexError : 809 print "[[[[ Analysis failed in %s-%s-%s ]]]]" % (self.__method.get_class_name(), self.__method.get_name(), self.__method.get_descriptor()) 810 811 idx += i.get_length() 812 813 if self.__stack.nil() == True and i != self.ins[-1] : 814 self.free_blocks_offsets.append( idx + self.get_start() )
815
816 - def show(self) :
817 print "\t@", self.name 818 819 idx = 0 820 nb = 0 821 for i in self.ins : 822 print "\t\t", nb, idx, 823 i.show(nb) 824 nb += 1 825 idx += i.get_length() 826 827 print "" 828 print "\t\tFree blocks offsets --->", self.free_blocks_offsets 829 print "\t\tBreakBlocks --->", len(self.break_blocks) 830 831 print "\t\tF --->", ', '.join( i[2].get_name() for i in self.fathers ) 832 print "\t\tC --->", ', '.join( i[2].get_name() for i in self.childs ) 833 834 self.stack_traces.show()
835
836 - def get_ins(self) :
837 return self.ins
838
839 -class JVMBreakBlock(BreakBlock) :
840 - def __init__(self, _vm, idx) :
841 super(JVMBreakBlock, self).__init__(_vm, idx) 842 843 self.__info = { 844 "F" : [ "get_field_descriptor", self._fields, ContextField ], 845 "M" : [ "get_method_descriptor", self._methods, ContextMethod ], 846 }
847 848
849 - def get_free(self) :
850 if self._ins == [] : 851 return False 852 853 if "store" in self._ins[-1].get_name() : 854 return True 855 elif "putfield" in self._ins[-1].get_name() : 856 return True 857 858 return False
859
860 - def analyze(self) :
861 ctt = [] 862 863 stack = Stack() 864 for i in self._ins : 865 v = self.trans(i) 866 if v != None : 867 ctt.append( v ) 868 869 t = "" 870 871 for mre in jvm.MATH_JVM_RE : 872 if mre[0].match( i.get_name() ) : 873 self._ops.append( mre[1] ) 874 break 875 876 # Woot it's a field ! 877 if i.get_name() in FIELDS : 878 t = "F" 879 elif i.get_name() in METHODS : 880 t = "M" 881 882 if t != "" : 883 o = i.get_operands() 884 desc = getattr(self._vm, self.__info[t][0])(o[0], o[1], o[2]) 885 886 # It's an external 887 if desc == None : 888 desc = ExternalFM( o[0], o[1], o[2] ) 889 890 if desc not in self.__info[t][1] : 891 self.__info[t][1][desc] = [] 892 893 if t == "F" : 894 self.__info[t][1][desc].append( self.__info[t][2]( FIELDS[ i.get_name() ][0] ) ) 895 896 # print "RES", res, "-->", desc.get_name() 897 # self.__tf.push_info( desc, [ FIELDS[ i.get_name() ][0], res ] ) 898 elif t == "M" : 899 self.__info[t][1][desc].append( self.__info[t][2]() ) 900 901 for i in self._fields : 902 for k in self._fields[i] : 903 k.set_details( ctt ) 904 905 for i in self._methods : 906 for k in self._methods[i] : 907 k.set_details( ctt )
908
909 - def trans(self, i) :
910 v = i.get_name()[0:2] 911 if v == "il" or v == "ic" or v == "ia" or v == "si" or v == "bi" : 912 return "I" 913 914 if v == "ba" : 915 return "B" 916 917 if v == "if" : 918 return "IF" 919 920 if v == "ir" : 921 return "RET" 922 923 if "and" in i.get_name() : 924 return "&" 925 926 if "add" in i.get_name() : 927 return "+" 928 929 if "sub" in i.get_name() : 930 return "-" 931 932 if "xor" in i.get_name() : 933 return "^" 934 935 if "ldc" in i.get_name() : 936 return "I" 937 938 if "invokevirtual" in i.get_name() : 939 return "M" + i.get_operands()[2] 940 941 if "getfield" in i.get_name() : 942 return "F" + i.get_operands()[2]
943 944 945 DVM_FIELDS_ACCESS = { 946 "iget" : "R", 947 "iget-wide" : "R", 948 "iget-object" : "R", 949 "iget-boolean" : "R", 950 "iget-byte" : "R", 951 "iget-char" : "R", 952 "iget-short" : "R", 953 954 "iput" : "W", 955 "iput-wide" : "W", 956 "iput-object" : "W", 957 "iput-boolean" : "W", 958 "iput-byte" : "W", 959 "iput-char" : "W", 960 "iput-short" : "W", 961 962 "sget" : "R", 963 "sget-wide" : "R", 964 "sget-object" : "R", 965 "sget-boolean" : "R", 966 "sget-byte" : "R", 967 "sget-char" : "R", 968 "sget-short" : "R", 969 970 "sput" : "W", 971 "sput-wide" : "W", 972 "sput-object" : "W", 973 "sput-boolean" : "W", 974 "sput-byte" : "W", 975 "sput-char" : "W", 976 "sput-short" : "W", 977 } 978
979 -class DVMBasicBlock :
980 - def __init__(self, start, _vm, _method, _context) :
981 self.__vm = _vm 982 self.__method = _method 983 self.__context = _context 984 985 self.ins = [] 986 987 self.fathers = [] 988 self.childs = [] 989 990 self.start = start 991 self.end = self.start 992 993 self.break_blocks = [] 994 995 self.free_blocks_offsets = [] 996 997 self.name = "%s-BB@0x%x" % (self.__method.get_name(), self.start)
998
999 - def get_method(self) :
1000 return self.__method
1001
1002 - def get_name(self) :
1003 return self.name
1004
1005 - def get_start(self) :
1006 return self.start
1007
1008 - def get_end(self) :
1009 return self.end
1010
1011 - def get_last(self) :
1012 return self.ins[-1]
1013
1014 - def push(self, i) :
1015 self.ins.append( i ) 1016 self.end += i.get_length()
1017
1018 - def set_fathers(self, f) :
1019 self.fathers.append( f )
1020
1021 - def set_childs(self, values) :
1022 #print self, self.start, self.end, values, self.ins[-1].get_name() 1023 if values == [] : 1024 next_block = self.__context.get_basic_block( self.end + 1 ) 1025 if next_block != None : 1026 self.childs.append( ( self.end - self.ins[-1].get_length(), self.end, next_block ) ) 1027 else : 1028 for i in values : 1029 if i != -1 : 1030 next_block = self.__context.get_basic_block( i ) 1031 #FIXME 1032 #print self, self.start, self.end, values, self.ins[-1].get_name() 1033 # raise("ooo") 1034 if next_block != None : 1035 self.childs.append( ( self.end - self.ins[-1].get_length(), i, next_block) ) 1036 1037 for c in self.childs : 1038 if c[2] != None : 1039 c[2].set_fathers( ( c[1], c[0], self ) )
1040
1041 - def analyze(self) :
1042 idx = 0 1043 for i in self.ins : 1044 if i.get_name() in DVM_FIELDS_ACCESS : 1045 o = i.get_operands() 1046 desc = self.__vm.get_class_manager().get_field(o[-1][1], True) 1047 if desc == None : 1048 raise("oo") 1049 1050 self.__context.get_tainted_variables().push_info( TAINTED_FIELD, desc, (DVM_FIELDS_ACCESS[ i.get_name() ][0], idx, self, self.__method) ) 1051 elif "invoke" in i.get_name() : 1052 idx_meth = 0 1053 for op in i.get_operands() : 1054 if op[0] == "meth@" : 1055 idx_meth = op[1] 1056 break 1057 1058 method_info = self.__vm.get_class_manager().get_method( idx_meth ) 1059 self.__context.get_tainted_packages()._push_info( method_info[0], (TAINTED_PACKAGE_CALL, idx, self, self.__method, method_info[2], method_info[1][0] + method_info[1][1]) ) 1060 elif "new-instance" in i.get_name() : 1061 type_info = self.__vm.get_class_manager().get_type( i.get_operands()[-1][1] ) 1062 self.__context.get_tainted_packages()._push_info( type_info, (TAINTED_PACKAGE_CREATE, idx, self, self.__method) ) 1063 elif "const-string" in i.get_name() : 1064 string_name = self.__vm.get_class_manager().get_string( i.get_operands()[-1][1] ) 1065 self.__context.get_tainted_variables().add( string_name, TAINTED_STRING ) 1066 self.__context.get_tainted_variables().push_info( TAINTED_STRING, string_name, ("R", idx, self, self.__method) ) 1067 1068 idx += i.get_length()
1069
1070 - def analyze_code(self) :
1071 pass
1072
1073 - def get_ins(self) :
1074 return self.ins
1075 1076 TAINTED_LOCAL_VARIABLE = 0 1077 TAINTED_FIELD = 1 1078 TAINTED_STRING = 2
1079 -class Path :
1080 - def __init__(self, info) :
1081 self.access_flag = info[0] 1082 self.idx = info[1] 1083 self.bb = info[2] 1084 self.method = info[3]
1085
1086 - def get_access_flag(self) :
1087 return self.access_flag
1088
1089 - def get_idx(self) :
1090 return self.idx
1091
1092 - def get_bb(self) :
1093 return self.bb
1094
1095 - def get_method(self) :
1096 return self.method
1097
1098 -class TaintedVariable :
1099 - def __init__(self, var, _type) :
1100 self.var = var 1101 self.type = _type 1102 1103 self.paths = []
1104
1105 - def get_type(self) :
1106 return self.type
1107
1108 - def get_info(self) :
1109 if self.type == TAINTED_FIELD : 1110 return [ self.var.get_class_name(), self.var.get_name(), self.var.get_descriptor() ] 1111 return self.var
1112
1113 - def push(self, info) :
1114 p = Path( info ) 1115 self.paths.append( p ) 1116 return p
1117
1118 - def get_paths_access(self, mode) :
1119 for i in self.paths : 1120 if i.get_access_flag() in mode : 1121 yield i
1122
1123 - def get_paths(self) :
1124 for i in self.paths : 1125 yield i
1126
1127 - def get_paths_length(self) :
1128 return len(self.paths)
1129
1130 - def show_paths(self) :
1131 for path in self.paths : 1132 print path.get_access_flag(), path.get_method().get_class_name(), path.get_method().get_name(), path.get_method().get_descriptor(), path.get_bb().get_name(), "%x" % (path.get_bb().start + path.get_idx() )
1133
1134 -class TaintedVariables :
1135 - def __init__(self, _vm) :
1136 self.__vm = _vm 1137 self.__vars = { 1138 TAINTED_LOCAL_VARIABLE : {}, 1139 TAINTED_FIELD : {}, 1140 TAINTED_STRING : {}, 1141 } 1142 1143 self.__methods = { 1144 TAINTED_FIELD : {}, 1145 TAINTED_STRING : {}, 1146 }
1147 1148 # functions to get particulars elements 1149
1150 - def get_string(self, s) :
1151 try : 1152 return self.__vars[ TAINTED_STRING ][ s ] 1153 except KeyError : 1154 return None
1155
1156 - def get_field(self, class_name, name, descriptor) :
1157 for i in self.__vars[ TAINTED_FIELD ] : 1158 if i.get_class_name() == class_name and i.get_name() == name and i.get_descriptor() == descriptor : 1159 return self.__vars[ TAINTED_FIELD ] [i] 1160 return None
1161 1162
1163 - def get_field_by_ref(self, ref) :
1164 for i in self.__vars[ TAINTED_FIELD ] : 1165 if i.get_class_name() == ref.get_class_name() and i.get_name() == ref.get_name() and i.get_descriptor() == ref.get_descriptor() : 1166 return self.__vars[ TAINTED_FIELD ] [i] 1167 return None
1168 1169 # global functions 1170
1171 - def get_strings(self) :
1172 for i in self.__vars[ TAINTED_STRING ] : 1173 yield self.__vars[ TAINTED_STRING ][ i ], i
1174
1175 - def get_fields(self) :
1176 for i in self.__vars[ TAINTED_FIELD ] : 1177 yield self.__vars[ TAINTED_FIELD ][ i ], i
1178 1179 # specifics functions 1180
1181 - def get_strings_by_method(self, method) :
1182 try : 1183 return self.__methods[ TAINTED_STRING ][ method ] 1184 except KeyError : 1185 return {}
1186
1187 - def get_fields_by_method(self, method) :
1188 try : 1189 return self.__methods[ TAINTED_FIELD ][ method ] 1190 except KeyError : 1191 return {}
1192
1193 - def get_local_variables(self, _method) :
1194 try : 1195 return self.__vars[ TAINTED_LOCAL_VARIABLE ][ _method ] 1196 except KeyError : 1197 return None
1198
1199 - def get_fields_by_bb(self, bb) :
1200 l = [] 1201 for i in self.__vars[ TAINTED_FIELD ] : 1202 for j in self.__vars[ TAINTED_FIELD ][i].gets() : 1203 if j.get_bb() == bb : 1204 l.append( (i.get_name(), j.get_access_flag()) ) 1205 return l
1206
1207 - def add(self, var, _type, _method=None) :
1208 if _type == TAINTED_FIELD : 1209 if var not in self.__vars[ TAINTED_FIELD ] : 1210 self.__vars[ TAINTED_FIELD ][ var ] = TaintedVariable( var, _type ) 1211 elif _type == TAINTED_STRING : 1212 if var not in self.__vars[ TAINTED_STRING ] : 1213 self.__vars[ TAINTED_STRING ][ var ] = TaintedVariable( var, _type ) 1214 elif _type == TAINTED_LOCAL_VARIABLE : 1215 if _method not in self.__vars[ TAINTED_LOCAL_VARIABLE ] : 1216 self.__vars[ TAINTED_LOCAL_VARIABLE ][ _method ] = {} 1217 1218 if var not in self.__vars[ TAINTED_LOCAL_VARIABLE ][ _method ] : 1219 self.__vars[ TAINTED_LOCAL_VARIABLE ][ _method ][ var ] = TaintedVariable( var, _type ) 1220 else : 1221 raise("ooop")
1222
1223 - def push_info(self, _type, var, info) :
1224 if _type == TAINTED_FIELD or _type == TAINTED_STRING : 1225 self.add( var, _type ) 1226 p = self.__vars[ _type ][ var ].push( info ) 1227 1228 try : 1229 self.__methods[ _type ][ p.get_method() ][ var ].append( p ) 1230 except KeyError : 1231 try : 1232 self.__methods[ _type ][ p.get_method() ][ var ] = [] 1233 except KeyError : 1234 self.__methods[ _type ][ p.get_method() ] = {} 1235 self.__methods[ _type ][ p.get_method() ][ var ] = [] 1236 1237 self.__methods[ _type ][ p.get_method() ][ var ].append( p ) 1238 1239 elif _type == TAINTED_LOCAL_VARIABLE : 1240 self.add( var, _type, info[-1] ) 1241 self.__vars[ TAINTED_LOCAL_VARIABLE ][ info[-1] ][ var ].push( info ) 1242 else : 1243 raise("ooop")
1244
1245 -class PathI(Path) :
1246 - def __init__(self, info) :
1247 Path.__init__( self, info ) 1248 self.value = info[0]
1249
1250 - def get_value(self) :
1251 return self.value
1252
1253 -class TaintedInteger :
1254 - def __init__(self, info) :
1255 self.info = PathI( info )
1256
1257 - def get(self) :
1258 return self.info
1259
1260 -class TaintedIntegers :
1261 - def __init__(self, _vm) :
1262 self.__vm = _vm 1263 self.__integers = [] 1264 self.__hash = {}
1265
1266 - def get_method(self, method) :
1267 try : 1268 return self.__hash[ method ] 1269 except KeyError : 1270 return []
1271
1272 - def push_info(self, ins, info) :
1273 #print ins, ins.get_name(), ins.get_operands(), info 1274 1275 ti = TaintedInteger( info ) 1276 self.__integers.append( ti ) 1277 1278 try : 1279 self.__hash[ info[-1] ].append( ti ) 1280 except KeyError : 1281 self.__hash[ info[-1] ] = [] 1282 self.__hash[ info[-1] ].append( ti )
1283
1284 - def get_integers(self) :
1285 for i in self.__integers : 1286 yield i
1287 1288 TAINTED_PACKAGE_CREATE = 0 1289 TAINTED_PACKAGE_CALL = 1 1290 1291 TAINTED_PACKAGE = { 1292 TAINTED_PACKAGE_CREATE : "C", 1293 TAINTED_PACKAGE_CALL : "M" 1294 } 1295
1296 -def show_PathP(paths) :
1297 for path in paths : 1298 print "%s %s %s (@%s-0x%x) ---> %s %s %s" % (path.get_method().get_class_name(), path.get_method().get_name(), path.get_method().get_descriptor(), \ 1299 path.get_bb().get_name(), path.get_bb().start + path.get_idx(), \ 1300 path.get_class_name(), path.get_name(), path.get_descriptor())
1301
1302 -class PathP(Path) :
1303 - def __init__(self, info, class_name) :
1304 Path.__init__( self, info ) 1305 self.class_name = class_name 1306 if info[0] == TAINTED_PACKAGE_CALL : 1307 self.name = info[-2] 1308 self.descriptor = info[-1]
1309
1310 - def get_class_name(self) :
1311 return self.class_name
1312
1313 - def get_name(self) :
1314 return self.name
1315
1316 - def get_descriptor(self) :
1317 return self.descriptor
1318
1319 -class TaintedPackage :
1320 - def __init__(self, name) :
1321 self.name = name 1322 self.paths = { TAINTED_PACKAGE_CREATE : [], TAINTED_PACKAGE_CALL : [] }
1323
1324 - def get_name(self) :
1325 return self.name
1326 1327 # FIXME : remote it to use get_name
1328 - def get_info(self) :
1329 return self.name
1330
1331 - def gets(self) :
1332 return self.paths
1333
1334 - def push(self, info) :
1335 p = PathP( info, self.get_name() ) 1336 self.paths[ info[0] ].append( p ) 1337 return p
1338
1339 - def search_method(self, name, descriptor) :
1340 """ 1341 @param name : a regexp for the name of the method 1342 @param descriptor : a regexp for the descriptor of the method 1343 1344 @rtype : a list of called paths 1345 """ 1346 ex = re.compile( class_name ) 1347 l = [] 1348 m_name = re.compile(name) 1349 m_descriptor = re.compile(descriptor) 1350 1351 for path in self.paths[ TAINTED_PACKAGE_CALL ] : 1352 if m_name.match( path.get_name() ) != None and m_descriptor.match( path.get_descriptor() ) != None : 1353 l.append( path ) 1354 return l
1355
1356 - def get_method(self, name, descriptor) :
1357 l = [] 1358 for path in self.paths[ TAINTED_PACKAGE_CALL ] : 1359 if path.get_name() == name and path.get_descriptor() == descriptor : 1360 l.append( path ) 1361 return l
1362
1363 - def get_paths(self) :
1364 for i in self.paths : 1365 for j in self.paths[ i ] : 1366 yield j
1367
1368 - def get_paths_length(self) :
1369 x = 0 1370 for i in self.paths : 1371 x += len(self.paths[ i ]) 1372 return x
1373
1374 - def get_methods(self) :
1375 return [ path for path in self.paths[ TAINTED_PACKAGE_CALL ] ]
1376
1377 - def show(self, format) :
1378 print self.name 1379 for _type in self.paths : 1380 print "\t -->", _type 1381 if _type == TAINTED_PACKAGE_CALL : 1382 for path in sorted(self.paths[ _type ], key=lambda x: getattr(x, format)()) : 1383 print "\t\t => %s %s <-- %s@%x in %s" % (path.get_name(), path.get_descriptor(), path.get_bb().get_name(), path.get_idx(), path.get_method().get_name()) 1384 else : 1385 for path in self.paths[ _type ] : 1386 print "\t\t => %s@%x in %s" % (path.get_bb().get_name(), path.get_idx(), path.get_method().get_name())
1387
1388 -class TaintedPackages :
1389 - def __init__(self, _vm) :
1390 self.__vm = _vm 1391 self.__packages = {} 1392 self.__methods = {}
1393
1394 - def _add_pkg(self, name) :
1395 if name not in self.__packages : 1396 self.__packages[ name ] = TaintedPackage( name )
1397
1398 - def _push_info(self, class_name, info) :
1399 self._add_pkg( class_name ) 1400 p = self.__packages[ class_name ].push( info ) 1401 1402 try : 1403 self.__methods[ p.get_method() ][ class_name ].append( p ) 1404 except : 1405 try : 1406 self.__methods[ p.get_method() ][ class_name ] = [] 1407 except : 1408 self.__methods[ p.get_method() ] = {} 1409 self.__methods[ p.get_method() ][ class_name ] = [] 1410 1411 self.__methods[ p.get_method() ][ class_name ].append( p )
1412
1413 - def get_packages_by_method(self, method) :
1414 try : 1415 return self.__methods[ method ] 1416 except KeyError : 1417 return {}
1418
1419 - def get_packages_by_bb(self, bb):
1420 """ 1421 @rtype : return a list of packaged used in a basic block 1422 """ 1423 l = [] 1424 for i in self.__packages : 1425 paths = self.__packages[i].gets() 1426 for j in paths : 1427 for k in paths[j] : 1428 if k.get_bb() == bb : 1429 l.append( (i, k.get_access_flag(), k.get_idx(), k.get_method()) ) 1430 1431 return l
1432
1433 - def get_packages(self) :
1434 for i in self.__packages : 1435 yield self.__packages[ i ], i
1436
1437 - def get_internal_packages(self) :
1438 """ 1439 @rtype : return a list of the internal packages called in the application 1440 """ 1441 classes = self.__vm.get_classes_names() 1442 l = [] 1443 for m, _ in self.get_packages() : 1444 paths = m.get_methods() 1445 for j in paths : 1446 if j.get_method().get_class_name() in classes and m.get_info() in classes : 1447 if j.get_access_flag() == TAINTED_PACKAGE_CALL : 1448 l.append( j ) 1449 return l
1450
1451 - def get_external_packages(self) :
1452 """ 1453 @rtype : return a list of the external packages called in the application 1454 """ 1455 classes = self.__vm.get_classes_names() 1456 l = [] 1457 for m, _ in self.get_packages() : 1458 paths = m.get_methods() 1459 for j in paths : 1460 if j.get_method().get_class_name() in classes and m.get_info() not in classes : 1461 if j.get_access_flag() == TAINTED_PACKAGE_CALL : 1462 l.append( j ) 1463 return l
1464
1465 - def search_packages(self, package_name) :
1466 """ 1467 @param package_name : a regexp for the name of the package 1468 1469 @rtype : a list of called packages' paths 1470 """ 1471 ex = re.compile( package_name ) 1472 1473 l = [] 1474 for m, _ in self.get_packages() : 1475 if ex.match( m.get_info() ) != None : 1476 l.extend( m.get_methods() ) 1477 return l
1478
1479 - def search_methods(self, class_name, name, descriptor) :
1480 """ 1481 @param class_name : a regexp for the class name of the method (the package) 1482 @param name : a regexp for the name of the method 1483 @param descriptor : a regexp for the descriptor of the method 1484 1485 @rtype : a list of called methods' paths 1486 """ 1487 ex = re.compile( class_name ) 1488 l = [] 1489 1490 for m, _ in self.get_packages() : 1491 if ex.match( m.get_info() ) != None : 1492 l.extend( m.search_method( name, descriptor ) ) 1493 return l
1494
1495 - def search_crypto_packages(self) :
1496 """ 1497 @rtype : a list of called crypto packages 1498 """ 1499 return self.search_packages( "Ljavax/crypto/" )
1500
1501 - def search_telephony_packages(self) :
1502 """ 1503 @rtype : a list of called telephony packages 1504 """ 1505 return self.search_packages( "Landroid/telephony/" )
1506
1507 - def search_net_packages(self) :
1508 """ 1509 @rtype : a list of called net packages 1510 """ 1511 return self.search_packages( "Landroid/net/" )
1512
1513 - def get_method(self, class_name, name, descriptor) :
1514 try : 1515 return self.__packages[ class_name ].get_method( name, descriptor ) 1516 except KeyError : 1517 return []
1518
1519 - def get_permissions(self, permissions_needed) :
1520 """ 1521 @param permissions_needed : a list of restricted permissions to get ([] returns all permissions) 1522 1523 @rtype : a dictionnary of permissions' paths 1524 """ 1525 permissions = {} 1526 1527 pn = permissions_needed 1528 if permissions_needed == [] : 1529 pn = DVM_PERMISSIONS_BY_PERMISSION.keys() 1530 1531 classes = self.__vm.get_classes_names() 1532 1533 for m, _ in self.get_packages() : 1534 paths = m.get_methods() 1535 for j in paths : 1536 if j.get_method().get_class_name() in classes and m.get_info() not in classes : 1537 if j.get_access_flag() == TAINTED_PACKAGE_CALL : 1538 data = "%s-%s-%s" % (m.get_info(), j.get_name(), j.get_descriptor()) 1539 if data in DVM_PERMISSIONS_BY_ELEMENT : 1540 if DVM_PERMISSIONS_BY_ELEMENT[ data ] in pn : 1541 try : 1542 permissions[ DVM_PERMISSIONS_BY_ELEMENT[ data ] ].append( j ) 1543 except KeyError : 1544 permissions[ DVM_PERMISSIONS_BY_ELEMENT[ data ] ] = [] 1545 permissions[ DVM_PERMISSIONS_BY_ELEMENT[ data ] ].append( j ) 1546 1547 return permissions
1548
1549 -class BasicBlocks :
1550 - def __init__(self, _vm, _tv) :
1551 self.__vm = _vm 1552 self.__tainted = _tv 1553 1554 self.bb = []
1555
1556 - def push(self, bb):
1557 self.bb.append( bb )
1558
1559 - def pop(self, idx) :
1560 return self.bb.pop( idx )
1561
1562 - def get_basic_block(self, idx) :
1563 for i in self.bb : 1564 if idx >= i.get_start() and idx < i.get_end() : 1565 return i 1566 return None
1567
1568 - def get_tainted_integers(self) :
1569 return self.__tainted["integers"]
1570
1571 - def get_tainted_packages(self) :
1572 return self.__tainted["packages"]
1573
1574 - def get_tainted_variables(self) :
1575 return self.__tainted["variables"]
1576
1577 - def get_random(self) :
1578 """ 1579 @rtype : return a random basic block 1580 """ 1581 return self.bb[ random.randint(0, len(self.bb) - 1) ]
1582
1583 - def get(self) :
1584 """ 1585 @rtype : return each basic block 1586 """ 1587 for i in self.bb : 1588 yield i
1589
1590 - def gets(self) :
1591 """ 1592 @rtype : a list of basic blocks 1593 """ 1594 return self.bb
1595
1596 -class MethodAnalysis :
1597 """ 1598 This class analyses in details a method of a class/dex file 1599 """
1600 - def __init__(self, _vm, _method, _tv, code_analysis=False) :
1601 """ 1602 @param _vm : a L{JVMFormat} or L{DalvikVMFormat} object 1603 @param _method : a method object 1604 @param tv : a dictionnary of tainted information 1605 """ 1606 self.__vm = _vm 1607 self.__method = _method 1608 1609 self.__tainted = _tv 1610 1611 BO = { "BasicOPCODES" : jvm.BRANCH2_JVM_OPCODES, "BasicClass" : JVMBasicBlock, "Dnext" : jvm.determineNext, 1612 "TS" : JVM_TOSTRING } 1613 if self.__vm.get_type() == "DVM" : 1614 BO = { "BasicOPCODES" : dvm.BRANCH_DVM_OPCODES, "BasicClass" : DVMBasicBlock, "Dnext" : dvm.determineNext, 1615 "TS" : DVM_TOSTRING } 1616 1617 self.__TS = ToString( BO[ "TS" ] ) 1618 1619 BO["BasicOPCODES_H"] = [] 1620 for i in BO["BasicOPCODES"] : 1621 BO["BasicOPCODES_H"].append( re.compile( i ) ) 1622 1623 self.basic_blocks = BasicBlocks( self.__vm, self.__tainted ) 1624 1625 code = self.__method.get_code() 1626 if code == None : 1627 return 1628 1629 current_basic = BO["BasicClass"]( 0, self.__vm, self.__method, self.basic_blocks ) 1630 self.basic_blocks.push( current_basic ) 1631 1632 ########################################################## 1633 1634 bc = code.get_bc() 1635 l = [] 1636 h = {} 1637 idx = 0 1638 for i in bc.get() : 1639 for j in BO["BasicOPCODES_H"] : 1640 if j.match(i.get_name()) != None : 1641 v = BO["Dnext"]( i, idx, self.__method ) 1642 h[ idx ] = v 1643 l.extend( v ) 1644 break 1645 1646 idx += i.get_length() 1647 1648 # print self.__method.get_name(), sorted(l), h 1649 idx = 0 1650 for i in bc.get() : 1651 name = i.get_name() 1652 1653 self.__TS.push( name ) 1654 1655 here = False 1656 # index is a destination 1657 if idx in l : 1658 if current_basic.ins != [] : 1659 current_basic = BO["BasicClass"]( current_basic.get_end(), self.__vm, self.__method, self.basic_blocks ) 1660 self.basic_blocks.push( current_basic ) 1661 here = True 1662 1663 current_basic.push( i ) 1664 1665 # index is a branch instruction 1666 if idx in h : #and here == False : 1667 current_basic = BO["BasicClass"]( current_basic.get_end(), self.__vm, self.__method, self.basic_blocks ) 1668 self.basic_blocks.push( current_basic ) 1669 1670 idx += i.get_length() 1671 1672 1673 if current_basic.ins == [] : 1674 self.basic_blocks.pop( -1 ) 1675 1676 for i in self.basic_blocks.get() : 1677 try : 1678 i.set_childs( h[ i.end - i.ins[-1].get_length() ] ) 1679 except KeyError : 1680 i.set_childs( [] ) 1681 1682 1683 for i in self.basic_blocks.get() : 1684 i.analyze() 1685 1686 if code_analysis == True : 1687 for i in self.basic_blocks.get() : 1688 i.analyze_code()
1689
1690 - def get_length(self) :
1691 """ 1692 @rtype : an integer which is the length of the code 1693 """ 1694 return self.get_code().get_length()
1695
1696 - def prev_free_block_offset(self, idx=0) :
1697 l = [] 1698 for i in self.basic_blocks.get() : 1699 if i.get_start() <= idx : 1700 l.append( i ) 1701 1702 l.reverse() 1703 for i in l : 1704 x = i.prev_free_block_offset( idx ) 1705 if x != -1 : 1706 return x 1707 return -1
1708
1709 - def random_free_block_offset(self) :
1710 b = self.basic_blocks.get_random() 1711 x = b.random_free_block_offset() 1712 return x
1713
1714 - def next_free_block_offset(self, idx=0) :
1715 for i in self.basic_blocks.get() : 1716 x = i.next_free_block_offset( idx ) 1717 if x != -1 : 1718 return x 1719 return -1
1720
1721 - def get_break_block(self, idx) :
1722 for i in self.basic_blocks.get() : 1723 if idx >= i.get_start() and idx <= i.get_end() : 1724 return i.get_break_block( idx ) 1725 return None
1726
1727 - def get_ts(self) :
1728 return self.__TS.get_string()
1729
1730 - def get_vm(self) :
1731 return self.__vm
1732
1733 - def get_method(self) :
1734 return self.__method
1735
1736 - def get_op(self, op) :
1737 return []
1738
1739 - def get_local_variables(self) :
1740 return self.__tainted["variables"].get_local_variables( self.__method )
1741
1742 - def get_ops(self) :
1743 l = [] 1744 for i in self.__bb : 1745 for j in i.get_ops() : 1746 l.append( j ) 1747 return l
1748
1749 - def show(self) :
1750 print "METHOD", self.__method.get_class_name(), self.__method.get_name(), self.__method.get_descriptor() 1751 print "\tTOSTRING = ", self.__TS.get_string() 1752 1753 for i in self.basic_blocks.get() : 1754 print "\t", i 1755 i.show() 1756 print ""
1757
1758 - def show_methods(self) :
1759 print "\t #METHODS :" 1760 l = [] 1761 for i in self.__bb : 1762 methods = i.get_methods() 1763 for method in methods : 1764 print "\t\t-->", method.get_class_name(), method.get_name(), method.get_descriptor() 1765 for context in methods[method] : 1766 print "\t\t\t |---|", context.details
1767 1768 SIGNATURE_L0_0 = "L0_0" 1769 SIGNATURE_L0_1 = "L0_1" 1770 SIGNATURE_L0_2 = "L0_2" 1771 SIGNATURE_L0_3 = "L0_3" 1772 SIGNATURE_L0_4 = "L0_4" 1773 SIGNATURE_L0_5 = "L0_5" 1774 SIGNATURE_L0_6 = "L0_6" 1775 SIGNATURE_L0_0_L1 = "L0_0:L1" 1776 SIGNATURE_L0_1_L1 = "L0_1:L1" 1777 SIGNATURE_L0_2_L1 = "L0_2:L1" 1778 SIGNATURE_L0_3_L1 = "L0_3:L1" 1779 SIGNATURE_L0_4_L1 = "L0_4:L1" 1780 SIGNATURE_L0_5_L1 = "L0_5:L1" 1781 SIGNATURE_L0_0_L2 = "L0_0:L2" 1782 SIGNATURE_L0_0_L3 = "L0_0:L3" 1783 1784 SIGNATURES = { 1785 SIGNATURE_L0_0 : { "type" : 0 }, 1786 SIGNATURE_L0_1 : { "type" : 1 }, 1787 SIGNATURE_L0_2 : { "type" : 2, "arguments" : ["Landroid"] }, 1788 SIGNATURE_L0_3 : { "type" : 2, "arguments" : ["Ljava"] }, 1789 SIGNATURE_L0_4 : { "type" : 2, "arguments" : ["Landroid", "Ljava"] }, 1790 SIGNATURE_L0_5 : { "type" : 3, "arguments" : ["Landroid"] }, 1791 SIGNATURE_L0_6 : { "type" : 3, "arguments" : ["Ljava"] }, 1792 } 1793 1794 from sign import Signature 1795
1796 -class VMAnalysis :
1797 """ 1798 This class analyses a class file or a dex file 1799 1800 @param _vm : a virtual machine object 1801 """
1802 - def __init__(self, _vm, code_analysis=False) :
1803 """ 1804 @param _vm : a L{JVMFormat} or L{DalvikFormatVM} 1805 @param code_analysis : True if you would like to do an advanced analyse of the code (e.g : to search free offset to insert codes 1806 """ 1807 1808 self.__vm = _vm 1809 1810 self.tainted_variables = TaintedVariables( self.__vm ) 1811 self.tainted_packages = TaintedPackages( self.__vm ) 1812 self.tainted_integers = TaintedIntegers( self.__vm ) 1813 1814 self.tainted = { "variables" : self.tainted_variables, 1815 "packages" : self.tainted_packages, 1816 "integers" : self.tainted_integers, 1817 } 1818 1819 self.signature = Signature( self.tainted ) 1820 1821 for i in self.__vm.get_all_fields() : 1822 self.tainted_variables.add( i, TAINTED_FIELD ) 1823 1824 self.methods = [] 1825 self.hmethods = {} 1826 self.__nmethods = {} 1827 for i in self.__vm.get_methods() : 1828 x = MethodAnalysis( self.__vm, i, self.tainted, code_analysis ) 1829 self.methods.append( x ) 1830 self.hmethods[ i ] = x 1831 self.__nmethods[ i.get_name() ] = x
1832
1833 - def get_method(self, method) :
1834 """ 1835 Return an analysis method 1836 1837 @param method : a classical method object 1838 @rtype : L{MethodAnalysis} 1839 """ 1840 return self.hmethods[ method ]
1841 1842 # FIXME
1843 - def get_like_field(self) :
1844 return [ random.choice( string.letters ) + ''.join([ random.choice(string.letters + string.digits) for i in range(10 - 1) ]), 1845 "ACC_PUBLIC", 1846 "I" 1847 ]
1848 1849 # FIXME
1850 - def get_init_method(self) :
1851 m = self.__vm.get_method("<init>") 1852 return m[0]
1853 1854 # FIXME
1855 - def get_random_integer_value(self, method, descriptor) :
1856 return 0
1857
1858 - def prev_free_block_offset(self, method, idx=0) :
1859 """ 1860 Find the previous offset where you can insert a block 1861 1862 @param method : a reference of a method object where you would like the offset 1863 @param idx : the index to start the research 1864 1865 @rtype : return -1 if an error occured, otherwise the offset 1866 """ 1867 # We would like a specific free offset in a method 1868 try : 1869 return self.hmethods[ method ].prev_free_block_offset( idx ) 1870 except KeyError : 1871 # We haven't found the method ... 1872 return -1
1873
1874 - def random_free_block_offset(self, method) :
1875 """ 1876 Find a random offset where you can insert a block 1877 1878 @param method : a reference of method object or a string which represents a regexp 1879 1880 @rtype : return -1 if an error occured, otherwise the offset 1881 """ 1882 if isinstance(method, str) : 1883 p = re.compile(method) 1884 for i in self.hmethods : 1885 if random.randint(0, 1) == 1 : 1886 if p.match( i.get_name() ) == None : 1887 return i, self.hmethods[i].random_free_block_offset() 1888 1889 for i in self.hmethods : 1890 if p.match( i.get_name() ) == None : 1891 return i, self.hmethods[i].random_free_block_offset() 1892 1893 # We would like a specific free offset in a method 1894 try : 1895 return self.hmethods[ method ].random_free_block_offset() 1896 except KeyError : 1897 # We haven't found the method ... 1898 return -1
1899
1900 - def next_free_block_offset(self, method, idx=0) :
1901 """ 1902 Find the next offset where you can insert a block 1903 1904 @param method : a reference of a method object where you would like the offset 1905 @param idx : the index to start the research 1906 1907 @rtype : return -1 if an error occured, otherwise the offset 1908 """ 1909 # We would like a specific free offset in a method 1910 try : 1911 return self.hmethods[ method ].next_free_block_offset( idx ) 1912 except KeyError : 1913 # We haven't found the method ... 1914 return -1
1915
1916 - def get_tainted_variables(self) :
1917 """ 1918 Return the tainted variables 1919 1920 @rtype : L{TaintedVariables} 1921 """ 1922 return self.tainted_variables
1923
1924 - def get_tainted_packages(self) :
1925 """ 1926 Return the tainted packages 1927 1928 @rtype : L{TaintedPackages} 1929 """ 1930 return self.tainted_packages
1931
1932 - def get_tainted_field(self, class_name, name, descriptor) :
1933 """ 1934 Return a specific tainted field 1935 1936 @param class_name : the name of the class 1937 @param name : the name of the field 1938 @param descriptor : the descriptor of the field 1939 1940 @rtype : L{TaintedVariable} 1941 """ 1942 return self.tainted_variables.get_field( class_name, name, descriptor )
1943
1944 - def get_methods(self) :
1945 """ 1946 Return each analysis method 1947 1948 @rtype : L{MethodAnalysis} 1949 """ 1950 for i in self.hmethods : 1951 yield self.hmethods[i]
1952
1953 - def get_method_signature(self, method, grammar_type="", options={}, predef_sign="") :
1954 """ 1955 Return a specific signature for a specific method 1956 1957 @param method : a reference to method from a vm class 1958 @param grammar_type : the type of the signature 1959 @param options : the options of the signature 1960 @param predef_sign : used a predefined signature 1961 1962 @rtype : L{Sign} 1963 """ 1964 if predef_sign != "" : 1965 g = "" 1966 o = {} 1967 1968 for i in predef_sign.split(":") : 1969 if "_" in i : 1970 g += "L0:" 1971 o[ "L0" ] = SIGNATURES[ i ] 1972 else : 1973 g += i 1974 g += ":" 1975 1976 return self.signature.get_method( self.get_method( method ), g[:-1], o ) 1977 else : 1978 return self.signature.get_method( self.get_method( method ), grammar_type, options )
1979 1980 1981 # FIXME
1982 - def get_op(self, op) :
1983 return [ (i.get_method(), i.get_op(op)) for i in self.l ]
1984 1985 # FIXME
1986 - def get_ops(self, method) :
1987 return [ (i.get_method(), i.get_ops()) for i in self.l ]
1988