ruby_apk 0.6.0 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CHANGELOG.md +4 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +49 -14
- data/README.md +21 -2
- data/VERSION +1 -1
- data/lib/android/apk.rb +30 -15
- data/lib/android/axml_parser.rb +1 -2
- data/lib/android/dex.rb +1 -1
- data/lib/android/dex/dex_object.rb +22 -22
- data/lib/android/manifest.rb +23 -5
- data/ruby_apk.gemspec +10 -10
- data/spec/apk_spec.rb +18 -8
- data/spec/axml_parser_spec.rb +21 -0
- data/spec/manifest_spec.rb +13 -1
- metadata +55 -39
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 2daa80cd5d4c7d1f942ca90e35b48214cfe600d3
|
4
|
+
data.tar.gz: ccc5d7a63719fb1c2609971932aadfe5838748dc
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 04786f2bb0ee3d85364ac54a62ccbbe507c9b4ae770b5a8ce8a6c4fcec1889472c1a846b47f9322a917dfd98bece3f35f4e5fa44ed8ffe7d08735300332ad86c
|
7
|
+
data.tar.gz: ba983b958d476173ea8a0b99d50b8646548201388b306bea576297b0a93aba40134c6b4aa7600401b037455df06d1f008eb729ed7da58682630ade7255d45a6a
|
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
@@ -8,8 +8,8 @@ gem "rubyzip"
|
|
8
8
|
# Include everything needed to run rake, tests, features, etc.
|
9
9
|
group :development do
|
10
10
|
gem "rspec", "~> 2.11.0"
|
11
|
-
gem "bundler", "
|
12
|
-
gem "jeweler", "~> 1.
|
11
|
+
gem "bundler", ">= 1.1.5"
|
12
|
+
gem "jeweler", "~> 1.8.7"
|
13
13
|
gem "yard", require: false
|
14
14
|
gem "redcarpet"
|
15
15
|
gem "simplecov", require: false
|
data/Gemfile.lock
CHANGED
@@ -1,36 +1,71 @@
|
|
1
1
|
GEM
|
2
2
|
remote: http://rubygems.org/
|
3
3
|
specs:
|
4
|
+
addressable (2.3.5)
|
5
|
+
builder (3.2.2)
|
4
6
|
diff-lcs (1.1.3)
|
5
|
-
|
6
|
-
|
7
|
+
faraday (0.8.8)
|
8
|
+
multipart-post (~> 1.2.0)
|
9
|
+
git (1.2.6)
|
10
|
+
github_api (0.10.1)
|
11
|
+
addressable
|
12
|
+
faraday (~> 0.8.1)
|
13
|
+
hashie (>= 1.2)
|
14
|
+
multi_json (~> 1.4)
|
15
|
+
nokogiri (~> 1.5.2)
|
16
|
+
oauth2
|
17
|
+
hashie (2.0.5)
|
18
|
+
highline (1.6.19)
|
19
|
+
httpauth (0.2.0)
|
20
|
+
jeweler (1.8.7)
|
21
|
+
builder
|
7
22
|
bundler (~> 1.0)
|
8
23
|
git (>= 1.2.5)
|
24
|
+
github_api (= 0.10.1)
|
25
|
+
highline (>= 1.6.15)
|
26
|
+
nokogiri (= 1.5.10)
|
9
27
|
rake
|
10
|
-
|
11
|
-
|
12
|
-
|
28
|
+
rdoc
|
29
|
+
json (1.8.0)
|
30
|
+
jwt (0.1.8)
|
31
|
+
multi_json (>= 1.5)
|
32
|
+
multi_json (1.8.0)
|
33
|
+
multi_xml (0.5.5)
|
34
|
+
multipart-post (1.2.0)
|
35
|
+
nokogiri (1.5.10)
|
36
|
+
oauth2 (0.9.2)
|
37
|
+
faraday (~> 0.8)
|
38
|
+
httpauth (~> 0.2)
|
39
|
+
jwt (~> 0.1.4)
|
40
|
+
multi_json (~> 1.0)
|
41
|
+
multi_xml (~> 0.5)
|
42
|
+
rack (~> 1.2)
|
43
|
+
rack (1.5.2)
|
44
|
+
rake (10.1.0)
|
45
|
+
rdoc (4.0.1)
|
46
|
+
json (~> 1.4)
|
47
|
+
redcarpet (3.0.0)
|
13
48
|
rspec (2.11.0)
|
14
49
|
rspec-core (~> 2.11.0)
|
15
50
|
rspec-expectations (~> 2.11.0)
|
16
51
|
rspec-mocks (~> 2.11.0)
|
17
52
|
rspec-core (2.11.1)
|
18
|
-
rspec-expectations (2.11.
|
53
|
+
rspec-expectations (2.11.3)
|
19
54
|
diff-lcs (~> 1.1.3)
|
20
|
-
rspec-mocks (2.11.
|
21
|
-
rubyzip (0.
|
22
|
-
simplecov (0.
|
55
|
+
rspec-mocks (2.11.3)
|
56
|
+
rubyzip (1.0.0)
|
57
|
+
simplecov (0.7.1)
|
23
58
|
multi_json (~> 1.0)
|
24
|
-
simplecov-html (~> 0.
|
25
|
-
simplecov-html (0.
|
26
|
-
yard (0.8.2
|
59
|
+
simplecov-html (~> 0.7.1)
|
60
|
+
simplecov-html (0.7.1)
|
61
|
+
yard (0.8.7.2)
|
27
62
|
|
28
63
|
PLATFORMS
|
29
64
|
ruby
|
30
65
|
|
31
66
|
DEPENDENCIES
|
32
|
-
bundler (
|
33
|
-
jeweler (~> 1.
|
67
|
+
bundler (>= 1.1.5)
|
68
|
+
jeweler (~> 1.8.7)
|
34
69
|
redcarpet
|
35
70
|
rspec (~> 2.11.0)
|
36
71
|
rubyzip
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# ruby_apk
|
2
2
|
Android Apk static analysis library for Ruby.
|
3
3
|
|
4
|
+
[](http://badge.fury.io/rb/ruby_apk)
|
4
5
|
[](https://travis-ci.org/SecureBrain/ruby_apk)
|
5
6
|
|
6
7
|
## Requirements
|
@@ -40,11 +41,23 @@ end
|
|
40
41
|
File.open(File.basename(name), 'wb') {|f| f.write data } # save to file.
|
41
42
|
end
|
42
43
|
```
|
43
|
-
|
44
|
+
|
45
|
+
#### Extract signature and certificate information from Apk (since v0.7.0)
|
44
46
|
```ruby
|
45
47
|
apk = Android::Apk.new('sample.apk')
|
46
|
-
|
48
|
+
signs = apk.signs # retrun Hash(key: signature file path, value: OpenSSL::PKCS7)
|
49
|
+
signs.each do |path, sign|
|
50
|
+
puts path # => "MATA-INF/CERT.RSA" or ...
|
51
|
+
puts sign # => "-----BEGIN PKCS7-----\n..." PKCS7 object
|
52
|
+
end
|
53
|
+
|
54
|
+
certs = apk.certificates # retrun Hash(key: signature file path, value: OpenSSL::X509::Certificate)
|
55
|
+
certs.each do |path, cert|
|
56
|
+
puts path # => "MATA-INF/CERT.RSA" or ...
|
57
|
+
puts cert # => "-----BEGIN CERTIFICATE-----\n..." # X509::Certificate object
|
58
|
+
end
|
47
59
|
```
|
60
|
+
Note: Most apks have only one signature and cerficate.
|
48
61
|
|
49
62
|
### Manifest
|
50
63
|
#### Get readable xml
|
@@ -72,6 +85,12 @@ end
|
|
72
85
|
end
|
73
86
|
```
|
74
87
|
|
88
|
+
#### Extract application label string
|
89
|
+
```ruby
|
90
|
+
apk = Android::Apk.new('sample.apk')
|
91
|
+
puts apk.manifest.label
|
92
|
+
```
|
93
|
+
|
75
94
|
### Resource
|
76
95
|
#### Extract resource strings from apk
|
77
96
|
```ruby
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.7.0
|
data/lib/android/apk.rb
CHANGED
@@ -2,6 +2,7 @@ require 'zip/zip' # need rubyzip gem -> doc: http://rubyzip.sourceforge.net/
|
|
2
2
|
require 'digest/md5'
|
3
3
|
require 'digest/sha1'
|
4
4
|
require 'digest/sha2'
|
5
|
+
require 'openssl'
|
5
6
|
|
6
7
|
module Android
|
7
8
|
class NotApkFileError < StandardError; end
|
@@ -48,21 +49,21 @@ module Android
|
|
48
49
|
@bindata.force_encoding(Encoding::ASCII_8BIT)
|
49
50
|
raise NotApkFileError, "manifest file is not found." if @zip.find_entry(MANIFEST).nil?
|
50
51
|
begin
|
51
|
-
@
|
52
|
+
@resource = Android::Resource.new(self.file(RESOURCE))
|
52
53
|
rescue => e
|
53
|
-
$stderr.puts "failed to parse
|
54
|
+
$stderr.puts "failed to parse resource:#{e}"
|
54
55
|
#$stderr.puts e.backtrace
|
55
56
|
end
|
56
57
|
begin
|
57
|
-
@
|
58
|
+
@manifest = Android::Manifest.new(self.file(MANIFEST), @resource)
|
58
59
|
rescue => e
|
59
|
-
$stderr.puts "failed to parse
|
60
|
+
$stderr.puts "failed to parse manifest:#{e}"
|
60
61
|
#$stderr.puts e.backtrace
|
61
62
|
end
|
62
63
|
begin
|
63
|
-
@
|
64
|
+
@dex = Android::Dex.new(self.file(DEX))
|
64
65
|
rescue => e
|
65
|
-
$stderr.puts "failed to parse
|
66
|
+
$stderr.puts "failed to parse dex:#{e}"
|
66
67
|
#$stderr.puts e.backtrace
|
67
68
|
end
|
68
69
|
end
|
@@ -169,24 +170,38 @@ module Android
|
|
169
170
|
# @param [String] lang language code like 'ja', 'cn', ...
|
170
171
|
# @return [String] application label string
|
171
172
|
# @return [nil] when label is not found
|
173
|
+
# @deprecated move to {Android::Manifest#label}
|
172
174
|
# @since 0.6.0
|
173
175
|
def label(lang=nil)
|
174
|
-
|
175
|
-
if /^@(\w+\/\w+)|(0x[0-9a-fA-F]{8})$/ =~ label_id
|
176
|
-
opts = {}
|
177
|
-
opts[:lang] = lang unless lang.nil?
|
178
|
-
@resource.find(label_id, opts)
|
179
|
-
else
|
180
|
-
label_id # include nil
|
181
|
-
end
|
176
|
+
@manifest.label
|
182
177
|
end
|
183
178
|
|
184
179
|
# get screen layout xml datas
|
185
|
-
# @return [Hash{
|
180
|
+
# @return [Hash{ String => Android::Layout }] key: laytout file path, value: layout object
|
186
181
|
# @since 0.6.0
|
187
182
|
def layouts
|
188
183
|
@layouts ||= Layout.collect_layouts(self) # lazy parse
|
189
184
|
end
|
185
|
+
|
186
|
+
# apk's signature information
|
187
|
+
# @return [Hash{ String => OpenSSL::PKCS7 } ] key: sign file path, value: signature
|
188
|
+
# @since 0.7.0
|
189
|
+
def signs
|
190
|
+
signs = {}
|
191
|
+
self.each_file do |path, data|
|
192
|
+
# find META-INF/xxx.{RSA|DSA}
|
193
|
+
next unless path =~ /^META-INF\// && data.unpack("CC") == [0x30, 0x82]
|
194
|
+
signs[path] = OpenSSL::PKCS7.new(data)
|
195
|
+
end
|
196
|
+
signs
|
197
|
+
end
|
198
|
+
|
199
|
+
# certificate info which is used for signing
|
200
|
+
# @return [Hash{String => OpenSSL::X509::Certificate }] key: sign file path, value: first certficate in the sign file
|
201
|
+
# @since 0.7.0
|
202
|
+
def certificates
|
203
|
+
return Hash[self.signs.map{|path, sign| [path, sign.certificates.first] }]
|
204
|
+
end
|
190
205
|
end
|
191
206
|
end
|
192
207
|
|
data/lib/android/axml_parser.rb
CHANGED
@@ -68,7 +68,6 @@ module Android
|
|
68
68
|
end
|
69
69
|
|
70
70
|
|
71
|
-
private
|
72
71
|
# read one word(4byte) as integer
|
73
72
|
# @param [Integer] offset offset from top position. current position is used if ofset is nil
|
74
73
|
# @return [Integer] little endian word value
|
@@ -163,7 +162,7 @@ module Android
|
|
163
162
|
when VAL_TYPE_INT_HEX
|
164
163
|
value = "%#x" % val
|
165
164
|
when VAL_TYPE_INT_BOOLEAN
|
166
|
-
value = ((val
|
165
|
+
value = ((val == 0xFFFFFFFF) || (val==1)) ? true : false
|
167
166
|
else
|
168
167
|
value = "[%#x, flag=%#x]" % [val, flags]
|
169
168
|
end
|
data/lib/android/dex.rb
CHANGED
@@ -5,7 +5,7 @@ require_relative 'dex/utils'
|
|
5
5
|
|
6
6
|
module Android
|
7
7
|
# parsed dex object
|
8
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
8
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
9
9
|
# @attr_reader strings [Array<String>] strings in dex file.
|
10
10
|
class Dex
|
11
11
|
# @return [Dex::Header] dex header information
|
@@ -2,7 +2,7 @@
|
|
2
2
|
module Android
|
3
3
|
class Dex
|
4
4
|
# parsing dex object
|
5
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
5
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
6
6
|
class DexObject
|
7
7
|
# @return [Integer] object size
|
8
8
|
attr_reader :size
|
@@ -106,7 +106,7 @@ module Android
|
|
106
106
|
|
107
107
|
public
|
108
108
|
# header_item
|
109
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
109
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
110
110
|
class Header < DexObject
|
111
111
|
def initialize(data)
|
112
112
|
super(data, 0)
|
@@ -132,7 +132,7 @@ module Android
|
|
132
132
|
end
|
133
133
|
|
134
134
|
# map_list
|
135
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
135
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
136
136
|
class MapList < DexObject
|
137
137
|
private
|
138
138
|
def parse
|
@@ -142,7 +142,7 @@ module Android
|
|
142
142
|
end
|
143
143
|
|
144
144
|
# map_item
|
145
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
145
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
146
146
|
class MapItem < DexObject
|
147
147
|
private
|
148
148
|
def parse
|
@@ -154,7 +154,7 @@ module Android
|
|
154
154
|
end
|
155
155
|
|
156
156
|
# id_list
|
157
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
157
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
158
158
|
class IdsList < DexObject
|
159
159
|
attr_reader :ids_size
|
160
160
|
def initialize(data, off, ids_size)
|
@@ -164,7 +164,7 @@ module Android
|
|
164
164
|
end
|
165
165
|
|
166
166
|
# string_id_item
|
167
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
167
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
168
168
|
class StringIdItem < IdsList
|
169
169
|
private
|
170
170
|
def parse
|
@@ -173,7 +173,7 @@ module Android
|
|
173
173
|
end
|
174
174
|
|
175
175
|
# string_data_item
|
176
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
176
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
177
177
|
class StringDataItem < DexObject
|
178
178
|
def to_s
|
179
179
|
@params[:data]
|
@@ -186,7 +186,7 @@ module Android
|
|
186
186
|
end
|
187
187
|
|
188
188
|
# type_id_item
|
189
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
189
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
190
190
|
class TypeIdItem < IdsList
|
191
191
|
def [](idx)
|
192
192
|
raise ArgumentError if idx >= @params[:descriptor_idx].size or idx < 0
|
@@ -200,7 +200,7 @@ module Android
|
|
200
200
|
end
|
201
201
|
|
202
202
|
# proto_id_item
|
203
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
203
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
204
204
|
class ProtoIdItem < DexObject
|
205
205
|
# return parse data size
|
206
206
|
# @return bytes
|
@@ -217,7 +217,7 @@ module Android
|
|
217
217
|
end
|
218
218
|
|
219
219
|
# field_id_item
|
220
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
220
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
221
221
|
class FieldIdItem < DexObject
|
222
222
|
# return parse data size
|
223
223
|
# @return bytes
|
@@ -234,7 +234,7 @@ module Android
|
|
234
234
|
end
|
235
235
|
|
236
236
|
# method_id_item
|
237
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
237
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
238
238
|
class MethodIdItem < DexObject
|
239
239
|
# return parse data size
|
240
240
|
# @return bytes
|
@@ -250,7 +250,7 @@ module Android
|
|
250
250
|
end
|
251
251
|
|
252
252
|
# class_def_item
|
253
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
253
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
254
254
|
# @!attribute [r] class_data_item
|
255
255
|
# @return [ClassDataItem] class_data_item of this class
|
256
256
|
class ClassDefItem < DexObject
|
@@ -284,7 +284,7 @@ module Android
|
|
284
284
|
end
|
285
285
|
|
286
286
|
# class_data_item
|
287
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
287
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
288
288
|
class ClassDataItem < DexObject
|
289
289
|
private
|
290
290
|
def parse
|
@@ -300,7 +300,7 @@ module Android
|
|
300
300
|
end
|
301
301
|
|
302
302
|
# encoded_field
|
303
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
303
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
304
304
|
class EncodedField < DexObject
|
305
305
|
private
|
306
306
|
def parse
|
@@ -310,7 +310,7 @@ module Android
|
|
310
310
|
end
|
311
311
|
|
312
312
|
# encoded_method
|
313
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
313
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
314
314
|
# @!attribute [r] code_item
|
315
315
|
# @return [CodeItem] code_item of the method
|
316
316
|
class EncodedMethod < DexObject
|
@@ -335,7 +335,7 @@ module Android
|
|
335
335
|
|
336
336
|
|
337
337
|
# type_list
|
338
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
338
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
339
339
|
class TypeList < DexObject
|
340
340
|
private
|
341
341
|
def parse
|
@@ -345,7 +345,7 @@ module Android
|
|
345
345
|
end
|
346
346
|
|
347
347
|
# code_item
|
348
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
348
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
349
349
|
# @!attribute [r] debug_info_item
|
350
350
|
# @return [DebugInfoItem] debug_info_item of this code
|
351
351
|
class CodeItem < DexObject
|
@@ -378,7 +378,7 @@ module Android
|
|
378
378
|
end
|
379
379
|
|
380
380
|
# try_item
|
381
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
381
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
382
382
|
class TryItem < DexObject
|
383
383
|
private
|
384
384
|
def parse
|
@@ -389,7 +389,7 @@ module Android
|
|
389
389
|
end
|
390
390
|
|
391
391
|
# encoded_catch_handler_list
|
392
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
392
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
393
393
|
class EncodedCatchHandlerList < DexObject
|
394
394
|
private
|
395
395
|
def parse
|
@@ -399,7 +399,7 @@ module Android
|
|
399
399
|
end
|
400
400
|
|
401
401
|
# encoded_catch_handler
|
402
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
402
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
403
403
|
class EncodedCatchHandler < DexObject
|
404
404
|
private
|
405
405
|
def parse
|
@@ -410,7 +410,7 @@ module Android
|
|
410
410
|
end
|
411
411
|
|
412
412
|
# encoded_type_addr_pair
|
413
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
413
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
414
414
|
class EncodedTypeAddrPair < DexObject
|
415
415
|
private
|
416
416
|
def parse
|
@@ -420,7 +420,7 @@ module Android
|
|
420
420
|
end
|
421
421
|
|
422
422
|
# debug_info_item
|
423
|
-
# @see http://source.android.com/tech/dalvik/dex-format.html
|
423
|
+
# @see http://source.android.com/devices/tech/dalvik/dex-format.html
|
424
424
|
class DebugInfoItem < DexObject
|
425
425
|
private
|
426
426
|
def parse
|
data/lib/android/manifest.rb
CHANGED
@@ -153,9 +153,10 @@ module Android
|
|
153
153
|
attr_reader :doc
|
154
154
|
|
155
155
|
# @param [String] data binary data of AndroidManifest.xml
|
156
|
-
def initialize(data)
|
156
|
+
def initialize(data, rsc=nil)
|
157
157
|
parser = AXMLParser.new(data)
|
158
158
|
@doc = parser.parse
|
159
|
+
@rsc = rsc
|
159
160
|
end
|
160
161
|
|
161
162
|
# used permission array
|
@@ -195,8 +196,16 @@ module Android
|
|
195
196
|
|
196
197
|
# application version name
|
197
198
|
# @return [String]
|
198
|
-
def version_name
|
199
|
-
@doc.root.attributes['versionName']
|
199
|
+
def version_name(lang=nil)
|
200
|
+
vername = @doc.root.attributes['versionName']
|
201
|
+
unless @rsc.nil?
|
202
|
+
if /^@(\w+\/\w+)|(0x[0-9a-fA-F]{8})$/ =~ vername
|
203
|
+
opts = {}
|
204
|
+
opts[:lang] = lang unless lang.nil?
|
205
|
+
vername = @rsc.find(vername, opts)
|
206
|
+
end
|
207
|
+
end
|
208
|
+
vername
|
200
209
|
end
|
201
210
|
|
202
211
|
# @return [Integer] minSdkVersion in uses element
|
@@ -205,9 +214,11 @@ module Android
|
|
205
214
|
end
|
206
215
|
|
207
216
|
# application label
|
208
|
-
# @
|
217
|
+
# @param [String] lang language code like 'ja', 'cn', ...
|
218
|
+
# @return [String] application label string(if resouce is provided), or label resource id
|
219
|
+
# @return [nil] when label is not found
|
209
220
|
# @since 0.5.1
|
210
|
-
def label
|
221
|
+
def label(lang=nil)
|
211
222
|
label = @doc.elements['/manifest/application'].attributes['label']
|
212
223
|
if label.nil?
|
213
224
|
# application element has no label attributes.
|
@@ -215,6 +226,13 @@ module Android
|
|
215
226
|
activities = @doc.elements['/manifest/application'].find{|e| e.name == 'activity' && !e.attributes['label'].nil? }
|
216
227
|
label = activities.nil? ? nil : activities.first.attributes['label']
|
217
228
|
end
|
229
|
+
unless @rsc.nil?
|
230
|
+
if /^@(\w+\/\w+)|(0x[0-9a-fA-F]{8})$/ =~ label
|
231
|
+
opts = {}
|
232
|
+
opts[:lang] = lang unless lang.nil?
|
233
|
+
label = @rsc.find(label, opts)
|
234
|
+
end
|
235
|
+
end
|
218
236
|
label
|
219
237
|
end
|
220
238
|
|
data/ruby_apk.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = "ruby_apk"
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.7.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["SecureBrain"]
|
12
|
-
s.date = "2013-
|
12
|
+
s.date = "2013-09-24"
|
13
13
|
s.description = "static analysis tool for android apk"
|
14
14
|
s.email = "info@securebrain.co.jp"
|
15
15
|
s.extra_rdoc_files = [
|
@@ -61,25 +61,25 @@ Gem::Specification.new do |s|
|
|
61
61
|
s.homepage = "https://github.com/SecureBrain/ruby_apk/"
|
62
62
|
s.licenses = ["MIT"]
|
63
63
|
s.require_paths = ["lib"]
|
64
|
-
s.rubygems_version = "
|
64
|
+
s.rubygems_version = "2.0.6"
|
65
65
|
s.summary = "static analysis tool for android apk"
|
66
66
|
|
67
67
|
if s.respond_to? :specification_version then
|
68
|
-
s.specification_version =
|
68
|
+
s.specification_version = 4
|
69
69
|
|
70
70
|
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
71
71
|
s.add_runtime_dependency(%q<rubyzip>, [">= 0"])
|
72
72
|
s.add_development_dependency(%q<rspec>, ["~> 2.11.0"])
|
73
|
-
s.add_development_dependency(%q<bundler>, ["
|
74
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.
|
73
|
+
s.add_development_dependency(%q<bundler>, [">= 1.1.5"])
|
74
|
+
s.add_development_dependency(%q<jeweler>, ["~> 1.8.7"])
|
75
75
|
s.add_development_dependency(%q<yard>, [">= 0"])
|
76
76
|
s.add_development_dependency(%q<redcarpet>, [">= 0"])
|
77
77
|
s.add_development_dependency(%q<simplecov>, [">= 0"])
|
78
78
|
else
|
79
79
|
s.add_dependency(%q<rubyzip>, [">= 0"])
|
80
80
|
s.add_dependency(%q<rspec>, ["~> 2.11.0"])
|
81
|
-
s.add_dependency(%q<bundler>, ["
|
82
|
-
s.add_dependency(%q<jeweler>, ["~> 1.
|
81
|
+
s.add_dependency(%q<bundler>, [">= 1.1.5"])
|
82
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
|
83
83
|
s.add_dependency(%q<yard>, [">= 0"])
|
84
84
|
s.add_dependency(%q<redcarpet>, [">= 0"])
|
85
85
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
@@ -87,8 +87,8 @@ Gem::Specification.new do |s|
|
|
87
87
|
else
|
88
88
|
s.add_dependency(%q<rubyzip>, [">= 0"])
|
89
89
|
s.add_dependency(%q<rspec>, ["~> 2.11.0"])
|
90
|
-
s.add_dependency(%q<bundler>, ["
|
91
|
-
s.add_dependency(%q<jeweler>, ["~> 1.
|
90
|
+
s.add_dependency(%q<bundler>, [">= 1.1.5"])
|
91
|
+
s.add_dependency(%q<jeweler>, ["~> 1.8.7"])
|
92
92
|
s.add_dependency(%q<yard>, [">= 0"])
|
93
93
|
s.add_dependency(%q<redcarpet>, [">= 0"])
|
94
94
|
s.add_dependency(%q<simplecov>, [">= 0"])
|
data/spec/apk_spec.rb
CHANGED
@@ -277,15 +277,25 @@ describe Android::Apk do
|
|
277
277
|
end
|
278
278
|
end
|
279
279
|
|
280
|
-
describe
|
281
|
-
context
|
280
|
+
describe '#signs' do
|
281
|
+
context 'with sampe apk file' do
|
282
282
|
let(:tmp_path){ File.expand_path(File.dirname(__FILE__) + '/data/sample.apk') }
|
283
|
-
subject { apk.
|
284
|
-
it { should
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
283
|
+
subject { apk.signs }
|
284
|
+
it { should be_a Hash }
|
285
|
+
it { should have(1).item }
|
286
|
+
it { should have_key('META-INF/CERT.RSA') }
|
287
|
+
it { subject['META-INF/CERT.RSA'].should be_a OpenSSL::PKCS7 }
|
288
|
+
end
|
289
|
+
end
|
290
|
+
|
291
|
+
describe '#certficates' do
|
292
|
+
context 'with sampe apk file' do
|
293
|
+
let(:tmp_path){ File.expand_path(File.dirname(__FILE__) + '/data/sample.apk') }
|
294
|
+
subject { apk.certificates }
|
295
|
+
it { should be_a Hash }
|
296
|
+
it { should have(1).item }
|
297
|
+
it { should have_key('META-INF/CERT.RSA') }
|
298
|
+
it { subject['META-INF/CERT.RSA'].should be_a OpenSSL::X509::Certificate }
|
289
299
|
end
|
290
300
|
end
|
291
301
|
end
|
data/spec/axml_parser_spec.rb
CHANGED
@@ -43,4 +43,25 @@ describe Android::AXMLParser do
|
|
43
43
|
it { should include("manifest") }
|
44
44
|
end
|
45
45
|
end
|
46
|
+
|
47
|
+
describe '#convert_value' do
|
48
|
+
let(:axmlparser){ Android::AXMLParser.new('') }
|
49
|
+
subject { axmlparser.convert_value(str_id, flags, val) }
|
50
|
+
context 'when parsing boolean attribute' do
|
51
|
+
let(:str_id) { 0xFFFFFFFF }
|
52
|
+
let(:flags) { 0x12000008 }
|
53
|
+
context 'and value is 0x01' do
|
54
|
+
let(:val) { 0x01 }
|
55
|
+
it { should be_true }
|
56
|
+
end
|
57
|
+
context 'and value is 0xFFFFFFF' do
|
58
|
+
let(:val) { 0xFFFFFFFF }
|
59
|
+
it { should be_true }
|
60
|
+
end
|
61
|
+
context 'and value is 0x00' do
|
62
|
+
let(:val) { 0x00 }
|
63
|
+
it { should be_false }
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
46
67
|
end
|
data/spec/manifest_spec.rb
CHANGED
@@ -176,6 +176,18 @@ describe Android::Manifest do
|
|
176
176
|
describe "#label" do
|
177
177
|
subject { manifest.label }
|
178
178
|
it { should == "@0x7f040001" }
|
179
|
+
|
180
|
+
context "with real apk file" do
|
181
|
+
let(:tmp_path){ File.expand_path(File.dirname(__FILE__) + '/data/sample.apk') }
|
182
|
+
let(:apk) { Android::Apk.new(tmp_path) }
|
183
|
+
let(:manifest){ apk.manifest }
|
184
|
+
subject { manifest.label }
|
185
|
+
it { should eq 'Sample' }
|
186
|
+
context 'when assign lang code' do
|
187
|
+
subject { manifest.label('ja') }
|
188
|
+
it { should eq 'Sample' }
|
189
|
+
end
|
190
|
+
end
|
179
191
|
end
|
180
192
|
describe "#doc" do
|
181
193
|
subject { manifest.doc }
|
@@ -187,7 +199,7 @@ describe Android::Manifest do
|
|
187
199
|
<uses-sdk android:minSdkVersion='10'/>
|
188
200
|
<uses-permission android:name='android.permission.INTERNET'/>
|
189
201
|
<uses-permission android:name='android.permission.WRITE_EXTERNAL_STORAGE'/>
|
190
|
-
<application android:label='@0x7f040001' android:icon='@0x7f020000' android:debuggable='
|
202
|
+
<application android:label='@0x7f040001' android:icon='@0x7f020000' android:debuggable='true'>
|
191
203
|
<activity android:label='@0x7f040001' android:name='example.app.sample.SampleActivity'>
|
192
204
|
<intent-filter>
|
193
205
|
<action android:name='android.intent.action.MAIN'/>
|
metadata
CHANGED
@@ -1,93 +1,113 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby_apk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 0.7.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- SecureBrain
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date: 2013-
|
11
|
+
date: 2013-09-24 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rubyzip
|
16
|
-
requirement:
|
17
|
-
none: false
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - '>='
|
20
18
|
- !ruby/object:Gem::Version
|
21
19
|
version: '0'
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
|
-
version_requirements:
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - '>='
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
25
27
|
- !ruby/object:Gem::Dependency
|
26
28
|
name: rspec
|
27
|
-
requirement:
|
28
|
-
none: false
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
29
30
|
requirements:
|
30
31
|
- - ~>
|
31
32
|
- !ruby/object:Gem::Version
|
32
33
|
version: 2.11.0
|
33
34
|
type: :development
|
34
35
|
prerelease: false
|
35
|
-
version_requirements:
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ~>
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 2.11.0
|
36
41
|
- !ruby/object:Gem::Dependency
|
37
42
|
name: bundler
|
38
|
-
requirement:
|
39
|
-
none: false
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
40
44
|
requirements:
|
41
|
-
- -
|
45
|
+
- - '>='
|
42
46
|
- !ruby/object:Gem::Version
|
43
47
|
version: 1.1.5
|
44
48
|
type: :development
|
45
49
|
prerelease: false
|
46
|
-
version_requirements:
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: 1.1.5
|
47
55
|
- !ruby/object:Gem::Dependency
|
48
56
|
name: jeweler
|
49
|
-
requirement:
|
50
|
-
none: false
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
51
58
|
requirements:
|
52
59
|
- - ~>
|
53
60
|
- !ruby/object:Gem::Version
|
54
|
-
version: 1.
|
61
|
+
version: 1.8.7
|
55
62
|
type: :development
|
56
63
|
prerelease: false
|
57
|
-
version_requirements:
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ~>
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: 1.8.7
|
58
69
|
- !ruby/object:Gem::Dependency
|
59
70
|
name: yard
|
60
|
-
requirement:
|
61
|
-
none: false
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
62
72
|
requirements:
|
63
|
-
- -
|
73
|
+
- - '>='
|
64
74
|
- !ruby/object:Gem::Version
|
65
75
|
version: '0'
|
66
76
|
type: :development
|
67
77
|
prerelease: false
|
68
|
-
version_requirements:
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - '>='
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
69
83
|
- !ruby/object:Gem::Dependency
|
70
84
|
name: redcarpet
|
71
|
-
requirement:
|
72
|
-
none: false
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
73
86
|
requirements:
|
74
|
-
- -
|
87
|
+
- - '>='
|
75
88
|
- !ruby/object:Gem::Version
|
76
89
|
version: '0'
|
77
90
|
type: :development
|
78
91
|
prerelease: false
|
79
|
-
version_requirements:
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
80
97
|
- !ruby/object:Gem::Dependency
|
81
98
|
name: simplecov
|
82
|
-
requirement:
|
83
|
-
none: false
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
84
100
|
requirements:
|
85
|
-
- -
|
101
|
+
- - '>='
|
86
102
|
- !ruby/object:Gem::Version
|
87
103
|
version: '0'
|
88
104
|
type: :development
|
89
105
|
prerelease: false
|
90
|
-
version_requirements:
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - '>='
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
91
111
|
description: static analysis tool for android apk
|
92
112
|
email: info@securebrain.co.jp
|
93
113
|
executables: []
|
@@ -139,29 +159,25 @@ files:
|
|
139
159
|
homepage: https://github.com/SecureBrain/ruby_apk/
|
140
160
|
licenses:
|
141
161
|
- MIT
|
162
|
+
metadata: {}
|
142
163
|
post_install_message:
|
143
164
|
rdoc_options: []
|
144
165
|
require_paths:
|
145
166
|
- lib
|
146
167
|
required_ruby_version: !ruby/object:Gem::Requirement
|
147
|
-
none: false
|
148
168
|
requirements:
|
149
|
-
- -
|
169
|
+
- - '>='
|
150
170
|
- !ruby/object:Gem::Version
|
151
171
|
version: '0'
|
152
|
-
segments:
|
153
|
-
- 0
|
154
|
-
hash: -3061789134736537466
|
155
172
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
156
|
-
none: false
|
157
173
|
requirements:
|
158
|
-
- -
|
174
|
+
- - '>='
|
159
175
|
- !ruby/object:Gem::Version
|
160
176
|
version: '0'
|
161
177
|
requirements: []
|
162
178
|
rubyforge_project:
|
163
|
-
rubygems_version:
|
179
|
+
rubygems_version: 2.0.6
|
164
180
|
signing_key:
|
165
|
-
specification_version:
|
181
|
+
specification_version: 4
|
166
182
|
summary: static analysis tool for android apk
|
167
183
|
test_files: []
|