ruby_apk 0.6.0 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
+
[![Gem Version](https://badge.fury.io/rb/ruby_apk.png)](http://badge.fury.io/rb/ruby_apk)
|
4
5
|
[![Build Status](https://travis-ci.org/SecureBrain/ruby_apk.png)](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: []
|