idb 2.9.0 → 2.9.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +30 -0
  3. data/Gemfile.lock +5 -0
  4. data/idb.gemspec +1 -0
  5. data/lib/gui/app_binary_tab_widget.rb +7 -14
  6. data/lib/gui/app_details_group_box.rb +63 -88
  7. data/lib/gui/app_list_dialog.rb +29 -35
  8. data/lib/gui/app_list_widget_item.rb +1 -5
  9. data/lib/gui/app_tab_widget.rb +17 -22
  10. data/lib/gui/binary_strings_widget.rb +7 -15
  11. data/lib/gui/ca_manager_dialog.rb +32 -54
  12. data/lib/gui/cache_db_widget.rb +21 -26
  13. data/lib/gui/certificate_item.rb +2 -2
  14. data/lib/gui/default_protection_class_group_widget.rb +7 -12
  15. data/lib/gui/device_info_group_box.rb +26 -23
  16. data/lib/gui/main_tab_widget.rb +2 -21
  17. data/lib/gui/shared_libraries_widget.rb +1 -1
  18. data/lib/gui/sqlite_widget.rb +1 -3
  19. data/lib/gui/weak_class_dump_widget.rb +1 -1
  20. data/lib/idb.rb +3 -3
  21. data/lib/idb/version.rb +1 -1
  22. data/lib/lib/abstract_device.rb +7 -11
  23. data/lib/lib/app.rb +49 -59
  24. data/lib/lib/app_binary.rb +18 -29
  25. data/lib/lib/ca_interface.rb +46 -59
  26. data/lib/lib/device.rb +68 -155
  27. data/lib/lib/device_ca_interface.rb +7 -13
  28. data/lib/lib/host_file_wrapper.rb +6 -8
  29. data/lib/lib/ios8_last_launch_services_map_wrapper.rb +11 -18
  30. data/lib/lib/local_operations.rb +24 -32
  31. data/lib/lib/otool_wrapper.rb +30 -33
  32. data/lib/lib/rsync_git_manager.rb +26 -22
  33. data/lib/lib/screen_shot_util.rb +20 -28
  34. data/lib/lib/settings.rb +14 -17
  35. data/lib/lib/simulator.rb +11 -16
  36. data/lib/lib/simulator_ca_interface.rb +1 -3
  37. data/lib/lib/ssh_operations.rb +49 -65
  38. data/lib/lib/ssh_port_forwarder.rb +9 -13
  39. data/lib/lib/tools.rb +3 -3
  40. data/lib/lib/url_scheme_fuzzer.rb +41 -49
  41. data/lib/lib/usb_muxd_wrapper.rb +6 -8
  42. data/lib/lib/weak_class_dump_wrapper.rb +15 -16
  43. metadata +19 -9
  44. data/lib/gui/console_widget.rb +0 -163
  45. data/lib/gui/cycript_console_widget.rb +0 -68
  46. data/lib/gui/cycript_thread.rb +0 -81
  47. data/lib/lib/console_launcher.rb +0 -24
  48. data/lib/lib/i_device_diagnostics_wrapper.rb +0 -90
  49. data/lib/lib/snoop_it_wrapper.rb +0 -80
@@ -2,35 +2,29 @@ require_relative 'ca_interface'
2
2
 
3
3
  module Idb
4
4
  class DeviceCAInterface < CAInterface
5
-
6
- def initialize device
5
+ def initialize(device)
7
6
  @device = device
8
7
  @device_store_path = "/private/var/Keychains/TrustStore.sqlite3"
9
8
  base_path = "#{$tmp_path}/device"
10
9
  FileUtils.mkdir_p base_path
11
10
  @db_path = "#{base_path}/TrustStore.sqlite3"
12
-
13
-
14
11
  end
15
12
 
16
-
17
- def get_certs
13
+ def certs
18
14
  @device.ops.download @device_store_path, @db_path
19
15
  super
20
16
  end
21
17
 
22
- def remove_cert cert
23
- FileUtils.copy_file @db_path, "#{@db_path}-#{Time.now.to_s}"
18
+ def remove_cert(cert)
19
+ FileUtils.copy_file @db_path, "#{@db_path}-#{Time.now}"
24
20
  super cert
25
21
  @device.ops.upload @db_path, @device_store_path
26
22
  end
27
23
 
28
- def add_cert cert_file
29
- FileUtils.copy_file @db_path, "#{@db_path}-#{Time.now.to_s}"
24
+ def add_cert(cert_file)
25
+ FileUtils.copy_file @db_path, "#{@db_path}-#{Time.now}"
30
26
  super cert_file
31
27
  @device.ops.upload @db_path, @device_store_path
32
28
  end
33
-
34
-
35
29
  end
36
- end
30
+ end
@@ -1,6 +1,5 @@
1
1
  module Idb
2
2
  class HostFileWrapper
3
-
4
3
  def initialize
5
4
  @cache_path = "#{$tmp_path}/device/hosts"
6
5
  end
@@ -9,19 +8,18 @@ module Idb
9
8
  FileUtils.mkpath "#{$tmp_path}/device" unless File.directory? "#{$tmp_path}/device"
10
9
  $device.ops.download "/etc/hosts", @cache_path
11
10
  begin
12
- File.open(@cache_path,"r").read
11
+ File.open(@cache_path, "r").read
13
12
  rescue
14
-
13
+ $log.error "Could not open #{@cache_path}"
15
14
  end
16
15
  end
17
16
 
18
- def save text
17
+ def save(text)
19
18
  # upload
20
- File.open(@cache_path,"w") { |f|
19
+ File.open(@cache_path, "w") do |f|
21
20
  f.puts text
22
- }
21
+ end
23
22
  $device.ops.upload(@cache_path, "/etc/hosts")
24
-
25
23
  end
26
24
  end
27
- end
25
+ end
@@ -1,32 +1,25 @@
1
1
  require 'plist4r'
2
2
 
3
3
  class IOS8LastLaunchServicesMapWrapper
4
-
5
- def initialize plist_file
4
+ def initialize(plist_file)
6
5
  @plist_file = plist_file
7
6
 
8
7
  @plist_data = Plist4r.open @plist_file
9
8
  end
10
9
 
11
- def entitlements_by_bundle_id bundle_id
12
- begin
13
- @plist_data.to_hash["User"][bundle_id]["Entitlements"]
14
- rescue
15
- $log.error "Could not read entitlements.."
16
- end
10
+ def entitlements_by_bundle_id(bundle_id)
11
+ @plist_data.to_hash["User"][bundle_id]["Entitlements"]
12
+ rescue
13
+ $log.error "Could not read entitlements.."
17
14
  end
18
15
 
19
-
20
- def data_path_by_bundle_id bundle_id
16
+ def data_path_by_bundle_id(bundle_id)
21
17
  @plist_data.to_hash["User"][bundle_id]["Container"]
22
18
  end
23
19
 
24
-
25
- def keychain_access_groups_by_bundle_id bundle_id
26
- begin
27
- @plist_data.to_hash["User"][bundle_id]["Entitlements"]["keychain-access-groups"]
28
- rescue
29
- ""
30
- end
20
+ def keychain_access_groups_by_bundle_id(bundle_id)
21
+ @plist_data.to_hash["User"][bundle_id]["Entitlements"]["keychain-access-groups"]
22
+ rescue
23
+ ""
31
24
  end
32
- end
25
+ end
@@ -1,67 +1,59 @@
1
1
  module Idb
2
2
  class LocalOperations
3
-
4
-
5
- def file? path
3
+ def file?(path)
6
4
  File.file? path
7
5
  end
8
6
 
9
-
10
- def download a, b
11
- FileUtils.copy_file(a,b)
12
- return true
7
+ def download(a, b)
8
+ FileUtils.copy_file(a, b)
9
+ true
13
10
  end
14
11
 
15
-
16
- def directory? path
17
- File.directory? path
12
+ def directory?(path)
13
+ File.directory? path
18
14
  end
19
15
 
20
- def mtime path
16
+ def mtime(path)
21
17
  File.mtime path
22
18
  end
23
19
 
24
- def open path
25
- begin
26
- Launchy.open path
27
- return true
28
- rescue Exception => e
29
- $log.error "Could not open file #{path}: #{e.message}"
30
- $log.error e.backtrace
31
- return false
32
- end
20
+ def open(path)
21
+ Launchy.open path
22
+ return true
23
+ rescue StandardError => e
24
+ $log.error "Could not open file #{path}: #{e.message}"
25
+ $log.error e.backtrace
26
+ return false
33
27
  end
34
28
 
35
- def list_dir path
29
+ def list_dir(path)
36
30
  Dir.entries path
37
31
  end
38
32
 
39
- def list_dir_full path
33
+ def list_dir_full(path)
40
34
  Dir.entries path
41
35
  end
42
36
 
43
- def dir_glob path, pattern
37
+ def dir_glob(path, pattern)
44
38
  full_path = "#{path}/#{pattern}"
45
39
  Dir.glob(full_path)
46
40
  end
47
41
 
48
- def file_exists? file
49
- File.exists? file
42
+ def file_exists?(file)
43
+ File.exist? file
50
44
  end
51
45
 
52
- def execute cmd
46
+ def execute(cmd)
53
47
  `#{cmd}`
54
48
  end
55
49
 
56
- def execute_fork cmd
50
+ def execute_fork(cmd)
57
51
  (pid = fork) ? Process.detach(pid) : exec(cmd)
58
52
  end
59
53
 
60
- def launch_app command, app
54
+ def launch_app(command, app)
61
55
  $log.info "Executing #{command} #{app}"
62
- self.execute_fork("#{command} \"#{app}\"")
56
+ execute_fork("#{command} \"#{app}\"")
63
57
  end
64
-
65
-
66
58
  end
67
- end
59
+ end
@@ -4,12 +4,14 @@ module Idb
4
4
  class OtoolWrapper
5
5
  attr_accessor :load_commands, :shared_libraries, :pie, :arc, :canaries
6
6
 
7
- def initialize binary
7
+ def initialize(binary)
8
8
  @otool_path = "/usr/bin/otool"
9
9
  unless File.exist? @otool_path.to_s
10
10
  $log.error "otool not available. Some functions will not work properly."
11
11
  error = Qt::MessageBox.new
12
- error.setInformativeText("This feature requires otool to be installed on the host running idb. This is the default on OS X but it may not be available for other platforms.")
12
+ msg = "This feature requires otool to be installed on the host running idb." \
13
+ " This is the default on OS X but it may not be available for other platforms."
14
+ error.setInformativeText(msg)
13
15
  error.setIcon(Qt::MessageBox::Critical)
14
16
  error.exec
15
17
  @otool_path = nil
@@ -24,17 +26,17 @@ module Idb
24
26
  process_symbol_table
25
27
  end
26
28
 
27
-
28
29
  private
30
+
29
31
  def parse_shared_libraries
30
32
  if @otool_path.nil?
31
- @shared_libraries = Array.new
33
+ @shared_libraries = []
32
34
  @shared_libraries << "Error; otool not available"
33
35
  return
34
36
  end
35
37
  @raw_shared_libraries_output = `#{@otool_path} -L '#{@binary}'`
36
38
  lines = @raw_shared_libraries_output.split("\n")
37
- @shared_libraries = lines[1,lines.size].map{ |x| x.strip} unless lines.nil?
39
+ @shared_libraries = lines[1, lines.size].map(&:strip) unless lines.nil?
38
40
  end
39
41
 
40
42
  def process_symbol_table
@@ -44,20 +46,19 @@ module Idb
44
46
  return
45
47
  end
46
48
  symbols = `#{@otool_path} -I -v '#{@binary}'`
47
- if symbols.include? "stack_chk_fail" or symbols.include? "stack_chk_guard"
48
- @canaries = true
49
- else
50
- @canaries = false
51
- end
52
-
53
- if symbols.include? "_objc_release"
54
- @arc = true
55
- else
56
- @arc = false
57
- end
49
+ @canaries = if symbols.include?("stack_chk_fail") || symbols.include?("stack_chk_guard")
50
+ true
51
+ else
52
+ false
53
+ end
54
+
55
+ @arc = if symbols.include? "_objc_release"
56
+ true
57
+ else
58
+ false
59
+ end
58
60
  end
59
61
 
60
-
61
62
  def hashify_otool_output(otool_output)
62
63
  # otool output may contain multiple mach headers
63
64
  mach_headers = otool_output.split("Mach header\n").map(&:strip)
@@ -65,7 +66,7 @@ module Idb
65
66
  # The newest otool version no longer echos the path of the binary being
66
67
  # inspected. Here we reject that line if it shows up in the output of
67
68
  # otool as well as any blank lines
68
- mach_headers.reject!{|line| line == "" or line.include?(@binary)}
69
+ mach_headers.reject! { |line| (line == "") || line.include?(@binary) }
69
70
 
70
71
  # convert otool output to a hash
71
72
  mach_headers.map do |mach_header|
@@ -78,7 +79,6 @@ module Idb
78
79
  end
79
80
  end
80
81
 
81
-
82
82
  def parse_header
83
83
  if @otool_path.nil?
84
84
  @pie = "Error"
@@ -87,18 +87,17 @@ module Idb
87
87
  pie_flag = 0x00200000
88
88
  @raw_load_output = `#{@otool_path} -h '#{@binary}'`
89
89
 
90
-
91
90
  mach_hashes = hashify_otool_output(@raw_load_output)
92
91
  $log.info "Mach Hashes: #{mach_hashes}"
93
92
 
94
93
  # extract the Position Independent Executable (PIE) flag from the flags
95
94
  # value.
96
95
  mach_hashes.each do |mach_hash|
97
- if (mach_hash["flags"].to_i(16) & pie_flag) == pie_flag
98
- @pie = true
99
- else
100
- @pie = false
101
- end
96
+ @pie = if (mach_hash["flags"].to_i(16) & pie_flag) == pie_flag
97
+ true
98
+ else
99
+ false
100
+ end
102
101
  end
103
102
  end
104
103
 
@@ -108,24 +107,22 @@ module Idb
108
107
  return
109
108
  end
110
109
  @raw_load_output = `#{@otool_path} -l '#{@binary}'`
111
- delim = "Load command"
112
110
  regex_cmd = /Load command (\d+)/
113
111
  regex_parse_key_vals = /\s*(cmd|cryptid)\s(.+)/
114
112
 
115
- @load_commands = Hash.new
113
+ @load_commands = {}
116
114
 
117
- @raw_load_output.split("\n").each {|line|
118
-
119
- if match = regex_cmd.match(line)
115
+ @raw_load_output.split("\n").each do |line|
116
+ if (match = regex_cmd.match(line))
120
117
  @load_commands[@cmd] = @command unless @cmd.nil?
121
118
  @cmd = match[1]
122
- @command = Hash.new
119
+ @command = {}
123
120
  end
124
121
 
125
- if match = regex_parse_key_vals.match(line)
122
+ if (match = regex_parse_key_vals.match(line))
126
123
  @command[match[1]] = match[2]
127
124
  end
128
- }
125
+ end
129
126
  end
130
127
  end
131
128
  end
@@ -4,18 +4,19 @@ require 'expect'
4
4
 
5
5
  module Idb
6
6
  class RsyncGitManager
7
- def initialize local_path
7
+ def initialize(local_path)
8
8
  @local_path = local_path
9
9
  FileUtils.mkdir_p @local_path unless Dir.exist? @local_path
10
10
 
11
11
  begin
12
- @g = Git.open(local_path, :log => $log)
12
+ @g = Git.open(local_path, log: $log)
13
13
  rescue
14
- $log.debug "Repository could not be opened. This is likely the first clone. Creating empty repo."
14
+ $log.debug "Repository could not be opened." \
15
+ " This is likely the first clone. Creating empty repo."
15
16
  Git.init(local_path)
16
- @g = Git.open(local_path, :log => $log)
17
+ @g = Git.open(local_path, log: $log)
17
18
  FileUtils.touch "#{local_path}/idb_dummy.placeholder"
18
- @g.add(:all=>true)
19
+ @g.add(all: true)
19
20
  $log.debug "Committing placeholder to initialize the repo."
20
21
  begin
21
22
  @g.commit_all("Initial commit. Initializing the repo.")
@@ -26,49 +27,52 @@ module Idb
26
27
  end
27
28
  end
28
29
 
29
-
30
- def sync_dir remote, local_relative
30
+ def sync_dir(remote, local_relative)
31
31
  local = @local_path + "/" + local_relative
32
32
  if $settings['device_connection_mode'] == "ssh"
33
- cmd = "rsync -avz -e 'ssh -oStrictHostKeyChecking=no -p #{$settings.ssh_port}' #{$settings.ssh_username}@#{$settings.ssh_host}:#{Shellwords.escape(remote)}/ #{Shellwords.escape(local)}/"
33
+ cmd = "rsync -avz -e 'ssh -oStrictHostKeyChecking=no -p #{$settings.ssh_port}'" \
34
+ " #{$settings.ssh_username}@#{$settings.ssh_host}:#{Shellwords.escape(remote)}/" \
35
+ " #{Shellwords.escape(local)}/"
34
36
  else
35
- cmd = "rsync -avz -e 'ssh -oStrictHostKeyChecking=no -p #{$device.tool_port}' root@localhost:#{Shellwords.escape(remote)}/ #{Shellwords.escape(local)}/"
37
+ cmd = "rsync -avz -e 'ssh -oStrictHostKeyChecking=no" \
38
+ " -p #{$device.tool_port}' root@localhost:#{Shellwords.escape(remote)}/" \
39
+ " #{Shellwords.escape(local)}/"
36
40
  end
37
41
 
38
42
  $log.info "Executing rsync command #{cmd}"
39
43
  begin
40
- PTY.spawn(cmd) { |rsync_out, rsync_in, pid |
44
+ PTY.spawn(cmd) do |rsync_out, rsync_in, _pid|
41
45
  STDOUT.flush
42
46
  rsync_out.sync = true
43
47
  rsync_in.sync = true
44
48
  $expect_verbose = true
45
49
 
46
- rsync_out.expect(/assword: /) { |x|
50
+ rsync_out.expect(/assword: /) do |_x|
47
51
  begin
48
52
  $log.info "Supplying password for rsync if required..."
49
53
  rsync_in.printf("#{$settings.ssh_password}\n")
50
54
  rescue
51
55
  $log.info "No password required for rsync...."
52
56
  end
53
- }
57
+ end
54
58
 
55
- rsync_out.each { |x|
59
+ rsync_out.each do |x|
56
60
  $log.info x
57
- }
61
+ end
58
62
  PTY.check
59
- }
63
+ end
60
64
  rescue
65
+ $log.error "Something went wrong"
61
66
  end
62
-
63
67
  end
64
68
 
65
-
66
69
  def commit_new_revision
67
70
  $log.info "Rsync Done. committing to git."
68
- @g.add(:all=>true)
71
+ @g.add(all: true)
69
72
  begin
70
- @g.commit_all("Snapshot from #{Time.now.to_s}")
73
+ @g.commit_all("Snapshot from #{Time.now}")
71
74
  rescue
75
+ $log.error "Something went wrong"
72
76
  end
73
77
  end
74
78
 
@@ -77,9 +81,9 @@ module Idb
77
81
  begin
78
82
  @g.reset_hard
79
83
  rescue
80
- $log.error "Reset of repo failed. If this is the first time you run rsync+git for this app this may be okay."
84
+ $log.error "Reset of repo failed. If this is the first time you" \
85
+ " run rsync+git for this app this may be okay."
81
86
  end
82
87
  end
83
-
84
88
  end
85
- end
89
+ end