dex-oracle 1.0.2
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/Gemfile +4 -0
- data/Gemfile.lock +56 -0
- data/LICENSE.txt +21 -0
- data/README.md +102 -0
- data/bin/dex-oracle +98 -0
- data/dex-oracle.gemspec +43 -0
- data/driver/build.gradle +52 -0
- data/driver/gradle/wrapper/gradle-wrapper.jar +0 -0
- data/driver/gradle/wrapper/gradle-wrapper.properties +6 -0
- data/driver/gradlew +160 -0
- data/driver/gradlew.bat +90 -0
- data/driver/src/main/java/org/cf/oracle/Driver.java +134 -0
- data/driver/src/main/java/org/cf/oracle/FileUtils.java +35 -0
- data/driver/src/main/java/org/cf/oracle/StackSpoofer.java +42 -0
- data/driver/src/main/java/org/cf/oracle/options/InvocationTarget.java +40 -0
- data/driver/src/main/java/org/cf/oracle/options/TargetParser.java +121 -0
- data/lib/dex-oracle/driver.rb +255 -0
- data/lib/dex-oracle/logging.rb +32 -0
- data/lib/dex-oracle/plugin.rb +87 -0
- data/lib/dex-oracle/plugins/string_decryptor.rb +59 -0
- data/lib/dex-oracle/plugins/undexguard.rb +155 -0
- data/lib/dex-oracle/plugins/unreflector.rb +85 -0
- data/lib/dex-oracle/resources.rb +13 -0
- data/lib/dex-oracle/smali_field.rb +21 -0
- data/lib/dex-oracle/smali_file.rb +64 -0
- data/lib/dex-oracle/smali_input.rb +81 -0
- data/lib/dex-oracle/smali_method.rb +33 -0
- data/lib/dex-oracle/utility.rb +37 -0
- data/lib/dex-oracle/version.rb +3 -0
- data/lib/oracle.rb +61 -0
- data/res/driver.dex +0 -0
- data/res/dx.jar +0 -0
- data/spec/data/helloworld.apk +0 -0
- data/spec/data/helloworld.dex +0 -0
- data/spec/data/plugins/bytes_decrypt.smali +18 -0
- data/spec/data/plugins/class_forname.smali +14 -0
- data/spec/data/plugins/multi_bytes_decrypt.smali +28 -0
- data/spec/data/plugins/string_decrypt.smali +14 -0
- data/spec/data/plugins/string_lookup_1int.smali +14 -0
- data/spec/data/plugins/string_lookup_3int.smali +18 -0
- data/spec/data/smali/helloworld.smali +17 -0
- data/spec/dex-oracle/driver_spec.rb +82 -0
- data/spec/dex-oracle/plugins/string_decryptor_spec.rb +25 -0
- data/spec/dex-oracle/plugins/undexguard_spec.rb +69 -0
- data/spec/dex-oracle/plugins/unreflector_spec.rb +29 -0
- data/spec/dex-oracle/smali_field_spec.rb +15 -0
- data/spec/dex-oracle/smali_file_spec.rb +41 -0
- data/spec/dex-oracle/smali_input_spec.rb +90 -0
- data/spec/dex-oracle/smali_method_spec.rb +19 -0
- data/spec/spec_helper.rb +9 -0
- data/update_driver +5 -0
- metadata +195 -0
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
require 'digest'
|
|
2
|
+
require_relative '../logging'
|
|
3
|
+
|
|
4
|
+
class Unreflector < Plugin
|
|
5
|
+
include Logging
|
|
6
|
+
include CommonRegex
|
|
7
|
+
|
|
8
|
+
attr_reader :optimizations
|
|
9
|
+
|
|
10
|
+
CLASS_FOR_NAME = 'invoke-static \{[vp]\d+\}, Ljava\/lang\/Class;->forName\(Ljava\/lang\/String;\)Ljava\/lang\/Class;'
|
|
11
|
+
|
|
12
|
+
CONST_CLASS_REGEX = Regexp.new(
|
|
13
|
+
'^[ \t]*(' << CONST_STRING << '\s+' <<
|
|
14
|
+
CLASS_FOR_NAME << '\s+' <<
|
|
15
|
+
MOVE_RESULT_OBJECT << ')'
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
VIRTUAL_FIELD_LOOKUP = Regexp.new(
|
|
19
|
+
'^[ \t]*(' <<
|
|
20
|
+
CONST_STRING << '\s+' \
|
|
21
|
+
'invoke-static \{[vp]\d+\}, Ljava\/lang\/Class;->forName\(Ljava\/lang\/String;\)Ljava\/lang\/Class;\s+' <<
|
|
22
|
+
MOVE_RESULT_OBJECT << '\s+' <<
|
|
23
|
+
CONST_STRING << '\s+' \
|
|
24
|
+
'invoke-virtual \{[vp]\d+, [vp]\d+\}, Ljava\/lang\/Class;->getField\(Ljava\/lang\/String;\)Ljava\/lang\/reflect\/Field;\s+' <<
|
|
25
|
+
MOVE_RESULT_OBJECT << '\s+' \
|
|
26
|
+
'invoke-virtual \{[vp]\d+, ([vp]\d+)\}, Ljava\/lang\/reflect\/Field;->get\(Ljava\/lang\/Object;\)Ljava\/lang\/Object;\s+' <<
|
|
27
|
+
MOVE_RESULT_OBJECT << ')'
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
STATIC_FIELD_LOOKUP = Regexp.new(
|
|
31
|
+
'^[ \t]*(' <<
|
|
32
|
+
CONST_STRING << '\s+' <<
|
|
33
|
+
CLASS_FOR_NAME << '\s+' <<
|
|
34
|
+
MOVE_RESULT_OBJECT << '\s+' <<
|
|
35
|
+
CONST_STRING <<
|
|
36
|
+
'invoke-virtual \{[vp]\d+, [vp]\d+\}, Ljava\/lang\/Class;->getField\(Ljava\/lang\/String;\)Ljava\/lang\/reflect\/Field;\s+' <<
|
|
37
|
+
MOVE_RESULT_OBJECT << '\s+' \
|
|
38
|
+
'const/4 [vp]\d+, 0x0\s+' \
|
|
39
|
+
'invoke-virtual \{[vp]\d+, ([vp]\d+)\}, Ljava\/lang\/reflect\/Field;->get\(Ljava\/lang\/Object;\)Ljava\/lang\/Object;\s+' <<
|
|
40
|
+
MOVE_RESULT_OBJECT <<
|
|
41
|
+
')'
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
CLASS_LOOKUP_MODIFIER = -> (_, output, out_reg) { "const-class #{out_reg}, #{output}" }
|
|
45
|
+
|
|
46
|
+
def initialize(driver, smali_files, methods)
|
|
47
|
+
@driver = driver
|
|
48
|
+
@smali_files = smali_files
|
|
49
|
+
@methods = methods
|
|
50
|
+
@optimizations = Hash.new(0)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def process
|
|
54
|
+
made_changes = false
|
|
55
|
+
@methods.each do |method|
|
|
56
|
+
logger.info("Unreflecting #{method.descriptor}")
|
|
57
|
+
made_changes |= lookup_classes(method)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
made_changes
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def optimizations
|
|
64
|
+
@optimizations
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
def lookup_classes(method)
|
|
70
|
+
target_to_contexts = {}
|
|
71
|
+
target_id_to_output = {}
|
|
72
|
+
matches = method.body.scan(CONST_CLASS_REGEX)
|
|
73
|
+
@optimizations[:class_lookups] += matches.size
|
|
74
|
+
matches.each do |original, class_name, out_reg|
|
|
75
|
+
target = { id: Digest::SHA256.hexdigest(original) }
|
|
76
|
+
smali_class = "L#{class_name.tr('.', '/')};"
|
|
77
|
+
target_id_to_output[target[:id]] = ['success', smali_class]
|
|
78
|
+
target_to_contexts[target] = [] unless target_to_contexts.key?(target)
|
|
79
|
+
target_to_contexts[target] << [original, out_reg]
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
method_to_target_to_contexts = { method => target_to_contexts }
|
|
83
|
+
Plugin.apply_outputs(target_id_to_output, method_to_target_to_contexts, CLASS_LOOKUP_MODIFIER)
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
class SmaliField
|
|
2
|
+
attr_reader :name, :class, :type, :descriptor
|
|
3
|
+
|
|
4
|
+
def initialize(class_name, field_signature)
|
|
5
|
+
@class = class_name
|
|
6
|
+
@descriptor = "#{class_name}->#{field_signature}"
|
|
7
|
+
@name, @type = field_signature.split(':')
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def to_s
|
|
11
|
+
@descriptor
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def ==(other)
|
|
15
|
+
other.class == self.class && other.state == state
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def state
|
|
19
|
+
[@name, @class, @type, @descriptor]
|
|
20
|
+
end
|
|
21
|
+
end
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
require_relative 'smali_field'
|
|
2
|
+
require_relative 'smali_method'
|
|
3
|
+
require_relative 'logging'
|
|
4
|
+
|
|
5
|
+
class SmaliFile
|
|
6
|
+
attr_reader :class, :super, :interfaces, :methods, :fields, :file_path, :content
|
|
7
|
+
|
|
8
|
+
include Logging
|
|
9
|
+
|
|
10
|
+
ACCESSOR = /(?:interface|public|protected|private|abstract|static|final|synchronized|transient|volatile|native|strictfp|synthetic|enum|annotation)/
|
|
11
|
+
TYPE = /(?:[IJFDZBCV]|L[^;]+;)/
|
|
12
|
+
CLASS = /^\.class (?:#{ACCESSOR} )+(L[^;]+;)/
|
|
13
|
+
SUPER = /^\.super (L[^;]+;)/
|
|
14
|
+
INTERFACE = /^\.implements (L[^;]+;)/
|
|
15
|
+
FIELD = /^\.field (?:#{ACCESSOR} )+([^\s]+)$/
|
|
16
|
+
METHOD = /^.method (?:#{ACCESSOR} )+([^\s]+)$/
|
|
17
|
+
|
|
18
|
+
def initialize(file_path)
|
|
19
|
+
@file_path = file_path
|
|
20
|
+
@modified = false
|
|
21
|
+
parse(file_path)
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def update
|
|
25
|
+
@methods.each do |m|
|
|
26
|
+
next unless m.modified
|
|
27
|
+
logger.debug("Updating method: #{m}")
|
|
28
|
+
update_method(m)
|
|
29
|
+
m.modified = false
|
|
30
|
+
end
|
|
31
|
+
File.open(@file_path, 'w') { |f| f.write(@content) }
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def to_s
|
|
35
|
+
@class
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def parse(file_path)
|
|
41
|
+
@content = IO.read(file_path)
|
|
42
|
+
@class = @content[CLASS, 1]
|
|
43
|
+
@super = @content[SUPER, 1]
|
|
44
|
+
@interfaces = []
|
|
45
|
+
@content.scan(INTERFACE).each { |m| @interfaces << m.first }
|
|
46
|
+
@fields = []
|
|
47
|
+
@content.scan(FIELD).each { |m| @fields << SmaliField.new(@class, m.first) }
|
|
48
|
+
@methods = []
|
|
49
|
+
@content.scan(METHOD).each do |m|
|
|
50
|
+
body_regex = build_method_regex(m.first)
|
|
51
|
+
body = @content[body_regex, 1]
|
|
52
|
+
@methods << SmaliMethod.new(@class, m.first, body)
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def build_method_regex(method_signature)
|
|
57
|
+
/\.method (?:#{ACCESSOR} )+#{Regexp.escape(method_signature)}(.*)^\.end method/m
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def update_method(method)
|
|
61
|
+
body_regex = build_method_regex(method.signature)
|
|
62
|
+
@content[body_regex, 1] = method.body
|
|
63
|
+
end
|
|
64
|
+
end
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
require 'zip'
|
|
2
|
+
require 'english'
|
|
3
|
+
require_relative 'utility'
|
|
4
|
+
|
|
5
|
+
class SmaliInput
|
|
6
|
+
attr_reader :dir, :out_apk, :out_dex, :temp_dir, :temp_dex
|
|
7
|
+
|
|
8
|
+
DEX_MAGIC = [0x64, 0x65, 0x78]
|
|
9
|
+
PK_ZIP_MAGIC = [0x50, 0x4b, 0x3]
|
|
10
|
+
|
|
11
|
+
def initialize(input)
|
|
12
|
+
prepare(input)
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def finish
|
|
16
|
+
SmaliInput.update_apk(dir, @out_apk) if @out_apk
|
|
17
|
+
SmaliInput.compile(dir, @out_dex) if @out_dex
|
|
18
|
+
FileUtils.rm_rf(@dir) if @temp_dir
|
|
19
|
+
FileUtils.rm_rf(@out_dex) if @temp_dex
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
private
|
|
23
|
+
|
|
24
|
+
def self.compile(dir, out_dex = nil)
|
|
25
|
+
fail 'Smali could not be found on the path.' if Utility.which('smali').nil?
|
|
26
|
+
out_dex = Tempfile.new(['oracle', '.dex']) if out_dex.nil?
|
|
27
|
+
exit_code = SmaliInput.exec("smali #{dir} -o #{out_dex.path}")
|
|
28
|
+
# Remember kids, if you make a CLI, exit with non-zero status for failures
|
|
29
|
+
fail 'Crap, smali compilation failed.' if $CHILD_STATUS.exitstatus != 0
|
|
30
|
+
out_dex
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def self.update_apk(dir, out_apk)
|
|
34
|
+
out_dex = compile(dir)
|
|
35
|
+
Utility.update_zip(out_apk, 'classes.dex', out_dex)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def self.extract_dex(apk, out_dex)
|
|
39
|
+
Utility.extract_file(apk, 'classes.dex', out_dex)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def prepare(input)
|
|
43
|
+
if File.directory?(input)
|
|
44
|
+
@temp_dir = false
|
|
45
|
+
@temp_dex = true
|
|
46
|
+
@dir = input
|
|
47
|
+
@out_dex = SmaliInput.compile(dir)
|
|
48
|
+
return
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
magic = File.open(input) { |f| f.read(3) }.bytes.to_a
|
|
52
|
+
case magic
|
|
53
|
+
when PK_ZIP_MAGIC
|
|
54
|
+
@temp_dex = true
|
|
55
|
+
@temp_dir = true
|
|
56
|
+
@out_apk = "#{File.basename(input, '.*')}_oracle#{File.extname(input)}"
|
|
57
|
+
@out_dex = Tempfile.new(['oracle', '.dex'])
|
|
58
|
+
FileUtils.cp(input, @out_apk)
|
|
59
|
+
SmaliInput.extract_dex(@out_apk, @out_dex)
|
|
60
|
+
baksmali(input)
|
|
61
|
+
when DEX_MAGIC
|
|
62
|
+
@temp_dex = false
|
|
63
|
+
@temp_dir = true
|
|
64
|
+
@out_dex = "#{File.basename(input, '.*')}_oracle#{File.extname(input)}"
|
|
65
|
+
baksmali(input)
|
|
66
|
+
else
|
|
67
|
+
fail "Unrecognized file type for: #{input}, magic=#{magic.inspect}"
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
def baksmali(input)
|
|
72
|
+
fail 'Baksmali could not be found on the path.' if Utility.which('baksmali').nil?
|
|
73
|
+
@dir = Dir.mktmpdir
|
|
74
|
+
cmd = "baksmali #{input} -o #{@dir}"
|
|
75
|
+
SmaliInput.exec(cmd)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def self.exec(cmd)
|
|
79
|
+
`#{cmd}`
|
|
80
|
+
end
|
|
81
|
+
end
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
class SmaliMethod
|
|
2
|
+
attr_accessor :modified, :body
|
|
3
|
+
attr_reader :name, :class, :descriptor, :signature, :parameters, :return_type
|
|
4
|
+
|
|
5
|
+
PARAMETER_ISOLATOR = /\([^\)]+\)/
|
|
6
|
+
PARAMETER_INDIVIDUATOR = /(\[*(?:[BCDFIJSZ]|L[^;]+;))/
|
|
7
|
+
|
|
8
|
+
def initialize(class_name, signature, body = nil)
|
|
9
|
+
@modified = false
|
|
10
|
+
@class = class_name
|
|
11
|
+
@name = signature[/[^\(]+/]
|
|
12
|
+
@body = body
|
|
13
|
+
@return_type = signature[/[^\)$]+$/]
|
|
14
|
+
@descriptor = "#{class_name}->#{signature}"
|
|
15
|
+
@signature = signature
|
|
16
|
+
@parameters = []
|
|
17
|
+
parameter_string = signature[PARAMETER_ISOLATOR]
|
|
18
|
+
return if parameter_string.nil?
|
|
19
|
+
parameter_string.scan(PARAMETER_INDIVIDUATOR).each { |m| @parameters << m.first }
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def to_s
|
|
23
|
+
@descriptor
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def ==(other)
|
|
27
|
+
other.class == self.class && other.state == state
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def state
|
|
31
|
+
[@name, @class, @descriptor, @parameters, @return_type, @modified, @body]
|
|
32
|
+
end
|
|
33
|
+
end
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
require 'zip'
|
|
2
|
+
|
|
3
|
+
class Utility
|
|
4
|
+
def self.which(cmd)
|
|
5
|
+
exts = ENV['PATHEXT'] ? ENV['PATHEXT'].split(';') : ['']
|
|
6
|
+
ENV['PATH'].split(File::PATH_SEPARATOR).each do |path|
|
|
7
|
+
exts.each do |ext|
|
|
8
|
+
exe = File.join(path, "#{cmd}#{ext}")
|
|
9
|
+
return exe if File.executable?(exe) && !File.directory?(exe)
|
|
10
|
+
end
|
|
11
|
+
end
|
|
12
|
+
nil
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.create_zip(zip, name_to_file)
|
|
16
|
+
Zip::File.open(zip, Zip::File::CREATE) do |zf|
|
|
17
|
+
name_to_file.each { |n, f| zf.add(n, f) }
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def self.extract_file(zip, name, dest)
|
|
22
|
+
Zip::File.open(zip) do |zf|
|
|
23
|
+
zf.each do |e|
|
|
24
|
+
next unless e.name == name
|
|
25
|
+
e.extract(dest) { true } # overwrite
|
|
26
|
+
break
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def self.update_zip(zip, name, target)
|
|
32
|
+
Zip::File.open(zip) do |zf|
|
|
33
|
+
zf.remove(name)
|
|
34
|
+
zf.add(name, target.path)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
data/lib/oracle.rb
ADDED
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
require_relative 'dex-oracle/logging'
|
|
2
|
+
require_relative 'dex-oracle/plugin'
|
|
3
|
+
require_relative 'dex-oracle/smali_file'
|
|
4
|
+
|
|
5
|
+
class Oracle
|
|
6
|
+
include Logging
|
|
7
|
+
|
|
8
|
+
def initialize(smali_dir, driver, include_types, exclude_types, disable_plugins)
|
|
9
|
+
@smali_files = Oracle.parse_smali(smali_dir)
|
|
10
|
+
@methods = Oracle.filter_methods(@smali_files, include_types, exclude_types)
|
|
11
|
+
Plugin.init_plugins(driver, @smali_files, @methods)
|
|
12
|
+
@disable_plugins = disable_plugins
|
|
13
|
+
logger.info("Disabled plugins: #{@disable_plugins * ','}") unless @disable_plugins.empty?
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def divine
|
|
17
|
+
puts "Optimizing #{@methods.size} methods over #{@smali_files.size} Smali files."
|
|
18
|
+
made_changes = process_plugins
|
|
19
|
+
@smali_files.each(&:update) if made_changes
|
|
20
|
+
optimizations = {}
|
|
21
|
+
Plugin.plugins.each { |p| optimizations.merge!(p.optimizations) }
|
|
22
|
+
opt_str = optimizations.collect { |k, v| "#{k}=#{v}" } * ', '
|
|
23
|
+
puts "Optimizations: #{opt_str}"
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def process_plugins
|
|
27
|
+
made_changes = false
|
|
28
|
+
loop do
|
|
29
|
+
sweep_changes = false
|
|
30
|
+
Plugin.plugins.each do |p|
|
|
31
|
+
next if @disable_plugins.include?(p.class.name.downcase)
|
|
32
|
+
sweep_changes |= p.process
|
|
33
|
+
end
|
|
34
|
+
made_changes |= sweep_changes
|
|
35
|
+
break unless sweep_changes
|
|
36
|
+
end
|
|
37
|
+
made_changes
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def self.filter_methods(smali_files, include_types, exclude_types)
|
|
41
|
+
methods = []
|
|
42
|
+
smali_files.each do |smali_file|
|
|
43
|
+
smali_file.methods.each do |method|
|
|
44
|
+
if include_types
|
|
45
|
+
next if method.descriptor !~ include_types
|
|
46
|
+
elsif exclude_types && !(method.descriptor !~ exclude_types)
|
|
47
|
+
next
|
|
48
|
+
end
|
|
49
|
+
methods << method
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
methods
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.parse_smali(smali_dir)
|
|
57
|
+
smali_files = []
|
|
58
|
+
Dir["#{smali_dir}/**/*.smali"].each { |f| smali_files << SmaliFile.new(f) }
|
|
59
|
+
smali_files
|
|
60
|
+
end
|
|
61
|
+
end
|
data/res/driver.dex
ADDED
|
Binary file
|
data/res/dx.jar
ADDED
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
.class public Lorg/cf/BytesDecrypt;
|
|
2
|
+
.super Ljava/lang/Object;
|
|
3
|
+
|
|
4
|
+
.method public static doStuff()V
|
|
5
|
+
.locals 1
|
|
6
|
+
|
|
7
|
+
const-string v0, "asdf"
|
|
8
|
+
|
|
9
|
+
invoke-virtual {v0}, Ljava/lang/String;->getBytes()[B
|
|
10
|
+
|
|
11
|
+
move-result-object v0
|
|
12
|
+
|
|
13
|
+
invoke-static {v0}, Lorg/cf/BytesDecrypt;->decrypt([B)Ljava/lang/String;
|
|
14
|
+
|
|
15
|
+
move-result-object v0
|
|
16
|
+
|
|
17
|
+
return-void
|
|
18
|
+
.end method
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
.class public Lorg/cf/ClassForName;
|
|
2
|
+
.super Ljava/lang/Object;
|
|
3
|
+
|
|
4
|
+
.method public static doStuff()V
|
|
5
|
+
.locals 1
|
|
6
|
+
|
|
7
|
+
const-string v0, "android.content.Intent"
|
|
8
|
+
|
|
9
|
+
invoke-static {v0}, Ljava/lang/Class;->forName(Ljava/lang/String;)Ljava/lang/Class;
|
|
10
|
+
|
|
11
|
+
move-result-object v0
|
|
12
|
+
|
|
13
|
+
return-void
|
|
14
|
+
.end method
|