Skip to content

Commit

Permalink
Merge pull request #689 from Neakxs/dexparser/#684-1
Browse files Browse the repository at this point in the history
StringDataItem decoding removed
  • Loading branch information
reox committed May 12, 2019
2 parents 55f282b + a39ff67 commit c5104fb
Show file tree
Hide file tree
Showing 12 changed files with 372 additions and 280 deletions.
6 changes: 3 additions & 3 deletions androguard/cli/main.py
Expand Up @@ -240,7 +240,7 @@ def export_apps_to_format(filename,
continue

# Current Folder to write to
filename_class = valid_class_name(method.get_class_name())
filename_class = valid_class_name(method.get_class_name().string)
filename_class = os.path.join(output, filename_class)
create_directory(filename_class)

Expand All @@ -257,10 +257,10 @@ def export_apps_to_format(filename,
method2format(filename + "." + form, form, None, buff)

# Write the Java file for the whole class
if method.get_class_name() not in dump_classes:
if method.get_class_name().string not in dump_classes:
print("source codes ...", end=' ')
current_class = vm.get_class(method.get_class_name())
current_filename_class = valid_class_name(current_class.get_name())
current_filename_class = valid_class_name(current_class.get_name().string)

current_filename_class = os.path.join(output, current_filename_class + ".java")
with open(current_filename_class, "w") as fd:
Expand Down
38 changes: 23 additions & 15 deletions androguard/core/analysis/analysis.py
Expand Up @@ -5,7 +5,7 @@
from androguard.core.androconf import is_ascii_problem, load_api_specific_resource_module
from androguard.core.bytecodes import dvm
import logging
from androguard.core import bytecode
from androguard.core import bytecode, mutf8
import networkx as nx
from enum import IntEnum

Expand Down Expand Up @@ -789,7 +789,7 @@ def get_method(self, name, descriptor):
:param descriptor: method descriptor, for example `'(I)V'`
:return: :class:`ExternalMethod`
"""
key = name + str(descriptor)
key = name + mutf8.MUTF8String.join(descriptor)
if key not in self.methods:
self.methods[key] = ExternalMethod(self.name, name, descriptor)

Expand Down Expand Up @@ -818,7 +818,7 @@ def get_class_name(self):
return self.class_name

def get_descriptor(self):
return ''.join(self.descriptor)
return mutf8.MUTF8String.join(self.descriptor)

@property
def full_name(self):
Expand All @@ -837,7 +837,7 @@ def get_access_flags_string(self):
return ""

def __str__(self):
return "{}->{}{}".format(self.class_name, self.name, ''.join(self.descriptor))
return "{}->{}{}".format(self.class_name.__str__(), self.name.__str__(), mutf8.MUTF8String.join(self.descriptor).string)

def __repr__(self):
return "<analysis.ExternalMethod {}>".format(self.__str__())
Expand Down Expand Up @@ -988,7 +988,7 @@ def get_fake_method(self, name, descriptor):

# We are searching an unknown method in this class
# It could be something that the class herits
key = name + str(descriptor)
key = name + mutf8.MUTF8String.join(descriptor)
if key not in self._inherits_methods:
self._inherits_methods[key] = ExternalMethod(self.orig_class.get_name(), name, descriptor)
return self._inherits_methods[key]
Expand Down Expand Up @@ -1277,14 +1277,14 @@ def _create_xref(self, current_class):
continue

class_info = method_info[0].lstrip('[')
if class_info[0] != 'L':
if class_info[0] != b'L':
# Need to make sure, that we get class types and not other types
continue

method_item = None
# TODO: should create get_method_descriptor inside Analysis
for vm in self.vms:
method_item = vm.get_method_descriptor(class_info, method_info[1], ''.join(method_info[2]))
method_item = vm.get_method_descriptor(class_info, method_info[1], mutf8.MUTF8String.join(method_info[2]))
if method_item:
break

Expand Down Expand Up @@ -1501,10 +1501,11 @@ def find_classes(self, name=".*", no_external=False):
:param no_external: Remove external classes from the output (default False)
:rtype: Iterator[ClassAnalysis]
"""
name = mutf8.MUTF8String.from_str(name).bytes
for cname, c in self.classes.items():
if no_external and isinstance(c.get_vm_class(), ExternalClass):
continue
if re.match(name, cname):
if re.match(name, cname.bytes):
yield c

def find_methods(self, classname=".*", methodname=".*", descriptor=".*",
Expand All @@ -1521,17 +1522,20 @@ def find_methods(self, classname=".*", methodname=".*", descriptor=".*",
:param no_external: Remove external method from the output (default False)
:rtype: Iterator[MethodClassAnalysis]
"""
classname = mutf8.MUTF8String.from_str(classname).bytes
methodname = mutf8.MUTF8String.from_str(methodname).bytes
descriptor = mutf8.MUTF8String.from_str(descriptor).bytes
for cname, c in self.classes.items():
if re.match(classname, cname):
if re.match(classname, cname.bytes):
for m in c.get_methods():
z = m.get_method()
# TODO is it even possible that an internal class has
# external methods? Maybe we should check for ExternalClass
# instead...
if no_external and isinstance(z, ExternalMethod):
continue
if re.match(methodname, z.get_name()) and \
re.match(descriptor, z.get_descriptor()) and \
if re.match(methodname, z.get_name().bytes) and \
re.match(descriptor, z.get_descriptor().bytes) and \
re.match(accessflags, z.get_access_flags_string()):
yield m

Expand All @@ -1542,8 +1546,9 @@ def find_strings(self, string=".*"):
:param string: regular expression for the string to search for
:rtype: Iterator[StringAnalysis]
"""
string = mutf8.MUTF8String.from_str(string).bytes
for s, sa in self.strings.items():
if re.match(string, s):
if re.match(string, s.bytes):
yield sa

def find_fields(self, classname=".*", fieldname=".*", fieldtype=".*", accessflags=".*"):
Expand All @@ -1556,12 +1561,15 @@ def find_fields(self, classname=".*", fieldname=".*", fieldtype=".*", accessflag
:param accessflags: regular expression of the access flags
:rtype: Iterator[FieldClassAnalysis]
"""
classname = mutf8.MUTF8String.from_str(classname).bytes
fieldname = mutf8.MUTF8String.from_str(fieldname).bytes
fieldtype = mutf8.MUTF8String.from_str(fieldtype).bytes
for cname, c in self.classes.items():
if re.match(classname, cname):
if re.match(classname, cname.bytes):
for f in c.get_fields():
z = f.get_field()
if re.match(fieldname, z.get_name()) and \
re.match(fieldtype, z.get_descriptor()) and \
if re.match(fieldname, z.get_name().bytes) and \
re.match(fieldtype, z.get_descriptor().bytes) and \
re.match(accessflags, z.get_access_flags_string()):
yield f

Expand Down
60 changes: 0 additions & 60 deletions androguard/core/bytecode.py
Expand Up @@ -593,60 +593,6 @@ def method2json_direct(mx):
return json.dumps(d)


class SV:

def __init__(self, size, buff):
self.__size = size
self.__value = unpack(self.__size, buff)[0]

def _get(self):
return pack(self.__size, self.__value)

def __str__(self):
return "0x%x" % self.__value

def __int__(self):
return self.__value

def get_value_buff(self):
return self._get()

def get_value(self):
return self.__value

def set_value(self, attr):
self.__value = attr


class SVs:

def __init__(self, size, ntuple, buff):
self.__size = size

self.__value = ntuple._make(unpack(self.__size, buff))

def _get(self):
l = []
for i in self.__value._fields:
l.append(getattr(self.__value, i))
return pack(self.__size, *l)

def _export(self):
return [x for x in self.__value._fields]

def get_value_buff(self):
return self._get()

def get_value(self):
return self.__value

def set_value(self, attr):
self.__value = self.__value._replace(**attr)

def __str__(self):
return self.__value.__str__()


def object_to_bytes(obj):
"""
Convert a object to a bytearray or call get_raw() of the object
Expand Down Expand Up @@ -787,9 +733,6 @@ def readat(self, off):
:param int off: starting offset
:rtype: bytearray
"""
if isinstance(off, SV):
off = off.value

return self.__buff[off:]

def read(self, size):
Expand All @@ -800,9 +743,6 @@ def read(self, size):
:param int size: length of bytes to read
:rtype: bytearray
"""
if isinstance(size, SV):
size = size.value

buff = self.__buff[self.__idx:self.__idx + size]
self.__idx += size

Expand Down

0 comments on commit c5104fb

Please sign in to comment.