Class: Headdesk::Apk

Inherits:
Object
  • Object
show all
Defined in:
lib/headdesk/apk.rb,
lib/headdesk/apk/class.rb,
lib/headdesk/apk/field.rb,
lib/headdesk/apk/method.rb,
lib/headdesk/apk/resources.rb

Overview

Representation of an APK file unpacked by apktool

:reek:TooManyInstanceVariables

Defined Under Namespace

Modules: ExtraMethods Classes: Class, Field, Method, Resources

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(path, manifest_contents = nil, yaml_contents = nil) ⇒ Apk

:reek:TooManyStatements



20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/headdesk/apk.rb', line 20

def initialize(path, manifest_contents = nil, yaml_contents = nil)
  @path = path

  android_manifest_xml = File.join(@path, 'AndroidManifest.xml').freeze
  apktool_yml = File.join(@path, 'apktool.yml').freeze

  throw CliError.new('Path did not contain AndroidManifest.xml') unless File.exist?(android_manifest_xml) || manifest_contents
  throw CliError.new('Path did not contain apktool.yml') unless File.exist?(apktool_yml) || yaml_contents

  @yaml = yaml_contents || YAML.load_file(apktool_yml)
  @sdk_info = @yaml['sdkInfo']
  @resources = Resources.new(@path)

  manifest = Nokogiri::XML(manifest_contents) if manifest_contents
  manifest ||= File.open(android_manifest_xml) do |file|
    Nokogiri::XML(file)
  end

  @android_manifest = manifest.xpath('manifest')
  throw CliError.new('Invalid Android manifest') if @android_manifest.empty?
  @android_manifest = @android_manifest.first
end

Instance Attribute Details

#android_manifestObject (readonly)

Returns the value of attribute android_manifest.



17
18
19
# File 'lib/headdesk/apk.rb', line 17

def android_manifest
  @android_manifest
end

#resourcesObject (readonly)

Returns the value of attribute resources.



17
18
19
# File 'lib/headdesk/apk.rb', line 17

def resources
  @resources
end

#sdk_infoObject (readonly)

Returns the value of attribute sdk_info.



17
18
19
# File 'lib/headdesk/apk.rb', line 17

def sdk_info
  @sdk_info
end

#yamlObject (readonly)

Returns the value of attribute yaml.



17
18
19
# File 'lib/headdesk/apk.rb', line 17

def yaml
  @yaml
end

Instance Method Details

#analyzeObject



43
44
45
46
47
48
49
50
51
52
53
# File 'lib/headdesk/apk.rb', line 43

def analyze
  report = Headdesk::APKReport.new(self)

  Headdesk::Check.for_apk.each do |check_type|
    check = check_type.new(self)
    report << check.process
  end

  # TODO: Associated domains
  report
end

#class?(decl) ⇒ Boolean

:reek:NilCheck



89
90
91
# File 'lib/headdesk/apk.rb', line 89

def class?(decl)
  !find_class(decl).nil?
end

#find_class(decl) ⇒ Object



93
94
95
96
97
98
# File 'lib/headdesk/apk.rb', line 93

def find_class(decl)
  file_name = Dir["#{@path}/smali*/**/#{Class.path_for(decl)}.smali"].first
  return nil unless file_name && File.exist?(file_name)

  Class.new(file_name)
end

#min_sdk(gt_eq) ⇒ Object



84
85
86
# File 'lib/headdesk/apk.rb', line 84

def min_sdk(gt_eq)
  min_sdk_version >= gt_eq
end

#min_sdk_versionObject



76
77
78
# File 'lib/headdesk/apk.rb', line 76

def min_sdk_version
  sdk_info['minSdkVersion'].to_i
end

#target_sdk_versionObject



72
73
74
# File 'lib/headdesk/apk.rb', line 72

def target_sdk_version
  sdk_info['targetSdkVersion'].to_i
end

#targets_sdk(gt_eq) ⇒ Object



80
81
82
# File 'lib/headdesk/apk.rb', line 80

def targets_sdk(gt_eq)
  target_sdk_version >= gt_eq
end

#unity_versionObject



55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
# File 'lib/headdesk/apk.rb', line 55

def unity_version
  unity_assets = File.join(@path, 'assets', 'bin', 'Data').freeze
  return nil unless Dir.exist?(unity_assets)

  asset_file = Dir[File.join(unity_assets, '/*')].first
  return nil unless asset_file

  version_bytes = []
  File.open(asset_file, 'rb') do |file|
    file.read(16) # Throw the first 16 bytes away
    file.read(16).each_byte do |byte|
      version_bytes << byte if byte > 0
    end
    return version_bytes.pack('c*')
  end
end