class Undexguard

Constants

BYTES_DECRYPT
MODIFIER
MULTI_BYTES_DECRYPT
STRING_LOOKUP_1INT
STRING_LOOKUP_3INT

Attributes

optimizations[R]

Public Class Methods

new(driver, smali_files, methods) click to toggle source
# File lib/dex-oracle/plugins/undexguard.rb, line 54
def initialize(driver, smali_files, methods)
  @driver = driver
  @smali_files = smali_files
  @methods = methods
  @optimizations = Hash.new(0)
end

Public Instance Methods

process() click to toggle source
# File lib/dex-oracle/plugins/undexguard.rb, line 61
def process
  method_to_target_to_contexts = {}
  @methods.each do |method|
    logger.info("Undexguarding #{method.descriptor} - stage 1/2")
    target_to_contexts = {}
    target_to_contexts.merge!(lookup_strings_3int(method))
    target_to_contexts.merge!(lookup_strings_1int(method))
    target_to_contexts.merge!(decrypt_bytes(method))
    target_to_contexts.map { |_, v| v.uniq! }
    method_to_target_to_contexts[method] = target_to_contexts unless target_to_contexts.empty?
  end

  made_changes = Plugin.apply_batch(@driver, method_to_target_to_contexts, MODIFIER)

  @methods.each do |method|
    logger.info("Undexguarding #{method.descriptor} - stage 2/2")
    made_changes |= decrypt_multi_bytes(method)
  end

  made_changes
end

Private Instance Methods

array_string_to_array(str) click to toggle source
# File lib/dex-oracle/plugins/undexguard.rb, line 152
def array_string_to_array(str)
  if str =~ /\A\[(?:\d+(?:,\d+)*)?\]\z/
    str = eval(str)
  else
    raise "Output is not in byte format; this frightens me: #{str}"
  end
  str
end
decrypt_bytes(method) click to toggle source
# File lib/dex-oracle/plugins/undexguard.rb, line 115
def decrypt_bytes(method)
  target_to_contexts = {}
  matches = method.body.scan(BYTES_DECRYPT)
  @optimizations[:string_decrypts] += matches.size if matches
  matches.each do |original, encrypted, class_name, method_signature, out_reg|
    target = @driver.make_target(
      class_name, method_signature, encrypted.bytes.to_a
    )
    target_to_contexts[target] = [] unless target_to_contexts.key?(target)
    target_to_contexts[target] << [original, out_reg]
  end

  target_to_contexts
end
decrypt_multi_bytes(method) click to toggle source
# File lib/dex-oracle/plugins/undexguard.rb, line 130
def decrypt_multi_bytes(method)
  target_to_contexts = {}
  target_id_to_output = {}
  matches = method.body.scan(MULTI_BYTES_DECRYPT)
  @optimizations[:string_decrypts] += matches.size if matches
  matches.each do |original, iv_str, out_reg, iv_class_name, iv_method_signature, iv2_str, iv2_class_name, iv2_method_signature, dec_class_name, dec_method_signature|
    iv_bytes = @driver.run(iv_class_name, iv_method_signature, iv_str)
    enc_bytes = @driver.run(iv2_class_name, iv2_method_signature, iv_bytes, iv2_str)
    dec_bytes = @driver.run(dec_class_name, dec_method_signature, enc_bytes)
    dec_array = array_string_to_array(dec_bytes)
    dec_string = dec_array.pack('U*')

    target = { id: Digest::SHA256.hexdigest(original) }
    target_id_to_output[target[:id]] = ['success', dec_string]
    target_to_contexts[target] = [] unless target_to_contexts.key?(target)
    target_to_contexts[target] << [original, out_reg]
  end

  method_to_target_to_contexts = { method => target_to_contexts }
  Plugin.apply_outputs(target_id_to_output, method_to_target_to_contexts, MODIFIER)
end
lookup_strings_1int(method) click to toggle source
# File lib/dex-oracle/plugins/undexguard.rb, line 100
def lookup_strings_1int(method)
  target_to_contexts = {}
  matches = method.body.scan(STRING_LOOKUP_1INT)
  @optimizations[:string_lookups] += matches.size if matches
  matches.each do |original, arg1, class_name, method_signature, out_reg|
    target = @driver.make_target(
      class_name, method_signature, arg1.to_i(16)
    )
    target_to_contexts[target] = [] unless target_to_contexts.key?(target)
    target_to_contexts[target] << [original, out_reg]
  end

  target_to_contexts
end
lookup_strings_3int(method) click to toggle source
# File lib/dex-oracle/plugins/undexguard.rb, line 85
def lookup_strings_3int(method)
  target_to_contexts = {}
  matches = method.body.scan(STRING_LOOKUP_3INT)
  @optimizations[:string_lookups] += matches.size if matches
  matches.each do |original, arg1, arg2, arg3, class_name, method_signature, out_reg|
    target = @driver.make_target(
      class_name, method_signature, arg1.to_i(16), arg2.to_i(16), arg3.to_i(16)
    )
    target_to_contexts[target] = [] unless target_to_contexts.key?(target)
    target_to_contexts[target] << [original, out_reg]
  end

  target_to_contexts
end