android_parser 2.5.1 → 2.6.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8360af54a4093e8cc95844b8b7419e3190aed92f5aa6c832f0fd4f7e8ccd2f53
4
- data.tar.gz: 1b8a9172fdf2b4f18c43cb0a342aa5244f7ad109cbfc8b8995d74d6de9fc34a9
3
+ metadata.gz: 5a455cf668b1e1fbae27b208a872c304ac7ff60987034c529aa93c676b3e4348
4
+ data.tar.gz: 5089aec3a63dec1766ae3c981442c2a6fa9500f1351d0e989552e84047309443
5
5
  SHA512:
6
- metadata.gz: 393956811a1cfcb6bd043cdc8c6494a1760a0558d6d12ce157ee9e08b67035499f702e15cf8d6baa7971572eb616c0de28ebc92003a4e9a32c18541eb82b7f7b
7
- data.tar.gz: a7998f5d5e71b889c083f6b1d73f4d277bd7aecd6c412a5d4b14dc10bccf1104472dffde03c2a2280071f88c846906f15c80991d73689f2dd957a46270ac3fbf
6
+ metadata.gz: b4e6104d2a29750902a79871b5a3e2750ea3ea3a8fdcde709870950ca93ddeaa2299f481c393be9556e21378a88c843afe8b9123b338c7a7e7c204a2800c6b99
7
+ data.tar.gz: 9474805fe13212f5193817cf0bc22b33163211232ec01cf4ad60b65eb4713992d701f3883f87241eb2d8b532d00397d6c641c167b19db4b8d71fc314bf87d352
@@ -0,0 +1,15 @@
1
+ name: Create Release
2
+ on:
3
+ push:
4
+ tags:
5
+ - "v*"
6
+
7
+ jobs:
8
+ create:
9
+ runs-on: ubuntu-latest
10
+ steps:
11
+ - name: Create Release
12
+ uses: softprops/action-gh-release@v1
13
+ if: startsWith(github.ref, 'refs/tags/')
14
+ env:
15
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
data/Gemfile CHANGED
@@ -3,8 +3,7 @@ source 'http://rubygems.org'
3
3
  # Specify your gem's dependencies in android_parser.gemspec
4
4
  gemspec
5
5
 
6
- # group :development do
7
- # gem 'awesome_print'
8
- # gem 'debase'
9
- # gem 'ruby-debug-ide'
10
- # end
6
+ group :development do
7
+ gem 'awesome_print'
8
+ gem 'debug'
9
+ end
data/README.md CHANGED
@@ -55,7 +55,7 @@ icons.each do |name, data|
55
55
  end
56
56
  ```
57
57
 
58
- #### Extract signature and certificate information from Apk (since v0.7.0)
58
+ #### Extract v1 signature and certificate information from Apk (since v0.7.0)
59
59
 
60
60
  ```ruby
61
61
  apk = Android::Apk.new('sample.apk')
@@ -5,7 +5,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'android_parser'
8
- spec.version = '2.5.1'
8
+ spec.version = '2.6.0'
9
9
  spec.authors = ['SecureBrain', 'icyleaf']
10
10
  spec.email = ['info@securebrain.co.jp', 'icyleaf.cn@gmail.com']
11
11
  spec.platform = Gem::Platform::RUBY
data/lib/android/apk.rb CHANGED
@@ -189,7 +189,7 @@ module Android
189
189
  # @return [nil] when label is not found
190
190
  # @deprecated move to {Android::Manifest#label}
191
191
  # @since 0.6.0
192
- def label(lang=nil)
192
+ def label(lang = nil)
193
193
  @manifest.label
194
194
  end
195
195
 
@@ -200,25 +200,63 @@ module Android
200
200
  @layouts ||= Layout.collect_layouts(self) # lazy parse
201
201
  end
202
202
 
203
- # apk's signature information
203
+ # apk's v1 signature information
204
204
  # @return [Hash{ String => OpenSSL::PKCS7 } ] key: sign file path, value: signature
205
205
  # @since 0.7.0
206
206
  def signs
207
- signs = {}
208
- self.each_file do |path, data|
209
- # find META-INF/xxx.{RSA|DSA}
210
- next unless path =~ /^META-INF\// && data.unpack("CC") == [0x30, 0x82]
211
- signs[path] = OpenSSL::PKCS7.new(data)
212
- end
213
- signs
207
+ @signs ||= lambda {
208
+ signs = {}
209
+ self.each_file do |path, data|
210
+ # find META-INF/xxx.{RSA|DSA|EC}
211
+ next unless path =~ /^META-INF\// && data.unpack("CC") == [0x30, 0x82]
212
+
213
+ signs[path] = OpenSSL::PKCS7.new(data)
214
+ end
215
+ signs
216
+ }.call
214
217
  end
215
218
 
216
- # certificate info which is used for signing
219
+ # v1 certificate info which is used for signing
217
220
  # @return [Hash{String => OpenSSL::X509::Certificate }] key: sign file path, value: first certficate in the sign file
218
221
  # @since 0.7.0
219
222
  def certificates
220
- return Hash[self.signs.map{|path, sign| [path, sign.certificates.first] }]
223
+ @certificates ||= Hash[self.signs.map{|path, sign| [path, sign.certificates.first] }]
224
+ end
225
+
226
+ # detect if use kotlin language (may be third-party sdk or not)
227
+ # @return [Boolean]
228
+ # @since 2.6.0
229
+ def kotlin?
230
+ @kotlin ||= kotlin_file? || kotlin_classes?
221
231
  end
232
+
233
+ private
234
+
235
+ def kotlin_file?
236
+ KOTLIN_FILES.any? do |file|
237
+ begin
238
+ entry(file)
239
+ rescue
240
+ next
241
+ end
242
+ end
243
+ end
244
+
245
+ def kotlin_classes?
246
+ @dex.classes.any? do |class_info|
247
+ class_info.type.start_with?('kotlin.') ||
248
+ class_info.type.start_with?('kotlinx.')
249
+ end
250
+ end
251
+
252
+ KOTLIN_FILES = [
253
+ 'kotlin-tooling-metadata.json',
254
+ 'kotlin/kotlin.kotlin_builtins',
255
+ 'META-INF/kotlinx_coroutines_android.version',
256
+ 'META-INF/kotlinx_coroutines_core.version',
257
+ 'META-INF/services/kotlinx.coroutines.CoroutineExceptionHandler',
258
+ 'META-INF/services/kotlinx.coroutines.internal.MainDispatcherFactory'
259
+ ].freeze
222
260
  end
223
261
  end
224
262
 
@@ -29,16 +29,32 @@ module Android
29
29
  # @return [DexObject::ClassDefItem]
30
30
  attr_reader :class_def
31
31
 
32
+ # return full namespace of class
33
+ #
34
+ # sample value like `Landroidx/activity/Cancellable;`
35
+ #
36
+ # @return [String] class name
32
37
  def name
33
- @dex.type_resolve(@class_def[:class_idx])
38
+ @name ||= @dex.type_resolve(@class_def[:class_idx])
34
39
  end
40
+
35
41
  def super_class
36
- if @class_def[:superclass_idx] != NO_INDEX
37
- @super_class = @dex.type_resolve(@class_def[:superclass_idx])
38
- else
39
- nil
40
- end
42
+ @super_class ||= if @class_def[:superclass_idx] != NO_INDEX
43
+ @dex.type_resolve(@class_def[:superclass_idx])
44
+ else
45
+ nil
46
+ end
47
+ end
48
+
49
+ # Convert name to human readable string
50
+ #
51
+ # From `Landroidx/activity/Cancellable;` to `androidx.activity.Cancellable`
52
+ #
53
+ # @return [String] human readable name
54
+ def type
55
+ @type ||= name.gsub('/', '.')[1..-2]
41
56
  end
57
+
42
58
  # @param [Dex::ClassDefItem] class_def
43
59
  # @param [Dex] dex dex class instance
44
60
  def initialize(class_def, dex)
@@ -62,6 +78,7 @@ module Android
62
78
  end
63
79
 
64
80
  private
81
+
65
82
  def cls2info(arr, cls, idx_key)
66
83
  idx = 0
67
84
  ret = []
@@ -10,7 +10,7 @@ module Android
10
10
  # <activity>, <service>, <receiver> or <provider> element in <application> element of the manifest file.
11
11
  class Component
12
12
  # component types
13
- TYPES = ['activity', 'activity-alias', 'service', 'receiver', 'provider', 'application']
13
+ TYPES = ['activity', 'activity-alias', 'service', 'receiver', 'provider', 'application', 'queries']
14
14
 
15
15
  # the element is valid Component element or not
16
16
  # @param [REXML::Element] elem xml element
@@ -322,6 +322,99 @@ module Android
322
322
  end
323
323
  end
324
324
 
325
+ # <intent>, <service>, <receiver> or <provider> element in <application> element of the manifest file.
326
+ class QueriesComponent
327
+ # component types
328
+ TYPES = ['package', 'intent', 'provider']
329
+
330
+ # @return [String] type string in TYPES
331
+ attr_reader :type
332
+ # @return [Manifest::Queries::Package]
333
+ attr_reader :packages
334
+ # @return [Array<Manifest::Queries::Intent>]
335
+ attr_reader :intents
336
+ # @return [Array<Manifest::Queries::Provider>]
337
+ attr_reader :providers
338
+ # @return [REXML::Element]
339
+ attr_reader :elem
340
+
341
+ # @param [REXML::Element] elem target element
342
+ # @raise [ArgumentError] when elem is invalid.
343
+ def initialize(elem)
344
+ raise ArgumentError unless Component.valid?(elem)
345
+
346
+ @elem = elem
347
+ @type = elem.name
348
+ @packages = parse_packages
349
+ @intents = parse_intents
350
+ @providers = parse_providers
351
+ end
352
+
353
+ private
354
+
355
+ def parse_packages
356
+ packages = []
357
+ return packages if @elem.elements['package'].nil?
358
+
359
+ @elem.each_element('package') do |package|
360
+ packages << Android::Manifest::Queries::Package.new(package)
361
+ end
362
+
363
+ packages
364
+ end
365
+
366
+ def parse_intents
367
+ intents = []
368
+ return intents if @elem.elements['intent'].nil?
369
+
370
+ @elem.each_element('intent') do |intent|
371
+ next if intent&.elements&.empty?
372
+ next unless Android::Manifest::Queries::Intent.valid?(intent)
373
+
374
+ intent = Android::Manifest::Queries::Intent.new(intent)
375
+ intents << intent unless intent.empty?
376
+ end
377
+
378
+ intents
379
+ end
380
+
381
+ def parse_providers
382
+ providers = []
383
+ return providers if @elem.elements['provider'].nil?
384
+
385
+ @elem.each_element('provider') do |provider|
386
+ providers << Android::Manifest::Queries::Provider.new(provider)
387
+ end
388
+
389
+ providers
390
+ end
391
+ end
392
+
393
+ class Queries < QueriesComponent
394
+ class Intent < Android::Manifest::IntentFilter; end
395
+ class Provider < Android::Manifest::Provider
396
+ def authorities
397
+ @authorities ||= @elem.attributes['authorities']
398
+ end
399
+ end
400
+
401
+ class Package
402
+ # @return [String] action name of queries
403
+ attr_reader :name
404
+ # @return [String] action type of intent-filter
405
+ attr_reader :type
406
+
407
+ def initialize(elem)
408
+ @type = 'package'
409
+ @name = elem.attributes['name']
410
+ end
411
+ end
412
+
413
+ def self.valid?(elem)
414
+ elem&.name == 'queries'
415
+ end
416
+ end
417
+
325
418
  #################################
326
419
  # Manifest class definitions
327
420
  #################################
@@ -370,6 +463,13 @@ module Android
370
463
  components
371
464
  end
372
465
 
466
+ # Returns the manifest's queries element or nil, if there isn't any.
467
+ # @return [Android::Manifest::Queries] the manifest's application element
468
+ def queries
469
+ element = @doc.elements['/manifest/queries']
470
+ Queries.new(element) if Queries.valid?(element)
471
+ end
472
+
373
473
  # @return [Array<Android::Manifest::Activity&ActivityAlias>] all activities in the apk
374
474
  # @note return empty array when the manifest include no activities
375
475
  def activities
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: android_parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.1
4
+ version: 2.6.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SecureBrain
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2023-03-09 00:00:00.000000000 Z
12
+ date: 2023-03-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rubyzip
@@ -139,6 +139,7 @@ extra_rdoc_files: []
139
139
  files:
140
140
  - ".github/dependabot.yml"
141
141
  - ".github/workflows/ci.yml"
142
+ - ".github/workflows/create_release.yml"
142
143
  - ".gitignore"
143
144
  - ".rspec"
144
145
  - CHANGELOG.md