mirror of
https://github.com/androguard/androguard.git
synced 2024-11-30 08:20:32 +00:00
Remove unused bitrotted code
This commit is contained in:
parent
78bafe6ace
commit
e51ec266dc
146
androdump.py
146
androdump.py
@ -1,146 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# This file is part of Androguard.
|
||||
#
|
||||
# Copyright (C) 2012, Anthony Desnos <desnos at t0t0.fr>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Androguard is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Lesser General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Androguard is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU Lesser General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU Lesser General Public License
|
||||
# along with Androguard. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import sys, os, cmd, threading, re, atexit
|
||||
|
||||
from optparse import OptionParser
|
||||
|
||||
import androguard, androconf, jvm
|
||||
|
||||
# External Libraries
|
||||
|
||||
# python-ptrace : http://bitbucket.org/haypo/python-ptrace/
|
||||
from ptrace import PtraceError
|
||||
from ptrace.tools import locateProgram
|
||||
from ptrace.debugger import ProcessExit, DebuggerError, PtraceDebugger, ProcessExit, ProcessSignal, NewProcessEvent, ProcessExecution
|
||||
from ptrace.debugger.memory_mapping import readProcessMappings
|
||||
####################
|
||||
|
||||
option_0 = { 'name' : ('-i', '--input'), 'help' : 'pid', 'nargs' : 1 }
|
||||
|
||||
option_1 = { 'name' : ('-v', '--version'), 'help' : 'version of the API', 'action' : 'count' }
|
||||
|
||||
options = [option_0, option_1]
|
||||
|
||||
MAGIC_PATTERN = "\xca\xfe\xba\xbe"
|
||||
|
||||
class AndroPreDump(object):
|
||||
def __init__(self, input):
|
||||
self.data = []
|
||||
|
||||
self.pid = int(input)
|
||||
self.debugger = PtraceDebugger()
|
||||
self.process = self.debugger.addProcess(self.pid, is_attached=False)
|
||||
atexit.register(self.debugger.quit)
|
||||
|
||||
Header = False
|
||||
Code = False
|
||||
|
||||
self.procmaps = readProcessMappings(self.process)
|
||||
for pm in self.procmaps:
|
||||
if pm.permissions.find("w") != -1 and pm.pathname == None:
|
||||
# if Code == False and Header == True:
|
||||
# data = self.process.readBytes(pm.start, pm.end-pm.start)
|
||||
# idx = data.find("SourceFile")
|
||||
# if idx != -1:
|
||||
# print "CODE", pm
|
||||
# self.data.append( (pm, data, idx) )
|
||||
# Code = True
|
||||
|
||||
if Header == False:
|
||||
data = self.process.readBytes(pm.start, pm.end-pm.start)
|
||||
idx = data.find(MAGIC_PATTERN)
|
||||
if idx != -1:
|
||||
print "HEADER", pm
|
||||
self.data.append( (pm, data) )
|
||||
Header = True
|
||||
|
||||
self.dumpMemory( "java_dump_memory" )
|
||||
# self.dumpFiles( "java_files" )
|
||||
|
||||
def write(self, idx, buff):
|
||||
self.process.writeBytes( idx, buff )
|
||||
|
||||
def getFilesBuffer(self):
|
||||
for i in self.data:
|
||||
d = i[1]
|
||||
x = d.find(MAGIC_PATTERN)
|
||||
idx = x
|
||||
while x != -1:
|
||||
yield i[0].start + idx, d[x:]
|
||||
d = d[x+len(MAGIC_PATTERN):]
|
||||
|
||||
idx += len(MAGIC_PATTERN)
|
||||
x = d.find(MAGIC_PATTERN)
|
||||
idx += x
|
||||
|
||||
def dumpMemory(self, base_filename):
|
||||
for i in self.data:
|
||||
with open(base_filename + "-" + "0x%x-0x%x" % (i[0].start, i[0].end), "w") as fd:
|
||||
fd.write( i[1] )
|
||||
|
||||
def dumpFiles(self, base_filename):
|
||||
for i in self.data:
|
||||
with fd = open(base_filename + "-" + "0x%x-0x%x" % (i[0].start + i[2], i[0].end), "w") as fd:
|
||||
fd.write( i[1][i[2]:] )
|
||||
|
||||
class AndroDump(object):
|
||||
def __init__(self, adp):
|
||||
self.__adp = adp
|
||||
|
||||
for i in self.__adp.getFilesBuffer():
|
||||
try:
|
||||
print "0x%x :" % (i[0])
|
||||
j = jvm.JVMFormat( i[1] )
|
||||
|
||||
for method in j.get_methods():
|
||||
print "\t -->", method.get_class_name(), method.get_name(), method.get_descriptor()
|
||||
|
||||
# if (method.get_class_name() == "Test2" and method.get_name() == "main"):
|
||||
# print "patch"
|
||||
|
||||
# code = method.get_code()
|
||||
#code.remplace_at( 51, [ "bipush", 20 ] )
|
||||
# code.show()
|
||||
|
||||
# print "\t\t-> %x" % (len(j.save()))
|
||||
|
||||
# self.__adp.write( i[0], j.save() )
|
||||
except Exception, e:
|
||||
print e
|
||||
|
||||
def main(options, arguments):
|
||||
if options.input != None:
|
||||
apd = AndroPreDump( options.input )
|
||||
AndroDump( apd )
|
||||
|
||||
elif options.version != None:
|
||||
print "Androdump version %s" % androconf.ANDROGUARD_VERSION
|
||||
|
||||
if __name__ == "__main__":
|
||||
parser = OptionParser()
|
||||
for option in options:
|
||||
param = option['name']
|
||||
del option['name']
|
||||
parser.add_option(*param, **option)
|
||||
|
||||
options, arguments = parser.parse_args()
|
||||
sys.argv[:] = arguments
|
||||
main(options, arguments)
|
@ -18,7 +18,7 @@
|
||||
import re, random, string, cPickle
|
||||
|
||||
from androguard.core.androconf import error, warning, debug, is_ascii_problem
|
||||
from androguard.core.bytecodes import jvm, dvm
|
||||
from androguard.core.bytecodes import dvm
|
||||
from androguard.core.bytecodes.api_permissions import DVM_PERMISSIONS_BY_PERMISSION, DVM_PERMISSIONS_BY_ELEMENT
|
||||
from androguard.util import read
|
||||
|
||||
@ -116,812 +116,6 @@ class BreakBlock(object):
|
||||
print "\t\t",
|
||||
i.show(0)
|
||||
|
||||
##### JVM ######
|
||||
FIELDS = {
|
||||
"getfield" : "R",
|
||||
"getstatic" : "R",
|
||||
"putfield" : "W",
|
||||
"putstatic" : "W",
|
||||
}
|
||||
|
||||
METHODS = [ "invokestatic", "invokevirtual", "invokespecial" ]
|
||||
|
||||
JVM_TOSTRING = { "O" : jvm.MATH_JVM_OPCODES.keys(),
|
||||
"I" : jvm.INVOKE_JVM_OPCODES,
|
||||
"G" : jvm.FIELD_READ_JVM_OPCODES,
|
||||
"P" : jvm.FIELD_WRITE_JVM_OPCODES,
|
||||
}
|
||||
|
||||
BREAK_JVM_OPCODES_RE = []
|
||||
for i in jvm.BREAK_JVM_OPCODES:
|
||||
BREAK_JVM_OPCODES_RE.append( re.compile( i ) )
|
||||
|
||||
class Stack(object):
|
||||
def __init__(self):
|
||||
self.__elems = []
|
||||
|
||||
def gets(self):
|
||||
return self.__elems
|
||||
|
||||
def push(self, elem):
|
||||
self.__elems.append( elem )
|
||||
|
||||
def get(self):
|
||||
return self.__elems[-1]
|
||||
|
||||
def pop(self):
|
||||
return self.__elems.pop(-1)
|
||||
|
||||
def nil(self):
|
||||
return len(self.__elems) == 0
|
||||
|
||||
def insert_stack(self, idx, elems):
|
||||
if elems != self.__elems:
|
||||
for i in elems:
|
||||
self.__elems.insert(idx, i)
|
||||
idx += 1
|
||||
|
||||
def show(self):
|
||||
nb = 0
|
||||
|
||||
if len(self.__elems) == 0:
|
||||
print "\t--> nil"
|
||||
|
||||
for i in self.__elems:
|
||||
print "\t-->", nb, ": ", i
|
||||
nb += 1
|
||||
|
||||
class StackTraces(object):
|
||||
def __init__(self):
|
||||
self.__elems = []
|
||||
|
||||
def save(self, idx, i_idx, ins, stack_pickle, msg_pickle):
|
||||
self.__elems.append( (idx, i_idx, ins, stack_pickle, msg_pickle) )
|
||||
|
||||
def get(self):
|
||||
for i in self.__elems:
|
||||
yield (i[0], i[1], i[2], cPickle.loads( i[3] ), cPickle.loads( i[4] ) )
|
||||
|
||||
def show(self):
|
||||
for i in self.__elems:
|
||||
print i[0], i[1], i[2].get_name()
|
||||
|
||||
cPickle.loads( i[3] ).show()
|
||||
print "\t", cPickle.loads( i[4] )
|
||||
|
||||
def push_objectref(_vm, ins, special, stack, res, ret_v):
|
||||
value = "OBJ_REF_@_%s" % str(special)
|
||||
stack.push( value )
|
||||
|
||||
def push_objectref_l(_vm, ins, special, stack, res, ret_v):
|
||||
stack.push( "VARIABLE_LOCAL_%d" % special )
|
||||
|
||||
def push_objectref_l_i(_vm, ins, special, stack, res, ret_v):
|
||||
stack.push( "VARIABLE_LOCAL_%d" % ins.get_operands() )
|
||||
|
||||
def pop_objectref(_vm, ins, special, stack, res, ret_v):
|
||||
ret_v.add_return( stack.pop() )
|
||||
|
||||
def multi_pop_objectref_i(_vm, ins, special, stack, res, ret_v):
|
||||
for i in range(0, ins.get_operands()[1]):
|
||||
stack.pop()
|
||||
|
||||
def push_objectres(_vm, ins, special, stack, res, ret_v):
|
||||
value = ""
|
||||
|
||||
if special[0] == 1:
|
||||
value += special[1] + "(" + str( res.pop() ) + ") "
|
||||
else:
|
||||
for i in range(0, special[0]):
|
||||
value += str( res.pop() ) + special[1]
|
||||
|
||||
value = value[:-1]
|
||||
|
||||
stack.push( value )
|
||||
|
||||
def push_integer_i(_vm, ins, special, stack, res, ret_v):
|
||||
value = ins.get_operands()
|
||||
stack.push( value )
|
||||
|
||||
def push_integer_d(_vm, ins, special, stack, res, ret_v):
|
||||
stack.push( special )
|
||||
|
||||
def push_float_d(_vm, ins, special, stack, res, ret_v):
|
||||
stack.push( special )
|
||||
|
||||
def putfield(_vm, ins, special, stack, res, ret_v):
|
||||
ret_v.add_return( stack.pop() )
|
||||
|
||||
def putstatic(_vm, ins, special, stack, res, ret_v):
|
||||
stack.pop()
|
||||
|
||||
def getfield(_vm, ins, special, stack, res, ret_v):
|
||||
ret_v.add_return( stack.pop() )
|
||||
stack.push( "FIELD" )
|
||||
|
||||
def getstatic(_vm, ins, special, stack, res, ret_v):
|
||||
stack.push( "FIELD_STATIC" )
|
||||
|
||||
def new(_vm, ins, special, stack, res, ret_v):
|
||||
stack.push( "NEW_OBJ" )
|
||||
|
||||
def dup(_vm, ins, special, stack, res, ret_v):
|
||||
l = []
|
||||
|
||||
for i in range(0, special+1):
|
||||
l.append( stack.pop() )
|
||||
l.reverse()
|
||||
|
||||
l.insert( 0, l[-1] )
|
||||
for i in l:
|
||||
stack.push( i )
|
||||
|
||||
def dup2(_vm, ins, special, stack, res, ret_v):
|
||||
l = []
|
||||
|
||||
for i in range(0, special+1):
|
||||
l.append( stack.pop() )
|
||||
l.reverse()
|
||||
|
||||
l.insert( 0, l[-1] )
|
||||
l.insert( 1, l[-2] )
|
||||
for i in l:
|
||||
stack.push( i )
|
||||
|
||||
#FIXME
|
||||
def ldc(_vm, ins, special, stack, res, ret_v):
|
||||
#print ins.get_name(), ins.get_operands(), special
|
||||
stack.push( "STRING" )
|
||||
|
||||
def invoke(_vm, ins, special, stack, res, ret_v):
|
||||
desc = ins.get_operands()[-1]
|
||||
param = desc[1:desc.find(")")]
|
||||
ret = desc[desc.find(")")+1:]
|
||||
|
||||
# print "DESC --->", param, calc_nb( param ), ret, calc_nb( ret )
|
||||
|
||||
for i in range(0, calc_nb( param )):
|
||||
stack.pop()
|
||||
|
||||
# objectref : static or not
|
||||
for i in range(0, special):
|
||||
stack.pop()
|
||||
|
||||
for i in range(0, calc_nb( ret )):
|
||||
stack.push( "E" )
|
||||
|
||||
def set_arrayref(_vm, ins, special, stack, res, ret_v):
|
||||
ret_v.add_msg( "SET VALUE %s %s @ ARRAY REF %s %s" % (special, str(stack.pop()), str(stack.pop()), str(stack.pop())) )
|
||||
|
||||
def set_objectref(_vm, ins, special, stack, res, ret_v):
|
||||
ret_v.add_msg( "SET OBJECT REF %d --> %s" % (special, str(stack.pop())) )
|
||||
|
||||
def set_objectref_i(_vm, ins, special, stack, res, ret_v):
|
||||
ret_v.add_msg( "SET OBJECT REF %d --> %s" % (ins.get_operands(), str(stack.pop())) )
|
||||
|
||||
def swap(_vm, ins, special, stack, res, ret_v):
|
||||
l = stack.pop()
|
||||
l2 = stack.pop()
|
||||
|
||||
stack.push(l2)
|
||||
stack.push(l)
|
||||
|
||||
def calc_nb(info):
|
||||
if info == "" or info == "V":
|
||||
return 0
|
||||
|
||||
if ";" in info:
|
||||
n = 0
|
||||
for i in info.split(";"):
|
||||
if i != "":
|
||||
n += 1
|
||||
return n
|
||||
else:
|
||||
return len(info) - info.count('[')
|
||||
|
||||
INSTRUCTIONS_ACTIONS = {
|
||||
"aaload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"aastore" : [ { set_arrayref : None } ],
|
||||
"aconst_null" : [ { push_objectref : "null" } ],
|
||||
"aload" : [ { push_objectref_l_i : None } ],
|
||||
"aload_0" : [ { push_objectref_l : 0 } ],
|
||||
"aload_1" : [ { push_objectref_l : 1 } ],
|
||||
"aload_2" : [ { push_objectref_l : 2 } ],
|
||||
"aload_3" : [ { push_objectref_l : 3 } ],
|
||||
"anewarray" : [ { pop_objectref : None }, { push_objectref : [ 1, "ANEWARRAY" ] } ],
|
||||
"areturn" : [ { pop_objectref : None } ],
|
||||
"arraylength" : [ { pop_objectref : None }, { push_objectres : [ 1, 'LENGTH' ] } ],
|
||||
"astore" : [ { set_objectref_i : None } ],
|
||||
"astore_0" : [ { set_objectref : 0 } ],
|
||||
"astore_1" : [ { set_objectref : 1 } ],
|
||||
"astore_2" : [ { set_objectref : 2 } ],
|
||||
"astore_3" : [ { set_objectref : 3 } ],
|
||||
"athrow" : [ { pop_objectref : None }, { push_objectres : [ 1, "throw" ] } ],
|
||||
"baload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"bastore" : [ { set_arrayref : "byte" } ],
|
||||
"bipush" : [ { push_integer_i : None } ],
|
||||
"caload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"castore" : [ { set_arrayref : "char" } ],
|
||||
"checkcast" : [ { pop_objectref : None }, { push_objectres : [ 1, "checkcast" ] } ],
|
||||
"d2f" : [ { pop_objectref : None }, { push_objectres : [ 1, 'float' ] } ],
|
||||
"d2i" : [ { pop_objectref : None }, { push_objectres : [ 1, 'integer' ] } ],
|
||||
"d2l" : [ { pop_objectref : None }, { push_objectres : [ 1, 'long' ] } ],
|
||||
"dadd" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '+' ] } ],
|
||||
"daload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"dastore" : [ { set_arrayref : "double" } ],
|
||||
"dcmpg" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"dcmpl" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"dconst_0" : [ { push_float_d : 0.0 } ],
|
||||
"dconst_1" : [ { push_float_d : 1.0 } ],
|
||||
"ddiv" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '&' ] } ],
|
||||
"dload" : [ { push_objectref_l_i : None } ],
|
||||
"dload_0" : [ { push_objectref_l : 0 } ],
|
||||
"dload_1" : [ { push_objectref_l : 1 } ],
|
||||
"dload_2" : [ { push_objectref_l : 2 } ],
|
||||
"dload_3" : [ { push_objectref_l : 3 } ],
|
||||
"dmul" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '*' ] } ],
|
||||
"dneg" : [ { pop_objectref : None }, { push_objectres : [ 1, '-' ] } ],
|
||||
"drem" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, 'rem' ] } ],
|
||||
"dreturn" : [ { pop_objectref : None } ],
|
||||
"dstore" : [ { set_objectref_i : None } ],
|
||||
"dstore_0" : [ { set_objectref : 0 } ],
|
||||
"dstore_1" : [ { set_objectref : 1 } ],
|
||||
"dstore_2" : [ { set_objectref : 2 } ],
|
||||
"dstore_3" : [ { set_objectref : 3 } ],
|
||||
"dsub" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '-' ] } ],
|
||||
"dup" : [ { dup : 0 } ],
|
||||
"dup_x1" : [ { dup : 1 } ],
|
||||
"dup_x2" : [ { dup : 2 } ],
|
||||
"dup2" : [ { dup2 : 0 } ],
|
||||
"dup2_x1" : [ { dup2 : 1 } ],
|
||||
"dup2_x2" : [ { dup2 : 2 } ],
|
||||
"f2d" : [ { pop_objectref : None }, { push_objectres : [ 1, 'double' ] } ],
|
||||
"f2i" : [ { pop_objectref : None }, { push_objectres : [ 1, 'integer' ] } ],
|
||||
"f2l" : [ { pop_objectref : None }, { push_objectres : [ 1, 'long' ] } ],
|
||||
"fadd" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '+' ] } ],
|
||||
"faload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"fastore" : [ { set_arrayref : "float" } ],
|
||||
"fcmpg" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"fcmpl" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"fconst_0" : [ { push_float_d : 0.0 } ],
|
||||
"fconst_1" : [ { push_float_d : 1.0 } ],
|
||||
"fconst_2" : [ { push_float_d : 2.0 } ],
|
||||
"fdiv" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '&' ] } ],
|
||||
"fload" : [ { push_objectref_l_i : None } ],
|
||||
"fload_0" : [ { push_objectref_l : 0 } ],
|
||||
"fload_1" : [ { push_objectref_l : 1 } ],
|
||||
"fload_2" : [ { push_objectref_l : 2 } ],
|
||||
"fload_3" : [ { push_objectref_l : 3 } ],
|
||||
"fmul" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '*' ] } ],
|
||||
"fneg" : [ { pop_objectref : None }, { push_objectres : [ 1, '-' ] } ],
|
||||
"freturn" : [ { pop_objectref : None } ],
|
||||
"fstore" : [ { set_objectref_i : None } ],
|
||||
"fstore_0" : [ { set_objectref : 0 } ],
|
||||
"fstore_1" : [ { set_objectref : 1 } ],
|
||||
"fstore_2" : [ { set_objectref : 2 } ],
|
||||
"fstore_3" : [ { set_objectref : 3 } ],
|
||||
"fsub" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '-' ] } ],
|
||||
"getfield" : [ { getfield : None } ],
|
||||
"getstatic" : [ { getstatic : None } ],
|
||||
"goto" : [ {} ],
|
||||
"goto_w" : [ {} ],
|
||||
"i2b" : [ { pop_objectref : None }, { push_objectres : [ 1, 'byte' ] } ],
|
||||
"i2c" : [ { pop_objectref : None }, { push_objectres : [ 1, 'char' ] } ],
|
||||
"i2d" : [ { pop_objectref : None }, { push_objectres : [ 1, 'double' ] } ],
|
||||
"i2f" : [ { pop_objectref : None }, { push_objectres : [ 1, 'float' ] } ],
|
||||
"i2l" : [ { pop_objectref : None }, { push_objectres : [ 1, 'long' ] } ],
|
||||
"i2s" : [ { pop_objectref : None }, { push_objectres : [ 1, 'string' ] } ],
|
||||
"iadd" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '+' ] } ],
|
||||
"iaload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"iand" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '&' ] } ],
|
||||
"iastore" : [ { set_arrayref : "int" } ],
|
||||
"iconst_m1" : [ { push_integer_d : -1 } ],
|
||||
"iconst_0" : [ { push_integer_d : 0 } ],
|
||||
"iconst_1" : [ { push_integer_d : 1 } ],
|
||||
"iconst_2" : [ { push_integer_d : 2 } ],
|
||||
"iconst_3" : [ { push_integer_d : 3 } ],
|
||||
"iconst_4" : [ { push_integer_d : 4 } ],
|
||||
"iconst_5" : [ { push_integer_d : 5 } ],
|
||||
"idiv" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '/' ] } ],
|
||||
"if_acmpeq" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"if_acmpne" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"if_icmpeq" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"if_icmpne" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"if_icmplt" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"if_icmpge" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"if_icmpgt" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"if_icmple" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"ifeq" : [ { pop_objectref : None } ],
|
||||
"ifne" : [ { pop_objectref : None } ],
|
||||
"iflt" : [ { pop_objectref : None } ],
|
||||
"ifge" : [ { pop_objectref : None } ],
|
||||
"ifgt" : [ { pop_objectref : None } ],
|
||||
"ifle" : [ { pop_objectref : None } ],
|
||||
"ifnonnull" : [ { pop_objectref : None } ],
|
||||
"ifnull" : [ { pop_objectref : None } ],
|
||||
"iinc" : [ {} ],
|
||||
"iload" : [ { push_objectref_l_i : None } ],
|
||||
"iload_1" : [ { push_objectref_l : 1 } ],
|
||||
"iload_2" : [ { push_objectref_l : 2 } ],
|
||||
"iload_3" : [ { push_objectref_l : 3 } ],
|
||||
"imul" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '*' ] } ],
|
||||
"ineg" : [ { pop_objectref : None }, { push_objectres : [ 1, '-' ] } ],
|
||||
"instanceof" : [ { pop_objectref : None }, { push_objectres : [ 1, 'instanceof' ] } ],
|
||||
"invokeinterface" : [ { invoke : 1 } ],
|
||||
"invokespecial" : [ { invoke : 1 } ],
|
||||
"invokestatic" : [ { invoke : 0 } ],
|
||||
"invokevirtual": [ { invoke : 1 } ],
|
||||
"ior" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '|' ] } ],
|
||||
"irem" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, 'REM' ] } ],
|
||||
"ireturn" : [ { pop_objectref : None } ],
|
||||
"ishl" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '<<' ] } ],
|
||||
"ishr" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '>>' ] } ],
|
||||
"istore" : [ { set_objectref_i : None } ],
|
||||
"istore_0" : [ { set_objectref : 0 } ],
|
||||
"istore_1" : [ { set_objectref : 1 } ],
|
||||
"istore_2" : [ { set_objectref : 2 } ],
|
||||
"istore_3" : [ { set_objectref : 3 } ],
|
||||
"isub" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '-' ] } ],
|
||||
"iushr" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '>>' ] } ],
|
||||
"ixor" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '^' ] } ],
|
||||
"jsr" : [ { push_integer_i : None } ],
|
||||
"jsr_w" : [ { push_integer_i : None } ],
|
||||
"l2d" : [ { pop_objectref : None }, { push_objectres : [ 1, 'double' ] } ],
|
||||
"l2f" : [ { pop_objectref : None }, { push_objectres : [ 1, 'float' ] } ],
|
||||
"l2i" : [ { pop_objectref : None }, { push_objectres : [ 1, 'integer' ] } ],
|
||||
"ladd" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '+' ] } ],
|
||||
"laload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"land" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '&' ] } ],
|
||||
"lastore" : [ { set_arrayref : "long" } ],
|
||||
"lcmp" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"lconst_0" : [ { push_float_d : 0.0 } ],
|
||||
"lconst_1" : [ { push_float_d : 1.0 } ],
|
||||
"ldc" : [ { ldc : None } ],
|
||||
"ldc_w" : [ { ldc : None } ],
|
||||
"ldc2_w" : [ { ldc : None } ],
|
||||
"ldiv" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '/' ] } ],
|
||||
"lload" : [ { push_objectref_l_i : None } ],
|
||||
"lload_0" : [ { push_objectref_l : 0 } ],
|
||||
"lload_1" : [ { push_objectref_l : 1 } ],
|
||||
"lload_2" : [ { push_objectref_l : 2 } ],
|
||||
"lload_3" : [ { push_objectref_l : 3 } ],
|
||||
"lmul" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '*' ] } ],
|
||||
"lneg" : [ { pop_objectref : None }, { push_objectres : [ 1, '-' ] } ],
|
||||
"lookupswitch" : [ { pop_objectref : None } ],
|
||||
"lor" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '|' ] } ],
|
||||
"lrem" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, 'REM' ] } ],
|
||||
"lreturn" : [ { pop_objectref : None } ],
|
||||
"lshl" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '<<' ] } ],
|
||||
"lshr" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '>>' ] } ],
|
||||
"lstore" : [ { set_objectref_i : None } ],
|
||||
"lstore_0" : [ { set_objectref : 0 } ],
|
||||
"lstore_1" : [ { set_objectref : 1 } ],
|
||||
"lstore_2" : [ { set_objectref : 2 } ],
|
||||
"lstore_3" : [ { set_objectref : 3 } ],
|
||||
"lsub" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '-' ] } ],
|
||||
"lushr" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '>>' ] } ],
|
||||
"lxor" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectres : [ 2, '^' ] } ],
|
||||
"monitorenter" : [ { pop_objectref : None } ],
|
||||
"monitorexit" : [ { pop_objectref : None } ],
|
||||
"multianewarray" : [ { multi_pop_objectref_i : None }, { push_objectref : 0 } ],
|
||||
"new" : [ { new : None } ],
|
||||
"newarray" : [ { pop_objectref : None }, { push_objectref : [ 1, "NEWARRAY" ] } ],
|
||||
"nop" : [ {} ],
|
||||
"pop" : [ { pop_objectref : None } ],
|
||||
"pop2" : [ { pop_objectref : None }, { pop_objectref : None } ],
|
||||
"putfield" : [ { putfield : None }, { pop_objectref : None } ],
|
||||
"putstatic" : [ { putstatic : None } ],
|
||||
"ret" : [ {} ],
|
||||
"return" : [ {} ],
|
||||
"saload" : [ { pop_objectref : None }, { pop_objectref : None }, { push_objectref : 0 } ],
|
||||
"sastore" : [ { set_arrayref : "short" } ],
|
||||
"sipush" : [ { push_integer_i : None } ],
|
||||
"swap" : [ { swap : None } ],
|
||||
"tableswitch" : [ { pop_objectref : None } ],
|
||||
"wide" : [ {} ],
|
||||
}
|
||||
|
||||
|
||||
class ReturnValues(object):
|
||||
def __init__(self):
|
||||
self.__elems = []
|
||||
self.__msgs = []
|
||||
|
||||
def add_msg(self, e):
|
||||
self.__msgs.append( e )
|
||||
|
||||
def add_return(self, e):
|
||||
self.__elems.append( e )
|
||||
|
||||
def get_msg(self):
|
||||
return self.__msgs
|
||||
|
||||
def get_return(self):
|
||||
return self.__elems
|
||||
|
||||
class ExternalMethod(object):
|
||||
def __init__(self, class_name, name, descriptor):
|
||||
self.__class_name = class_name
|
||||
self.__name = name
|
||||
self.__descriptor = descriptor
|
||||
|
||||
def get_name(self):
|
||||
return "M@[%s][%s]-[%s]" % (self.__class_name, self.__name, self.__descriptor)
|
||||
|
||||
def set_fathers(self, f):
|
||||
pass
|
||||
|
||||
class JVMBasicBlock(object):
|
||||
def __init__(self, start, vm, method, context):
|
||||
self.__vm = vm
|
||||
self.method = method
|
||||
self.context = context
|
||||
|
||||
self.__stack = Stack()
|
||||
self.stack_traces = StackTraces()
|
||||
|
||||
self.ins = []
|
||||
|
||||
self.fathers = []
|
||||
self.childs = []
|
||||
|
||||
self.start = start
|
||||
self.end = self.start
|
||||
|
||||
self.break_blocks = []
|
||||
|
||||
self.free_blocks_offsets = []
|
||||
|
||||
self.name = "%s-BB@0x%x" % (self.method.get_name(), self.start)
|
||||
|
||||
def get_stack(self):
|
||||
return self.__stack.gets()
|
||||
|
||||
def get_method(self):
|
||||
return self.method
|
||||
|
||||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_start(self):
|
||||
return self.start
|
||||
|
||||
def get_end(self):
|
||||
return self.end
|
||||
|
||||
def get_last(self):
|
||||
return self.ins[-1]
|
||||
|
||||
def push(self, i):
|
||||
self.ins.append( i )
|
||||
self.end += i.get_length()
|
||||
|
||||
def set_fathers(self, f):
|
||||
self.fathers.append( f )
|
||||
|
||||
def set_childs(self, values):
|
||||
# print self, self.start, self.end, values, self.ins[-1].get_name()
|
||||
if values == []:
|
||||
next_block = self.context.get_basic_block( self.end + 1 )
|
||||
if next_block != None:
|
||||
self.childs.append( ( self.end - self.ins[-1].get_length(), self.end, next_block ) )
|
||||
else:
|
||||
for i in values:
|
||||
#print i, self.context.get_basic_block( i )
|
||||
if i != -1:
|
||||
self.childs.append( ( self.end - self.ins[-1].get_length(), i, self.context.get_basic_block( i ) ) )
|
||||
|
||||
for c in self.childs:
|
||||
if c[2] != None:
|
||||
c[2].set_fathers( ( c[1], c[0], self ) )
|
||||
|
||||
def prev_free_block_offset(self, idx=0):
|
||||
last = -1
|
||||
|
||||
#print "IDX", idx, self.free_blocks_offsets
|
||||
|
||||
if self.free_blocks_offsets == []:
|
||||
return -1
|
||||
|
||||
for i in self.free_blocks_offsets:
|
||||
if i <= idx:
|
||||
last = i
|
||||
else:
|
||||
return last
|
||||
|
||||
return last
|
||||
|
||||
def random_free_block_offset(self):
|
||||
return self.free_blocks_offsets[ random.randint(0, len(self.free_blocks_offsets) - 1) ]
|
||||
|
||||
def next_free_block_offset(self, idx=0):
|
||||
#print idx, self.__free_blocks_offsets
|
||||
for i in self.free_blocks_offsets:
|
||||
if i > idx:
|
||||
return i
|
||||
return -1
|
||||
|
||||
def get_random_free_block_offset(self):
|
||||
return self.free_blocks_offsets[ random.randint(0, len(self.free_blocks_offsets) - 1) ]
|
||||
|
||||
def get_random_break_block(self):
|
||||
return self.break_blocks[ random.randint(0, len(self.break_blocks) - 1) ]
|
||||
|
||||
def get_break_block(self, idx):
|
||||
for i in self.break_blocks:
|
||||
if idx >= i.get_start() and idx <= i.get_end():
|
||||
return i
|
||||
return None
|
||||
|
||||
def analyze_break_blocks(self):
|
||||
idx = self.get_start()
|
||||
|
||||
current_break = JVMBreakBlock( self.__vm, idx )
|
||||
self.break_blocks.append(current_break)
|
||||
for i in self.ins:
|
||||
name = i.get_name()
|
||||
|
||||
##################### Break Block ########################
|
||||
match = False
|
||||
for j in BREAK_JVM_OPCODES_RE:
|
||||
if j.match(name) != None:
|
||||
match = True
|
||||
break
|
||||
|
||||
current_break.push( i )
|
||||
if match == True:
|
||||
current_break.analyze()
|
||||
current_break = JVMBreakBlock( self.__vm, current_break.get_end() )
|
||||
|
||||
self.break_blocks.append( current_break )
|
||||
#########################################################
|
||||
|
||||
idx += i.get_length()
|
||||
|
||||
def analyze(self):
|
||||
idx = 0
|
||||
for i in self.ins:
|
||||
################### TAINTED LOCAL VARIABLES ###################
|
||||
if "load" in i.get_name() or "store" in i.get_name():
|
||||
action = i.get_name()
|
||||
|
||||
access_flag = [ "R", "load" ]
|
||||
if "store" in action:
|
||||
access_flag = [ "W", "store" ]
|
||||
|
||||
if "_" in action:
|
||||
name = i.get_name().split(access_flag[1])
|
||||
value = name[1][-1]
|
||||
else:
|
||||
value = i.get_operands()
|
||||
|
||||
variable_name = "%s-%s" % (i.get_name()[0], value)
|
||||
|
||||
self.context.get_tainted_variables().add( variable_name, TAINTED_LOCAL_VARIABLE, self.method )
|
||||
self.context.get_tainted_variables().push_info( TAINTED_LOCAL_VARIABLE, variable_name, (access_flag[0], idx, self, self.method) )
|
||||
#########################################################
|
||||
|
||||
################### TAINTED FIELDS ###################
|
||||
elif i.get_name() in FIELDS:
|
||||
o = i.get_operands()
|
||||
desc = getattr(self.__vm, "get_field_descriptor")(o[0], o[1], o[2])
|
||||
|
||||
# It's an external
|
||||
#if desc == None:
|
||||
# desc = ExternalFM( o[0], o[1], o[2] )
|
||||
|
||||
# print "RES", res, "-->", desc.get_name()
|
||||
self.context.get_tainted_variables().push_info( TAINTED_FIELD, [o[0], o[1], o[2]], (FIELDS[ i.get_name() ][0], idx, self, self.method) )
|
||||
#########################################################
|
||||
|
||||
################### TAINTED PACKAGES ###################
|
||||
elif "new" in i.get_name() or "invoke" in i.get_name() or "getstatic" in i.get_name():
|
||||
if "new" in i.get_name():
|
||||
self.context.get_tainted_packages().push_info( i.get_operands(), (TAINTED_PACKAGE_CREATE, idx, self, self.method) )
|
||||
else:
|
||||
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]) )
|
||||
#########################################################
|
||||
|
||||
################### TAINTED INTEGERS ###################
|
||||
if "ldc" == i.get_name():
|
||||
o = i.get_operands()
|
||||
|
||||
if o[0] == "CONSTANT_Integer":
|
||||
self.context.get_tainted_integers().push_info( i, (o[1], idx, self, self.method) )
|
||||
|
||||
elif "sipush" in i.get_name():
|
||||
self.context.get_tainted_integers().push_info( i, (i.get_operands(), idx, self, self.method) )
|
||||
|
||||
elif "bipush" in i.get_name():
|
||||
self.context.get_tainted_integers().push_info( i, (i.get_operands(), idx, self, self.method) )
|
||||
|
||||
#########################################################
|
||||
|
||||
idx += i.get_length()
|
||||
|
||||
def set_exception(self, exception_analysis):
|
||||
pass
|
||||
|
||||
# FIXME : create a recursive function to follow the cfg, because it does not work with obfuscator
|
||||
def analyze_code(self):
|
||||
self.analyze_break_blocks()
|
||||
|
||||
#print "ANALYZE CODE -->", self.name
|
||||
d = {}
|
||||
for i in self.fathers:
|
||||
# print "\t FATHER ->", i[2].get_name(), i[2].get_stack(), i[0], i[1]
|
||||
d[ i[0] ] = i[2]
|
||||
|
||||
self.free_blocks_offsets.append( self.get_start() )
|
||||
|
||||
idx = 0
|
||||
for i in self.ins:
|
||||
# print i.get_name(), self.start + idx, idx
|
||||
# i.show(idx)
|
||||
|
||||
if self.start + idx in d:
|
||||
self.__stack.insert_stack( 0, d[ self.start + idx ].get_stack() )
|
||||
|
||||
ret_v = ReturnValues()
|
||||
|
||||
res = []
|
||||
try:
|
||||
#print i.get_name(), i.get_name() in INSTRUCTIONS_ACTIONS
|
||||
|
||||
if INSTRUCTIONS_ACTIONS[ i.get_name() ] == []:
|
||||
print "[[[[ %s is not yet implemented ]]]]" % i.get_name()
|
||||
raise("ooops")
|
||||
|
||||
i_idx = 0
|
||||
for actions in INSTRUCTIONS_ACTIONS[ i.get_name() ]:
|
||||
for action in actions:
|
||||
action( self.__vm, i, actions[action], self.__stack, res, ret_v )
|
||||
for val in ret_v.get_return():
|
||||
res.append( val )
|
||||
|
||||
#self.__stack.show()
|
||||
self.stack_traces.save( idx, i_idx, i, cPickle.dumps( self.__stack ), cPickle.dumps( ret_v.get_msg() ) )
|
||||
i_idx += 1
|
||||
|
||||
except KeyError:
|
||||
print "[[[[ %s is not in INSTRUCTIONS_ACTIONS ]]]]" % i.get_name()
|
||||
except IndexError:
|
||||
print "[[[[ Analysis failed in %s-%s-%s ]]]]" % (self.method.get_class_name(), self.method.get_name(), self.method.get_descriptor())
|
||||
|
||||
idx += i.get_length()
|
||||
|
||||
if self.__stack.nil() == True and i != self.ins[-1]:
|
||||
self.free_blocks_offsets.append( idx + self.get_start() )
|
||||
|
||||
def show(self):
|
||||
print "\t@", self.name
|
||||
|
||||
idx = 0
|
||||
nb = 0
|
||||
for i in self.ins:
|
||||
print "\t\t", nb, idx,
|
||||
i.show(nb)
|
||||
nb += 1
|
||||
idx += i.get_length()
|
||||
|
||||
print ""
|
||||
print "\t\tFree blocks offsets --->", self.free_blocks_offsets
|
||||
print "\t\tBreakBlocks --->", len(self.break_blocks)
|
||||
|
||||
print "\t\tF --->", ', '.join( i[2].get_name() for i in self.fathers )
|
||||
print "\t\tC --->", ', '.join( i[2].get_name() for i in self.childs )
|
||||
|
||||
self.stack_traces.show()
|
||||
|
||||
def get_ins(self):
|
||||
return self.ins
|
||||
|
||||
class JVMBreakBlock(BreakBlock):
|
||||
def __init__(self, _vm, idx):
|
||||
super(JVMBreakBlock, self).__init__(_vm, idx)
|
||||
|
||||
self.__info = {
|
||||
"F" : [ "get_field_descriptor", self._fields, ContextField ],
|
||||
"M" : [ "get_method_descriptor", self._methods, ContextMethod ],
|
||||
}
|
||||
|
||||
|
||||
def get_free(self):
|
||||
if self._ins == []:
|
||||
return False
|
||||
|
||||
if "store" in self._ins[-1].get_name():
|
||||
return True
|
||||
elif "putfield" in self._ins[-1].get_name():
|
||||
return True
|
||||
|
||||
return False
|
||||
|
||||
def analyze(self):
|
||||
ctt = []
|
||||
|
||||
stack = Stack()
|
||||
for i in self._ins:
|
||||
v = self.trans(i)
|
||||
if v != None:
|
||||
ctt.append( v )
|
||||
|
||||
t = ""
|
||||
|
||||
for mre in jvm.MATH_JVM_RE:
|
||||
if mre[0].match( i.get_name() ):
|
||||
self._ops.append( mre[1] )
|
||||
break
|
||||
|
||||
# Woot it's a field !
|
||||
if i.get_name() in FIELDS:
|
||||
t = "F"
|
||||
elif i.get_name() in METHODS:
|
||||
t = "M"
|
||||
|
||||
if t != "":
|
||||
o = i.get_operands()
|
||||
desc = getattr(self._vm, self.__info[t][0])(o[0], o[1], o[2])
|
||||
|
||||
# It's an external
|
||||
if desc == None:
|
||||
desc = ExternalFM( o[0], o[1], o[2] )
|
||||
|
||||
if desc not in self.__info[t][1]:
|
||||
self.__info[t][1][desc] = []
|
||||
|
||||
if t == "F":
|
||||
self.__info[t][1][desc].append( self.__info[t][2]( FIELDS[ i.get_name() ][0] ) )
|
||||
|
||||
# print "RES", res, "-->", desc.get_name()
|
||||
# self.__tf.push_info( desc, [ FIELDS[ i.get_name() ][0], res ] )
|
||||
elif t == "M":
|
||||
self.__info[t][1][desc].append( self.__info[t][2]() )
|
||||
|
||||
for i in self._fields:
|
||||
for k in self._fields[i]:
|
||||
k.set_details( ctt )
|
||||
|
||||
for i in self._methods:
|
||||
for k in self._methods[i]:
|
||||
k.set_details( ctt )
|
||||
|
||||
def trans(self, i):
|
||||
v = i.get_name()[0:2]
|
||||
if v == "il" or v == "ic" or v == "ia" or v == "si" or v == "bi":
|
||||
return "I"
|
||||
|
||||
if v == "ba":
|
||||
return "B"
|
||||
|
||||
if v == "if":
|
||||
return "IF"
|
||||
|
||||
if v == "ir":
|
||||
return "RET"
|
||||
|
||||
if "and" in i.get_name():
|
||||
return "&"
|
||||
|
||||
if "add" in i.get_name():
|
||||
return "+"
|
||||
|
||||
if "sub" in i.get_name():
|
||||
return "-"
|
||||
|
||||
if "xor" in i.get_name():
|
||||
return "^"
|
||||
|
||||
if "ldc" in i.get_name():
|
||||
return "I"
|
||||
|
||||
if "invokevirtual" in i.get_name():
|
||||
return "M" + i.get_operands()[2]
|
||||
|
||||
if "getfield" in i.get_name():
|
||||
return "F" + i.get_operands()[2]
|
||||
|
||||
|
||||
DVM_FIELDS_ACCESS = {
|
||||
"iget" : "R",
|
||||
"iget-wide" : "R",
|
||||
@ -2156,7 +1350,6 @@ class Exceptions(object):
|
||||
for i in self.exceptions:
|
||||
yield i
|
||||
|
||||
#BO = { "BasicOPCODES" : jvm.BRANCH2_JVM_OPCODES, "BasicClass" : JVMBasicBlock, "Dnext" : jvm.determineNext, "Dexception" : jvm.determineException }
|
||||
BO = { "BasicOPCODES" : dvm.BRANCH_DVM_OPCODES, "BasicClass" : DVMBasicBlock, "Dnext" : dvm.determineNext, "Dexception" : dvm.determineException }
|
||||
|
||||
BO["BasicOPCODES_H"] = []
|
||||
|
@ -16,7 +16,6 @@
|
||||
# limitations under the License.
|
||||
|
||||
from androguard.core import androconf
|
||||
from androguard.core.bytecodes import jvm
|
||||
from androguard.core.bytecodes import dvm
|
||||
from androguard.core.bytecodes import apk
|
||||
from androguard.core.analysis import analysis
|
||||
@ -122,11 +121,7 @@ class Androguard(object):
|
||||
else:
|
||||
raise( "Unknown format" )
|
||||
|
||||
if isinstance(bc, list):
|
||||
for j in bc:
|
||||
self.__bc.append( (j[0], BC( jvm.JVMFormat(j[1]) ) ) )
|
||||
else:
|
||||
self.__bc.append( (i, BC( bc )) )
|
||||
self.__bc.append( (i, BC( bc )) )
|
||||
|
||||
def ianalyze(self):
|
||||
for i in self.get_bc():
|
||||
@ -246,7 +241,7 @@ class AndroguardS(object):
|
||||
"""
|
||||
This method returns the VMFormat which correspond to the file
|
||||
|
||||
@rtype: L{jvm.JVMFormat} or L{dvm.DalvikVMFormat}
|
||||
@rtype: L{dvm.DalvikVMFormat}
|
||||
"""
|
||||
return self.__a.get_vm()
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -1,137 +0,0 @@
|
||||
# This file is part of Androguard.
|
||||
#
|
||||
# Copyright (C) 2012 Anthony Desnos <desnos at t0t0.fr>
|
||||
# All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS-IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
import random
|
||||
|
||||
from androconf import error
|
||||
import jvm
|
||||
|
||||
class Automaton(object):
|
||||
def __init__(self, _analysis):
|
||||
self.__analysis = _analysis
|
||||
|
||||
try:
|
||||
from networkx import DiGraph
|
||||
from networkx import draw_graphviz, write_dot
|
||||
except ImportError:
|
||||
error("module networkx not found")
|
||||
|
||||
self.__G = DiGraph()
|
||||
|
||||
for m in self.__analysis.get_methods():
|
||||
for bb in m.basic_blocks.get():
|
||||
for trace in bb.stack_traces.get():
|
||||
for mre in jvm.MATH_JVM_RE:
|
||||
if mre[0].match( trace[2].get_name() ):
|
||||
for i in trace[3].gets():
|
||||
self._add( str(i) )
|
||||
|
||||
def _add(self, elem):
|
||||
l = []
|
||||
x = ""
|
||||
for i in elem:
|
||||
if i not in jvm.MATH_JVM_OPCODES.values():
|
||||
x += i
|
||||
else:
|
||||
l.append( x )
|
||||
l.append( i )
|
||||
x = ""
|
||||
|
||||
if len(l) > 1:
|
||||
l.append( x )
|
||||
|
||||
self._add_expr( l )
|
||||
|
||||
def _add_expr(self, l):
|
||||
if l == []:
|
||||
return
|
||||
i = 0
|
||||
while i < (len(l)-1):
|
||||
self.__G.add_edge( self._transform(l[i]), self._transform(l[i+1]) )
|
||||
|
||||
i += 1
|
||||
|
||||
def _transform(self, i):
|
||||
if "VARIABLE" in i:
|
||||
return "V"
|
||||
return i
|
||||
|
||||
def new(self, loop):
|
||||
expr = []
|
||||
|
||||
l = list( self.__G.node )
|
||||
|
||||
init = l[ random.randint(0, len(l) - 1) ]
|
||||
while init in jvm.MATH_JVM_OPCODES.values():
|
||||
init = l[ random.randint(0, len(l) - 1) ]
|
||||
|
||||
expr.append( init )
|
||||
|
||||
i = 0
|
||||
while i <= loop:
|
||||
l = list( self.__G.edge[ init ] )
|
||||
if l == []:
|
||||
break
|
||||
|
||||
init = l[ random.randint(0, len(l) - 1) ]
|
||||
expr.append( init )
|
||||
|
||||
i += 1
|
||||
|
||||
return expr
|
||||
|
||||
def show(self):
|
||||
print self.__G.node
|
||||
print self.__G.edge
|
||||
|
||||
#draw_graphviz(self.__G)
|
||||
#write_dot(self.__G,'file.dot')
|
||||
|
||||
class JVMGenerate(object):
|
||||
def __init__(self, _vm, _analysis):
|
||||
self.__vm = _vm
|
||||
self.__analysis = _analysis
|
||||
|
||||
self.__automaton = Automaton( self.__analysis )
|
||||
self.__automaton.show()
|
||||
|
||||
def create_affectation(self, method_name, desc):
|
||||
l = []
|
||||
|
||||
if desc[0] == 0:
|
||||
l.append( [ "aload_0" ] )
|
||||
l.append( [ "bipush", desc[2] ] )
|
||||
l.append( [ "putfield", desc[1].get_name(), desc[1].get_descriptor() ] )
|
||||
|
||||
return l
|
||||
|
||||
def write(self, method, offset, field):
|
||||
print method, offset, field
|
||||
expr = self.__automaton.new( 5 )
|
||||
|
||||
print field.get_name(), "EXPR ->", expr
|
||||
|
||||
self._transform( expr )
|
||||
|
||||
|
||||
def _transform(self, expr):
|
||||
if len(expr) == 1:
|
||||
return
|
||||
|
||||
x = [ expr.pop(0), expr.pop(1), expr.pop(0) ]
|
||||
|
||||
# while expr != []:
|
@ -26,7 +26,6 @@ from androguard.core import *
|
||||
from androguard.core.androgen import *
|
||||
from androguard.core.androconf import *
|
||||
from androguard.core.bytecode import *
|
||||
from androguard.core.bytecodes.jvm import *
|
||||
from androguard.core.bytecodes.dvm import *
|
||||
from androguard.core.bytecodes.apk import *
|
||||
|
||||
@ -259,23 +258,6 @@ def ExportElfToPython(e):
|
||||
setattr(e, name, function)
|
||||
|
||||
|
||||
def AnalyzeJAR(filename, raw=False):
|
||||
androconf.debug("JAR ...")
|
||||
a = JAR(filename, raw)
|
||||
|
||||
d = AnalyzeClasses(a.get_classes())
|
||||
|
||||
return a, d
|
||||
|
||||
|
||||
def AnalyzeClasses(classes):
|
||||
d = {}
|
||||
for i in classes:
|
||||
d[i[0]] = JVMFormat(i[1])
|
||||
|
||||
return d
|
||||
|
||||
|
||||
def main(options, arguments):
|
||||
if options.shell != None:
|
||||
interact()
|
||||
|
18
androlyze.py
18
androlyze.py
@ -26,7 +26,6 @@ from androguard.core import *
|
||||
from androguard.core.androgen import *
|
||||
from androguard.core.androconf import *
|
||||
from androguard.core.bytecode import *
|
||||
from androguard.core.bytecodes.jvm import *
|
||||
from androguard.core.bytecodes.dvm import *
|
||||
from androguard.core.bytecodes.apk import *
|
||||
|
||||
@ -259,23 +258,6 @@ def ExportElfToPython(e):
|
||||
setattr(e, name, function)
|
||||
|
||||
|
||||
def AnalyzeJAR(filename, raw=False):
|
||||
androconf.debug("JAR ...")
|
||||
a = JAR(filename, raw)
|
||||
|
||||
d = AnalyzeClasses(a.get_classes())
|
||||
|
||||
return a, d
|
||||
|
||||
|
||||
def AnalyzeClasses(classes):
|
||||
d = {}
|
||||
for i in classes:
|
||||
d[i[0]] = JVMFormat(i[1])
|
||||
|
||||
return d
|
||||
|
||||
|
||||
def main(options, arguments):
|
||||
if options.shell != None:
|
||||
interact()
|
||||
|
@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL + "/core")
|
||||
sys.path.append(PATH_INSTALL + "/core/bytecodes")
|
||||
|
||||
from androguard.util import read
|
||||
import jvm
|
||||
|
||||
TEST = "./examples/java/test/orig/Test1.class"
|
||||
|
||||
j = jvm.JVMFormat( read(TEST, binary=False) )
|
||||
|
||||
# SHOW CLASS (verbose)
|
||||
j.show()
|
||||
|
||||
# SHOW FIELDS
|
||||
for i in j.get_fields():
|
||||
print i.get_access(), i.get_name(), i.get_descriptor()
|
||||
|
||||
print
|
||||
|
||||
# SHOW METHODS
|
||||
for i in j.get_methods():
|
||||
print i.get_access(), i.get_name(), i.get_descriptor()
|
@ -1,29 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, random, string
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL + "/core")
|
||||
sys.path.append(PATH_INSTALL + "/core/bytecodes")
|
||||
|
||||
from androguard.util import read
|
||||
import jvm
|
||||
|
||||
TEST = "./examples/java/test/orig/Test1.class"
|
||||
TEST_OUTPUT = "./examples/java/test/new/Test1.class"
|
||||
|
||||
j = jvm.JVMFormat( read(TEST, binary=False) )
|
||||
|
||||
# Modify the name of each field
|
||||
for field in j.get_fields():
|
||||
field.set_name( random.choice( string.letters ) + ''.join([ random.choice(string.letters + string.digits) for i in range(10 - 1) ] ) )
|
||||
|
||||
# Modify the name of each method (minus the constructor (<init>) and a extern called method (go))
|
||||
for method in j.get_methods():
|
||||
if method.get_name() != "go" and method.get_name() != "<init>":
|
||||
method.set_name( random.choice( string.letters ) + ''.join([ random.choice(string.letters + string.digits) for i in range(10 - 1) ] ) )
|
||||
|
||||
# SAVE CLASS
|
||||
with open( TEST_OUTPUT, "w" ) as fd:
|
||||
fd.write( j.save() )
|
||||
|
@ -1,27 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, random, string
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL + "/core")
|
||||
sys.path.append(PATH_INSTALL + "/core/bytecodes")
|
||||
|
||||
from androguard.util import read
|
||||
import jvm
|
||||
|
||||
TEST = "./examples/java/test/orig/Test1.class"
|
||||
TEST_REF = "./examples/java/Hello.class"
|
||||
TEST_OUTPUT = "./examples/java/test/new/Test1.class"
|
||||
|
||||
j = jvm.JVMFormat( read(TEST, binary=False) )
|
||||
j2 = jvm.JVMFormat( read(TEST_REF, binary=False) )
|
||||
|
||||
# Insert a craft method :)
|
||||
j.insert_craft_method( "toto", [ "ACC_PUBLIC", "[B", "[B" ], [ [ "aconst_null" ], [ "areturn" ] ] )
|
||||
|
||||
# Insert a method with no dependances methods
|
||||
j.insert_direct_method( "toto2", j2.get_method("test3")[0] )
|
||||
|
||||
# SAVE CLASS
|
||||
with open( TEST_OUTPUT, "w" ) as fd:
|
||||
fd.write( j.save() )
|
@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, random, string
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL + "/core")
|
||||
sys.path.append(PATH_INSTALL + "/core/bytecodes")
|
||||
|
||||
from androguard.util import read
|
||||
import jvm
|
||||
|
||||
TEST = "./examples/java/test/orig/Test1.class"
|
||||
TEST_REF = "./examples/java/Hello.class"
|
||||
TEST_OUTPUT = "./examples/java/test/new/Test1.class"
|
||||
|
||||
j = jvm.JVMFormat( read(TEST, binary=False) )
|
||||
j2 = jvm.JVMFormat( read(TEST_REF, binary=False) )
|
||||
|
||||
# Insert a method with java dependances methods/class
|
||||
j.insert_direct_method( "toto2", j2.get_method("test5")[0] )
|
||||
|
||||
# SAVE CLASS
|
||||
with open( TEST_OUTPUT, "w" ) as fd:
|
||||
fd.write( j.save() )
|
@ -1,24 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL + "/core")
|
||||
sys.path.append(PATH_INSTALL + "/core/bytecodes")
|
||||
sys.path.append(PATH_INSTALL + "/core/analysis")
|
||||
|
||||
from androguard.util import read
|
||||
import jvm, analysis
|
||||
|
||||
TEST = "./examples/java/test/orig/Test1.class"
|
||||
|
||||
j = jvm.JVMFormat( read(TEST, binary=False) )
|
||||
x = analysis.VMAnalysis( j )
|
||||
|
||||
# SHOW CLASS (verbose and pretty)
|
||||
#j.pretty_show( x )
|
||||
|
||||
# SHOW METHODS
|
||||
for i in j.get_methods():
|
||||
print i
|
||||
i.pretty_show( x )
|
@ -1,155 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
import sys, re
|
||||
|
||||
PATH_INSTALL = "./"
|
||||
sys.path.append(PATH_INSTALL)
|
||||
|
||||
from androguard.core.androgen import AndroguardS
|
||||
from androguard.core.analysis import analysis
|
||||
|
||||
from androguard.core.bytecodes.jvm import BRANCH2_JVM_OPCODES, determineNext
|
||||
|
||||
TEST_CASE = 'examples/java/TC/orig/TCE.class'
|
||||
|
||||
VALUES = { "TCE <init> ()V" : [
|
||||
("if_icmpge", [116]),
|
||||
("if_icmpge", [19]),
|
||||
("goto", [-18]),
|
||||
("lookupswitch", [22, 19]),
|
||||
("lookupswitch", [47, 40, 34, 37]),
|
||||
("goto", [-123]),
|
||||
("return", [-1]),
|
||||
],
|
||||
}
|
||||
|
||||
###############################################
|
||||
MODIF = { "TCE <init> ()V" : [
|
||||
("remove_at", 28),
|
||||
]
|
||||
}
|
||||
###############################################
|
||||
|
||||
###############################################
|
||||
MODIF2 = { "TCE <init> ()V" : [
|
||||
("insert_at", 28, [ "aload_0"]),
|
||||
]
|
||||
}
|
||||
###############################################
|
||||
|
||||
###############################################
|
||||
MODIF3 = { "TCE <init> ()V" : [
|
||||
("remove_at", 88),
|
||||
]
|
||||
}
|
||||
|
||||
VALUES3 = { "TCE <init> ()V" : [
|
||||
("if_icmpge", [113]),
|
||||
("if_icmpge", [16]),
|
||||
("goto", [-15]),
|
||||
("lookupswitch", [22, 19]),
|
||||
("lookupswitch", [47, 40, 34, 37]),
|
||||
("goto", [-120]),
|
||||
("return", [-1]),
|
||||
],
|
||||
}
|
||||
###############################################
|
||||
|
||||
###############################################
|
||||
MODIF4 = { "TCE <init> ()V" : [
|
||||
("insert_at", 88, [ "sipush", 400 ]),
|
||||
]
|
||||
}
|
||||
###############################################
|
||||
|
||||
###############################################
|
||||
MODIF4 = { "TCE <init> ()V" : [
|
||||
("insert_at", 88, [ "sipush", 400 ]),
|
||||
]
|
||||
}
|
||||
###############################################
|
||||
|
||||
|
||||
def test(got, expected):
|
||||
if got == expected:
|
||||
prefix = ' OK '
|
||||
else:
|
||||
prefix = ' X '
|
||||
|
||||
print '\t%s got: %s expected: %s' % (prefix, repr(got), repr(expected))
|
||||
|
||||
def getVal(i):
|
||||
op = i.get_operands()
|
||||
|
||||
if isinstance(op, int):
|
||||
return [ op ]
|
||||
elif i.get_name() == "lookupswitch":
|
||||
x = []
|
||||
|
||||
x.append( i.get_operands().default )
|
||||
for idx in range(0, i.get_operands().npairs):
|
||||
off = getattr(i.get_operands(), "offset%d" % idx)
|
||||
x.append( off )
|
||||
return x
|
||||
|
||||
return [-1]
|
||||
|
||||
def check(a, values, branch):
|
||||
b = []
|
||||
for i in branch:
|
||||
b.append( re.compile( i ) )
|
||||
|
||||
for method in a.get_methods():
|
||||
key = method.get_class_name() + " " + method.get_name() + " " + method.get_descriptor()
|
||||
|
||||
if key not in values:
|
||||
continue
|
||||
|
||||
print "CHECKING ...", method.get_class_name(), method.get_name(), method.get_descriptor()
|
||||
code = method.get_code()
|
||||
bc = code.get_bc()
|
||||
|
||||
idx = 0
|
||||
v = 0
|
||||
for i in bc.get():
|
||||
# print "\t", "%x(%d)" % (idx, idx), i.get_name(), i.get_operands()
|
||||
for j in b:
|
||||
if j.match(i.get_name()) != None:
|
||||
elem = values[key][v]
|
||||
test("%s %s" % (elem[0], elem[1]), "%s %s" % (i.get_name(), getVal(i)))
|
||||
|
||||
v += 1
|
||||
break
|
||||
|
||||
idx += i.get_length()
|
||||
|
||||
def modify(a, modif):
|
||||
for method in a.get_methods():
|
||||
key = method.get_class_name() + " " + method.get_name() + " " + method.get_descriptor()
|
||||
|
||||
if key not in modif:
|
||||
continue
|
||||
|
||||
print "MODIFYING ...", method.get_class_name(), method.get_name(), method.get_descriptor()
|
||||
code = method.get_code()
|
||||
|
||||
for i in modif[key]:
|
||||
getattr( code, i[0] )( *i[1:] )
|
||||
|
||||
a = AndroguardS( TEST_CASE )
|
||||
|
||||
### INIT CHECK ###
|
||||
check( a, VALUES, BRANCH2_JVM_OPCODES )
|
||||
### APPLY MODIFICATION ###
|
||||
modify( a, MODIF )
|
||||
### CHECK IF MODIFICATION IS OK ###
|
||||
check( a, VALUES, BRANCH2_JVM_OPCODES )
|
||||
|
||||
modify( a, MODIF2 )
|
||||
check( a, VALUES, BRANCH2_JVM_OPCODES )
|
||||
|
||||
modify( a, MODIF3 )
|
||||
check( a, VALUES3, BRANCH2_JVM_OPCODES )
|
||||
|
||||
modify( a, MODIF4 )
|
||||
check( a, VALUES, BRANCH2_JVM_OPCODES )
|
Loading…
Reference in New Issue
Block a user