#!/usr/bin/env vpython
#
# Copyright 2018 The Chromium Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import argparse
import collections
import logging
import re
import subprocess
import sys

DEX_CLASS_NAME_RE = re.compile(r'\'L(?P<class_name>[^;]+);\'')
DEX_METHOD_NAME_RE = re.compile(r'\'(?P<method_name>[^\']+)\'')
DEX_METHOD_TYPE_RE = re.compile( # type descriptor method signature re
    r'\''
    r'\('
    r'(?P<method_params>[^)]*)'
    r'\)'
    r'(?P<method_return_type>[^\']+)'
    r'\'')
DEX_METHOD_LINE_NR_RE = re.compile(r'line=(?P<line_number>\d+)')

PROFILE_METHOD_RE = re.compile(
    r'(?P<tags>[HSP]+)' # tags such as H/S/P
    r'(?P<class_name>L[^;]+;)' # class name in type descriptor format
    r'->(?P<method_name>[^(]+)'
    r'\((?P<method_params>[^)]*)\)'
    r'(?P<method_return_type>.+)')

PROGUARD_CLASS_MAPPING_RE = re.compile(
    r'(?P<original_name>[^ ]+)'
    r' -> '
    r'(?P<obfuscated_name>[^:]+):')
PROGUARD_METHOD_MAPPING_RE = re.compile(
    # line_start:line_end: (optional)
    r'((?P<line_start>\d+):(?P<line_end>\d+):)?'
    r'(?P<return_type>[^ ]+)' # original method return type
    # original method class name (if exists)
    r' (?:(?P<original_method_class>[a-zA-Z_\d.$]+)\.)?'
    r'(?P<original_method_name>[^.\(]+)'
    r'\((?P<params>[^\)]*)\)' # original method params
    r'(?:[^ ]*)' # original method line numbers (ignored)
    r' -> '
    r'(?P<obfuscated_name>.+)') # obfuscated method name

TYPE_DESCRIPTOR_RE = re.compile(
    r'(?P<brackets>\[*)'
    r'(?:'
    r'(?P<class_name>L[^;]+;)'
    r'|'
    r'[VZBSCIJFD]'
    r')')

DOT_NOTATION_MAP = {
    '': '',
    'boolean': 'Z',
    'byte': 'B',
    'void': 'V',
    'short': 'S',
    'char': 'C',
    'int': 'I',
    'long': 'J',
    'float': 'F',
    'double': 'D'
}

class Method(object):
  def __init__(self, name, class_name, param_types=None, return_type=None):
    self.name = name
    self.class_name = class_name
    self.param_types = param_types
    self.return_type = return_type

  def __str__(self):
    return '{}->{}({}){}'.format(self.class_name, self.name,
        self.param_types or '', self.return_type or '')

  def __repr__(self):
    return 'Method<{}->{}({}){}>'.format(self.class_name, self.name,
        self.param_types or '', self.return_type or '')

  def __cmp__(self, other):
    return cmp((self.class_name, self.name, self.param_types, self.return_type),
        (other.class_name, other.name, other.param_types, other.return_type))

  def __hash__(self):
    # only hash name and class_name since other fields may not be set yet.
    return hash((self.name, self.class_name))


class Class(object):
  def __init__(self, name):
    self.name = name
    self._methods = []

  def AddMethod(self, method, line_numbers):
    self._methods.append((method, set(line_numbers)))

  def FindMethodsAtLine(self, method_name, line_start, line_end=None):
    """Searches through dex class for a method given a name and line numbers

    The dex maps methods to line numbers, this method, given the a method name
    in this class as well as a start line and an optional end line (which act as
    hints as to which function in the class is being looked for), returns a list
    of possible matches (or none if none are found).

    Args:
      method_name: name of method being searched for
      line_start: start of hint range for lines in this method
      line_end: end of hint range for lines in this method (optional)

    Returns:
      A list of Method objects that could match the hints given, or None if no
      method is found.
    """
    found_methods = []
    if line_end is None:
      hint_lines = set([line_start])
    else:
      hint_lines = set(range(line_start, line_end+1))

    named_methods = [(method, l) for method, l in self._methods
                     if method.name == method_name]

    if len(named_methods) == 1:
      return [method for method, l in named_methods]
    if len(named_methods) == 0:
      return None

    for method, line_numbers in named_methods:
      if not hint_lines.isdisjoint(line_numbers):
        found_methods.append(method)

    if len(found_methods) > 0:
      if len(found_methods) > 1:
        logging.warning('ambigous methods in dex %s at lines %s in class "%s"',
            found_methods, hint_lines, self.name)
      return found_methods

    for method, line_numbers in named_methods:
      if (max(hint_lines) >= min(line_numbers)
          and min(hint_lines) <= max(line_numbers)):
        found_methods.append(method)

    if len(found_methods) > 0:
      if len(found_methods) > 1:
        logging.warning('ambigous methods in dex %s at lines %s in class "%s"',
            found_methods, hint_lines, self.name)
      return found_methods
    else:
      logging.warning('No method named "%s" in class "%s" is '
                      'mapped to lines %s', method_name, self.name, hint_lines)
      return None


class Profile(object):
  def __init__(self):
    # {Method: set(char)}
    self._methods = collections.defaultdict(set)
    self._classes = []

  def AddMethod(self, method, tags):
    for tag in tags:
      self._methods[method].add(tag)

  def AddClass(self, cls):
    self._classes.append(cls)

  def WriteToFile(self, path):
    with open(path, 'w') as output_profile:
      for cls in sorted(self._classes):
        output_profile.write(cls + '\n')
      for method in sorted(self._methods):
        tags = sorted(self._methods[method])
        line = '{}{}\n'.format(''.join(tags), str(method))
        output_profile.write(line)


class ProguardMapping(object):
  def __init__(self):
    # {Method: set(Method)}
    self._method_mapping = collections.defaultdict(set)
    # {String: String} String is class name in type descriptor format
    self._class_mapping = dict()

  def AddMethodMapping(self, from_method, to_method):
    self._method_mapping[from_method].add(to_method)

  def AddClassMapping(self, from_class, to_class):
    self._class_mapping[from_class] = to_class

  def GetMethodMapping(self, from_method):
    return self._method_mapping.get(from_method)

  def GetClassMapping(self, from_class):
    return self._class_mapping.get(from_class, from_class)

  def MapTypeDescriptor(self, type_descriptor):
    match = TYPE_DESCRIPTOR_RE.search(type_descriptor)
    assert match is not None
    class_name = match.group('class_name')
    if class_name is not None:
      return match.group('brackets') + self.GetClassMapping(class_name)
    # just a native type, return as is
    return match.group()

  def MapTypeDescriptorList(self, type_descriptor_list):
    return TYPE_DESCRIPTOR_RE.sub(
        lambda match: self.MapTypeDescriptor(match.group()),
        type_descriptor_list)


class MalformedLineException(Exception):
  def __init__(self, message, line_number):
    super(MalformedLineException, self).__init__(message)
    self.line_number = line_number

  def __str__(self):
    return self.message + ' at line {}'.format(self.line_number)


class MalformedProguardMappingException(MalformedLineException):
  pass


class MalformedProfileException(MalformedLineException):
  pass


def _RunDexDump(dexdump_path, dex_file_path):
  return subprocess.check_output([dexdump_path, dex_file_path]).splitlines()


def _ReadFile(file_path):
  with open(file_path, 'r') as f:
    return f.readlines()


def _ToTypeDescriptor(dot_notation):
  """Parses a dot notation type and returns it in type descriptor format

  eg:
  org.chromium.browser.ChromeActivity -> Lorg/chromium/browser/ChromeActivity;
  boolean -> Z
  int[] -> [I

  Args:
    dot_notation: trimmed string with a single type in dot notation format

  Returns:
    A string with the type in type descriptor format
  """
  dot_notation = dot_notation.strip()
  prefix = ''
  while dot_notation.endswith('[]'):
    prefix += '['
    dot_notation = dot_notation[:-2]
  if dot_notation in DOT_NOTATION_MAP:
    return prefix + DOT_NOTATION_MAP[dot_notation]
  return prefix + 'L' + dot_notation.replace('.', '/') + ';'


def _DotNotationListToTypeDescriptorList(dot_notation_list_string):
  """Parses a param list of dot notation format and returns it in type
  descriptor format

  eg:
  org.chromium.browser.ChromeActivity,boolean,int[] ->
      Lorg/chromium/browser/ChromeActivity;Z[I

  Args:
    dot_notation_list_string: single string with multiple comma separated types
                              in dot notation format

  Returns:
    A string with the param list in type descriptor format
  """
  return ''.join(_ToTypeDescriptor(param) for param in
      dot_notation_list_string.split(','))


def ProcessDex(dex_dump):
  """Parses dexdump output returning a dict of class names to Class objects

  Parses output of the dexdump command on a dex file and extracts information
  about classes and their respective methods and which line numbers a method is
  mapped to.

  Methods that are not mapped to any line number are ignored and not listed
  inside their respective Class objects.

  Args:
    dex_dump: An array of lines of dexdump output

  Returns:
    A dict that maps from class names in type descriptor format (but without the
    surrounding 'L' and ';') to Class objects.
  """
  # class_name: Class
  classes_by_name = {}
  current_class = None
  current_method = None
  reading_positions = False
  reading_methods = False
  method_line_numbers = []
  for line in dex_dump:
    line = line.strip()
    if line.startswith('Class descriptor'):
      # New class started, no longer reading methods.
      reading_methods = False
      current_class = Class(DEX_CLASS_NAME_RE.search(line).group('class_name'))
      classes_by_name[current_class.name] = current_class
    elif (line.startswith('Direct methods')
          or line.startswith('Virtual methods')):
      reading_methods = True
    elif reading_methods and line.startswith('name'):
      assert current_class is not None
      current_method = Method(
          DEX_METHOD_NAME_RE.search(line).group('method_name'),
          "L" + current_class.name + ";")
    elif reading_methods and line.startswith('type'):
      assert current_method is not None
      match = DEX_METHOD_TYPE_RE.search(line)
      current_method.param_types = match.group('method_params')
      current_method.return_type = match.group('method_return_type')
    elif line.startswith('positions'):
      assert reading_methods
      reading_positions = True
      method_line_numbers = []
    elif reading_positions and line.startswith('0x'):
      line_number = DEX_METHOD_LINE_NR_RE.search(line).group('line_number')
      method_line_numbers.append(int(line_number))
    elif reading_positions and line.startswith('locals'):
      if len(method_line_numbers) > 0:
        current_class.AddMethod(current_method, method_line_numbers)
      # finished reading method line numbers
      reading_positions = False
  return classes_by_name


def ProcessProguardMapping(proguard_mapping_lines, dex):
  """Parses a proguard mapping file

  This takes proguard mapping file lines and then uses the obfuscated dex to
  create a mapping of unobfuscated methods to obfuscated ones and vice versa.

  The dex is used because the proguard mapping file only has the name of the
  obfuscated methods but not their signature, thus the dex is read to look up
  which method with a specific name was mapped to the lines mentioned in the
  proguard mapping file.

  Args:
    proguard_mapping_lines: Array of strings, each is a line from the proguard
                            mapping file (in order).
    dex: a dict of class name (in type descriptor format but without the
         enclosing 'L' and ';') to a Class object.
  Returns:
    Two dicts the first maps from obfuscated methods to a set of non-obfuscated
    ones. It also maps the obfuscated class names to original class names, both
    in type descriptor format (with the enclosing 'L' and ';')
  """
  mapping = ProguardMapping()
  reverse_mapping = ProguardMapping()
  to_be_obfuscated = []
  current_class_orig = None
  current_class_obfs = None
  for index, line in enumerate(proguard_mapping_lines):
    if line.strip() == '':
      continue
    if not line.startswith(' '):
      match = PROGUARD_CLASS_MAPPING_RE.search(line)
      if match is None:
        raise MalformedProguardMappingException(
            'Malformed class mapping', index)
      current_class_orig = match.group('original_name')
      current_class_obfs = match.group('obfuscated_name')
      mapping.AddClassMapping(_ToTypeDescriptor(current_class_obfs),
                              _ToTypeDescriptor(current_class_orig))
      reverse_mapping.AddClassMapping(_ToTypeDescriptor(current_class_orig),
                                      _ToTypeDescriptor(current_class_obfs))
      continue

    assert current_class_orig is not None
    assert current_class_obfs is not None
    line = line.strip()
    match = PROGUARD_METHOD_MAPPING_RE.search(line)
    # check if is a method mapping (we ignore field mappings)
    if match is not None:
      # check if this line is an inlining by reading ahead 1 line.
      if index + 1 < len(proguard_mapping_lines):
        next_match = PROGUARD_METHOD_MAPPING_RE.search(
            proguard_mapping_lines[index+1].strip())
        if (next_match and match.group('line_start') is not None
            and next_match.group('line_start') == match.group('line_start')
            and next_match.group('line_end') == match.group('line_end')):
          continue # This is an inlining, skip

      original_method = Method(
          match.group('original_method_name'),
          _ToTypeDescriptor(
              match.group('original_method_class') or current_class_orig),
          _DotNotationListToTypeDescriptorList(match.group('params')),
          _ToTypeDescriptor(match.group('return_type')))

      if match.group('line_start') is not None:
        obfs_methods = (dex[current_class_obfs.replace('.', '/')]
            .FindMethodsAtLine(
                match.group('obfuscated_name'),
                int(match.group('line_start')),
                int(match.group('line_end'))))

        if obfs_methods is None:
          continue

        for obfs_method in obfs_methods:
          mapping.AddMethodMapping(obfs_method, original_method)
          reverse_mapping.AddMethodMapping(original_method, obfs_method)
      else:
        to_be_obfuscated.append(
            (original_method, match.group('obfuscated_name')))

  for original_method, obfuscated_name in to_be_obfuscated:
    obfuscated_method = Method(
        obfuscated_name,
        reverse_mapping.GetClassMapping(original_method.class_name),
        reverse_mapping.MapTypeDescriptorList(original_method.param_types),
        reverse_mapping.MapTypeDescriptor(original_method.return_type))
    mapping.AddMethodMapping(obfuscated_method, original_method)
    reverse_mapping.AddMethodMapping(original_method, obfuscated_method)
  return mapping, reverse_mapping


def ProcessProfile(input_profile, proguard_mapping):
  """Parses an android profile and uses the proguard mapping to (de)obfuscate it

  This takes the android profile lines and for each method or class for the
  profile, it uses the mapping to either obfuscate or deobfuscate (based on the
  provided mapping) and returns a Profile object that stores this information.

  Args:
    input_profile: array of lines of the input profile
    proguard_mapping: a proguard mapping that would map from the classes and
                      methods in the input profile to the classes and methods
                      that should be in the output profile.

  Returns:
    A Profile object that stores the information (ie list of mapped classes and
    methods + tags)
  """
  profile = Profile()
  for index, line in enumerate(input_profile):
    line = line.strip()
    if line.startswith('L'):
      profile.AddClass(proguard_mapping.GetClassMapping(line))
      continue
    match = PROFILE_METHOD_RE.search(line)
    if not match:
      raise MalformedProfileException("Malformed line", index)

    method = Method(
        match.group('method_name'),
        match.group('class_name'),
        match.group('method_params'),
        match.group('method_return_type'))

    mapped_methods = proguard_mapping.GetMethodMapping(method)
    if mapped_methods is None:
      logging.warning('No method matching "%s" has been found in the proguard '
                      'mapping file', method)
      continue

    for original_method in mapped_methods:
      profile.AddMethod(original_method, match.group('tags'))

  return profile


def ObfuscateProfile(nonobfuscated_profile, dex_file, proguard_mapping,
                     dexdump_path, output_filename):
  """Helper method for obfuscating a profile.

  Args:
    nonobfuscated_profile: a profile with nonobfuscated symbols.
    dex_file: path to the dex file matching the mapping.
    proguard_mapping: a mapping from nonobfuscated to obfuscated symbols used
      in the dex file.
    dexdump_path: path to the dexdump utility.
    output_filename: output filename in which to write the obfuscated profile.
  """
  dexinfo = ProcessDex(_RunDexDump(dexdump_path, dex_file))
  _, reverse_mapping = ProcessProguardMapping(
      _ReadFile(proguard_mapping), dexinfo)
  obfuscated_profile = ProcessProfile(
      _ReadFile(nonobfuscated_profile), reverse_mapping)
  obfuscated_profile.WriteToFile(output_filename)


def main(args):
  parser = argparse.ArgumentParser()
  parser.add_argument(
      '--dexdump-path',
      required=True,
      help='Path to dexdump binary.')
  parser.add_argument(
      '--dex-path',
      required=True,
      help='Path to dex file corresponding to the proguard mapping file.')
  parser.add_argument(
      '--proguard-mapping-path',
      required=True,
      help='Path to input proguard mapping file corresponding to the dex file.')
  parser.add_argument(
      '--output-profile-path',
      required=True,
      help='Path to output profile.')
  parser.add_argument(
      '--input-profile-path',
      required=True,
      help='Path to output profile.')
  parser.add_argument(
      '--verbose',
      action='store_true',
      default=False,
      help='Print verbose output.')
  obfuscation = parser.add_mutually_exclusive_group(required=True)
  obfuscation.add_argument('--obfuscate', action='store_true',
      help='Indicates to output an obfuscated profile given a deobfuscated '
     'one.')
  obfuscation.add_argument('--deobfuscate', dest='obfuscate',
      action='store_false', help='Indicates to output a deobfuscated profile '
      'given an obfuscated one.')
  options = parser.parse_args(args)

  if options.verbose:
    log_level = logging.WARNING
  else:
    log_level = logging.ERROR
  logging.basicConfig(format='%(levelname)s: %(message)s', level=log_level)

  dex = ProcessDex(_RunDexDump(options.dexdump_path, options.dex_path))
  proguard_mapping, reverse_proguard_mapping = ProcessProguardMapping(
      _ReadFile(options.proguard_mapping_path), dex)
  if options.obfuscate:
    profile = ProcessProfile(
        _ReadFile(options.input_profile_path),
        reverse_proguard_mapping)
  else:
    profile = ProcessProfile(
        _ReadFile(options.input_profile_path),
        proguard_mapping)
  profile.WriteToFile(options.output_profile_path)


if __name__ == '__main__':
  main(sys.argv[1:])
