idb 2.9.0 → 2.9.1

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.
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,8 +2,6 @@ require_relative 'local_storage_tab_widget'
2
2
  require_relative 'url_handler_widget'
3
3
  require_relative 'app_binary_tab_widget'
4
4
  require_relative 'log_widget'
5
- require_relative 'snoop_it_tab_widget'
6
- require_relative 'cycript_console_widget'
7
5
  require_relative 'pasteboard_monitor_widget'
8
6
  require_relative 'fs_viewer_tab_widget'
9
7
  require_relative 'keychain_widget'
@@ -60,11 +58,6 @@ module Idb
60
58
  @tools.setEnabled(false)
61
59
  @tabs[:tools] = addTab(@tools, "Tools")
62
60
 
63
- # @isnoop = SnoopItTabWidget.new self
64
- # @isnoop.setEnabled(false)
65
- # @tabs[:isnoop] = addTab(@isnoop, "Snoop-It")
66
- # setTabToolTip(@tabs[:isnoop],"The performance of the snoop-it integration is not good enough to enable the tab yet. If people would find it useful, let me know and I'll put time into it.")
67
-
68
61
  @log = LogWidget.new self
69
62
  @log.setEnabled(false)
70
63
  @tabs[:log] = addTab(@log, "Log")
@@ -73,11 +66,6 @@ module Idb
73
66
  @keychain.setEnabled(false)
74
67
  @tabs[:keychain] = addTab(@keychain, "Keychain")
75
68
 
76
- # @cycript = CycriptConsoleWidget.new self
77
- # @cycript.setEnabled(false)
78
- # @tabs[:cycript] = addTab(@cycript, "Cycript")
79
- # setTabToolTip(@tabs[:cycript],"Cycript needs proper terminal emulation. At the moment this tab is not very useful and disabled.")
80
-
81
69
  @pasteboard = PasteboardMonitorWidget.new self
82
70
  @pasteboard.setEnabled(false)
83
71
  @tabs[:pasteboard] = addTab(@pasteboard, "Pasteboard")
@@ -97,13 +85,9 @@ module Idb
97
85
  def enableAppBinary
98
86
  @app_binary.setEnabled(true)
99
87
  setTabEnabled(@tabs[:app_binary], true)
100
- @app_binary.enableTabs
88
+ @app_binary.enable_tabs
101
89
  end
102
90
 
103
- def enableCycript
104
- # @cycript.setEnabled(true)
105
- # setTabEnabled(@tabs[:cycript], true)
106
- end
107
91
 
108
92
  def enableLocalStorage
109
93
  @local_storage.setEnabled(true)
@@ -139,7 +123,6 @@ module Idb
139
123
 
140
124
 
141
125
  def enableDeviceFunctions
142
- enableCycript
143
126
  enableLog
144
127
  enablePasteboard
145
128
  enableKeychain
@@ -151,8 +134,6 @@ module Idb
151
134
  setTabEnabled(@tabs[:app_binary],false)
152
135
  setTabEnabled(@tabs[:url_handlers],false)
153
136
  setTabEnabled(@tabs[:pasteboard],false)
154
- # setTabEnabled(@tabs[:cycript],false)
155
- # setTabEnabled(@tabs[:isnoop],false)
156
137
  setTabEnabled(@tabs[:fs_viewer],false)
157
138
  setTabEnabled(@tabs[:keychain],false)
158
139
  setTabEnabled(@tabs[:tools],false)
@@ -191,4 +172,4 @@ module Idb
191
172
 
192
173
 
193
174
  end
194
- end
175
+ end
@@ -24,7 +24,7 @@ module Idb
24
24
  def refresh
25
25
  @list.clear
26
26
  if not $selected_app.binary.nil?
27
- shared_lib = $selected_app.binary.get_shared_libraries
27
+ shared_lib = $selected_app.binary.shared_libraries
28
28
  if shared_lib.nil?
29
29
  item = Qt::ListWidgetItem.new
30
30
  item.setText "Error: otool required"
@@ -1,5 +1,3 @@
1
- require_relative '../lib/console_launcher'
2
-
3
1
  module Idb
4
2
  class SqliteWidget < Qt::Widget
5
3
 
@@ -31,7 +29,7 @@ module Idb
31
29
  end
32
30
  end
33
31
 
34
- x = ConsoleLauncher.new
32
+ #x = ConsoleLauncher.new
35
33
  #TODO: find sqlite binary
36
34
  #http://www.ruby-doc.org/stdlib-2.0.0/libdoc/mkmf/rdoc/MakeMakefile.html#method-i-find_executable
37
35
  #x.run "/usr/bin/sqlite3 #{Dir.getwd}/#{$selected_app.cache_file item.full_path}"
@@ -73,7 +73,7 @@ module Idb
73
73
 
74
74
  def refresh_header_list
75
75
  @header_list.clear
76
- @weak_class_dump_wrapper.get_header_files.each { |x|
76
+ @weak_class_dump_wrapper.header_files.each { |x|
77
77
  @header_list.addItem x
78
78
  }
79
79
  end
data/lib/idb.rb CHANGED
@@ -204,8 +204,8 @@ module Idb
204
204
  $settings.ssh_password,
205
205
  $settings.ssh_host,
206
206
  $settings.ssh_port
207
- rescue
208
-
207
+ rescue StandardError => ex
208
+ $log.error ex
209
209
  end
210
210
  unless $device.nil?
211
211
  unless $device.configured?
@@ -236,7 +236,7 @@ module Idb
236
236
  x = @menu_devices.addSeparator
237
237
  x.setText("Simulators")
238
238
 
239
- Simulator.get_simulators.each { |s|
239
+ Simulator.simulators.each { |s|
240
240
  action = @menu_devices.addAction s
241
241
  @sim_group.addAction action
242
242
  action.setCheckable(true)
@@ -1,3 +1,3 @@
1
1
  module Idb
2
- VERSION = "2.9.0"
2
+ VERSION = "2.9.1"
3
3
  end
@@ -3,29 +3,25 @@ module Idb
3
3
  attr_accessor :apps_dir
4
4
  attr_accessor :ops
5
5
 
6
-
7
- def get_app_uuids
8
- if not @ops.file_exists? @apps_dir
6
+ def app_uuids
7
+ unless @ops.file_exists? @apps_dir
9
8
  puts "Application directory #{@apps_dir} not found."
10
9
  raise "Application directory #{@apps_dir} not found."
11
10
  end
12
11
 
13
12
  puts '[*] Retrieving list of applications...'
14
13
 
15
- dirs = @ops.list_dir "#{@apps_dir}"
16
- dirs.select! { |x| x != "." and x != ".." }
14
+ dirs = @ops.list_dir @apps_dir.to_s
15
+ dirs.select! { |x| (x != ".") && (x != "..") }
17
16
 
18
- if dirs.length == 0
17
+ if dirs.length.zero?
19
18
  puts "No applications found in #{@apps_dir}."
20
19
  raise "No applications found in #{@apps_dir}."
21
20
  end
22
- return dirs
21
+ dirs
23
22
  end
24
23
 
25
24
  def close
26
-
27
25
  end
28
-
29
-
30
26
  end
31
- end
27
+ end
@@ -5,15 +5,18 @@ require_relative 'ios8_last_launch_services_map_wrapper'
5
5
 
6
6
  module Idb
7
7
  class App
8
- attr_accessor :uuid, :app_dir, :binary, :cache_dir, :data_dir, :services_map
8
+ attr_accessor :uuid, :app_dir, :binary, :cache_dir, :services_map
9
+ attr_reader :data_dir
9
10
 
10
-
11
- def initialize uuid
11
+ def initialize(uuid)
12
12
  @uuid = uuid
13
13
  @cache_dir = "#{$tmp_path}/#{uuid}"
14
14
  FileUtils.mkdir_p @cache_dir unless Dir.exist? @cache_dir
15
15
 
16
+
16
17
  @app_dir = "#{$device.apps_dir}/#{@uuid}"
18
+ $log.debug "App Dir: #{@app_dir}"
19
+
17
20
  parse_info_plist
18
21
 
19
22
  if $device.ios_version >= 8
@@ -22,7 +25,7 @@ module Idb
22
25
  else
23
26
  mapping_file = "/private/var/installd/Library/MobileInstallation/LastLaunchServicesMap.plist"
24
27
  end
25
- local_mapping_file = cache_file mapping_file
28
+ local_mapping_file = cache_file mapping_file
26
29
  @services_map = IOS8LastLaunchServicesMapWrapper.new local_mapping_file
27
30
  @data_dir = @services_map.data_path_by_bundle_id @info_plist.bundle_identifier
28
31
  @keychain_access_groups = @services_map.keychain_access_groups_by_bundle_id @info_plist.bundle_identifier
@@ -30,14 +33,15 @@ module Idb
30
33
  else
31
34
  @data_dir = @app_dir
32
35
  end
33
-
34
-
36
+ # binding.pry
37
+ $log.debug "Data Dir: #{@data_dir}"
35
38
  end
36
39
 
40
+
37
41
  def analyze
38
42
  local_binary_path = cache_file binary_path
39
43
  @binary = AppBinary.new local_binary_path
40
- if @binary.is_encrypted?
44
+ if @binary.encrypted?
41
45
  $log.info "Binary is encrypted. Decrypting for further analysis."
42
46
  decrypt_binary!
43
47
  else
@@ -65,23 +69,23 @@ module Idb
65
69
  # If the ios version is less than 9 then we execute dumpdecrypted as
66
70
  # root. iOS 9 requires dumpdecrypted to be run as the mobile user.
67
71
  if $device.ios_version < 9
68
- #TODO: Is this the best way to do this?
72
+ # TODO: Is this the best way to do this?
69
73
  decrypted_path = "/var/root/#{File.basename full_remote_path}.decrypted"
70
74
  $device.ops.execute "DYLD_INSERT_LIBRARIES=#{dylib_path} \"#{full_remote_path}\""
71
75
  else
72
- #TODO: Is this the best way to do this?
76
+ # TODO: Is this the best way to do this?
73
77
  decrypted_path = "/var/mobile/#{File.basename full_remote_path}.decrypted"
74
- $device.ops.execute "DYLD_INSERT_LIBRARIES=#{dylib_path} \"#{full_remote_path}\"", { as_user: "mobile" }
78
+ $device.ops.execute "DYLD_INSERT_LIBRARIES=#{dylib_path} \"#{full_remote_path}\"", as_user: "mobile"
75
79
  end
76
80
 
77
81
  $log.info "Checking if decrypted file #{decrypted_path} was created..."
78
- if not $device.ops.file_exists? decrypted_path
82
+ unless $device.ops.file_exists? decrypted_path
79
83
  $log.error "Decryption failed. Trying armv6 build for iOS 6 and earlier..."
80
84
  $device.ops.execute "DYLD_INSERT_LIBRARIES=dumpdecrypted_armv6.dylib \"#{full_remote_path}\""
81
85
  $log.info "Checking if decrypted file #{decrypted_path} was created..."
82
86
  end
83
87
 
84
- if not $device.ops.file_exists? decrypted_path
88
+ unless $device.ops.file_exists? decrypted_path
85
89
  $log.error "Decryption failed. File may not be encrypted."
86
90
  return
87
91
  end
@@ -89,35 +93,29 @@ module Idb
89
93
  $log.info "Decrypted file found. Downloading..."
90
94
 
91
95
  @local_decrypted_binary = "#{cache_dir}/#{File.basename full_remote_path}.decrypted"
92
- @binary.setDecryptedPath @local_decrypted_binary
96
+ @binary.decrypted_path = @local_decrypted_binary
93
97
 
94
98
  local_path = $device.ops.download decrypted_path, @local_decrypted_binary
95
99
 
96
100
  $log.info "Decrypted binary downloaded to #{@local_decrypted_binary}"
97
101
  @local_decrypted_binary
98
-
99
102
  end
100
103
 
101
- def get_raw_plist_value val
102
- begin
103
- @info_plist.plist_data[val]
104
- rescue
105
- "[error]"
106
- end
104
+ def get_raw_plist_value(val)
105
+ @info_plist.plist_data[val]
106
+ rescue
107
+ "[error]"
107
108
  end
108
109
 
109
-
110
110
  def find_icon
111
111
  # lets try the easy way first...
112
112
  icon_name = get_raw_plist_value('CFBundleIconFile')
113
- if not icon_name.nil?
114
- return icon_name
115
- end
113
+ return icon_name unless icon_name.nil?
116
114
 
117
115
  # lets try iphone icons
118
116
  icon_name = get_raw_plist_value('CFBundleIcons')
119
117
  unless icon_name.nil?
120
- if not icon_name["CFBundlePrimaryIcon"].nil? and not icon_name["CFBundlePrimaryIcon"]["CFBundleIconFiles"].nil?
118
+ if !icon_name["CFBundlePrimaryIcon"].nil? && !icon_name["CFBundlePrimaryIcon"]["CFBundleIconFiles"].nil?
121
119
  return icon_name["CFBundlePrimaryIcon"]["CFBundleIconFiles"].sort.last
122
120
  end
123
121
  end
@@ -125,7 +123,7 @@ module Idb
125
123
  # lets try ipad icons
126
124
  icon_name = get_raw_plist_value('CFBundleIcons~ipad')
127
125
  unless icon_name.nil?
128
- if not icon_name["CFBundlePrimaryIcon"].nil? and not icon_name["CFBundlePrimaryIcon"]["CFBundleIconFiles"].nil?
126
+ if !icon_name["CFBundlePrimaryIcon"].nil? && !icon_name["CFBundlePrimaryIcon"]["CFBundleIconFiles"].nil?
129
127
  return icon_name["CFBundlePrimaryIcon"]["CFBundleIconFiles"].sort.last
130
128
  end
131
129
  end
@@ -135,7 +133,7 @@ module Idb
135
133
  app_dir = Shellwords.escape(@app_dir)
136
134
  icon_name = find_icon
137
135
 
138
- unless (icon_name[-4,4] == ".png")
136
+ unless icon_name[-4, 4] == ".png"
139
137
  $log.debug "Appending extension to #{icon_name}"
140
138
  icon_name += "*.png"
141
139
  $log.debug "Now: #{icon_name}"
@@ -143,12 +141,12 @@ module Idb
143
141
 
144
142
  icon_file = $device.ops.execute("ls #{app_dir}/*app/#{icon_name}").split("\n").first.strip
145
143
 
146
- if not $device.ops.file_exists? icon_file
144
+ unless $device.ops.file_exists? icon_file
147
145
  $log.warn "Icon not found: #{icon_file}"
148
146
  return nil
149
147
  end
150
148
  $log.info "Icon found at #{icon_file}"
151
- return icon_file
149
+ icon_file
152
150
  end
153
151
 
154
152
  def get_icon_file
@@ -159,8 +157,6 @@ module Idb
159
157
  new_local_path = "#{local_path}.png"
160
158
  CGBI.from_file(local_path).to_png_file(new_local_path)
161
159
  new_local_path
162
- else
163
- nil
164
160
  end
165
161
  end
166
162
 
@@ -197,44 +193,41 @@ module Idb
197
193
  end
198
194
 
199
195
  def bundle_id
200
- begin
201
- @info_plist.bundle_identifier.to_s
202
- rescue
203
- "[error]"
204
- end
196
+ @info_plist.bundle_identifier.to_s
197
+ rescue
198
+ "[error]"
205
199
  end
206
200
 
207
201
  def launch
208
- $device.app_launch self
202
+ $device.app_launch self
209
203
  end
210
204
 
211
205
  def binary_path
212
206
  $log.info "Locating application binary..."
213
- dirs = $device.ops.dir_glob("#{@app_dir}/","**")
214
- dirs.select! { |f|
207
+ dirs = $device.ops.dir_glob("#{@app_dir}/", "**")
208
+ dirs.select! do |f|
215
209
  $device.ops.file_exists? "#{f}/#{binary_name}"
216
- }
210
+ end
217
211
 
218
212
  "#{dirs.first}/#{binary_name}"
219
213
  end
220
214
 
221
215
  def binary_name
222
- begin
223
- @info_plist.binary_name
224
- rescue
225
- "[error]"
226
- end
216
+ @info_plist.binary_name
217
+ rescue
218
+ "[error]"
227
219
  end
228
220
 
229
221
  def sync_app_dir
230
- `#{rsync} avc -e ssh TKTK #{} `
222
+ `#{rsync} avc -e ssh TKTK #{}`
231
223
  end
232
224
 
233
- def find_files_by_pattern pattern
225
+ def find_files_by_pattern(pattern)
234
226
  app_dir_files = $device.ops.dir_glob(@app_dir, pattern)
235
- data_dir_files = Array.new
227
+ data_dir_files = []
236
228
 
237
- if app_dir != data_dir
229
+ if @app_dir != @data_dir
230
+ puts "IN DATA DIR: #{@data_dir}"
238
231
  data_dir_files = $device.ops.dir_glob(@data_dir, pattern)
239
232
  end
240
233
  app_dir_files + data_dir_files
@@ -260,12 +253,11 @@ module Idb
260
253
  end
261
254
 
262
255
  def cache_dir
263
- "#{$tmp_path}/#{@uuid}/"
256
+ "#{$tmp_path}/#{@uuid}/"
264
257
  end
265
258
 
266
-
267
- def cache_file f
268
- relative_file = f.sub(@app_dir,'')
259
+ def cache_file(f)
260
+ relative_file = f.sub(@app_dir, '')
269
261
  relative_dir = File.dirname relative_file
270
262
  cache_dir = "#{$tmp_path}/#{@uuid}/#{relative_dir}"
271
263
  FileUtils.mkdir_p(cache_dir) unless Dir.exist?(cache_dir)
@@ -277,6 +269,7 @@ module Idb
277
269
  return nil
278
270
  end
279
271
  end
272
+
280
273
  private
281
274
 
282
275
  def parse_info_plist
@@ -298,24 +291,21 @@ module Idb
298
291
  $log.debug "Backtrace: #{ex.backtrace.join("\n")}."
299
292
  return
300
293
  end
301
-
302
294
  end
303
295
 
304
-
305
-
306
296
  def info_plist_path
307
297
  app_dir = Shellwords.escape(@app_dir)
308
298
  plist_file = $device.ops.execute("ls #{app_dir}/*app/Info.plist").strip
309
299
 
310
300
  # the following works but is terribly slow.
311
- #plist_file = (@if.ops.dir_glob "#{@app_dir}/","*app/Info.plist").first
301
+ # plist_file = (@if.ops.dir_glob "#{@app_dir}/","*app/Info.plist").first
312
302
 
313
- if not $device.ops.file_exists? plist_file
303
+ unless $device.ops.file_exists? plist_file
314
304
  $log.error "Info.plist not found."
315
305
  return nil
316
306
  end
317
307
  $log.info "Info.plist found at #{plist_file}"
318
- return plist_file
308
+ plist_file
319
309
  end
320
310
  end
321
311
  end
@@ -3,55 +3,44 @@ require_relative 'app'
3
3
 
4
4
  module Idb
5
5
  class AppBinary
6
-
7
- def initialize app_binary
6
+ attr_writer :decrypted_path
7
+ def initialize(app_binary)
8
8
  @otool = OtoolWrapper.new app_binary
9
9
  end
10
10
 
11
- def get_shared_libraries
11
+ def shared_libraries
12
12
  @otool.shared_libraries
13
13
  end
14
14
 
15
- def setDecryptedPath path
16
- @decrypted_path = path
17
- end
18
-
19
- def is_pie?
15
+ def pie?
20
16
  @otool.pie
21
17
  end
22
18
 
23
-
24
- def is_stack_protected?
19
+ def stack_protected?
25
20
  @otool.canaries
26
21
  end
27
22
 
28
- def uses_arc?
23
+ def arc?
29
24
  @otool.arc
30
25
  end
31
26
 
32
- def is_encrypted?
27
+ def encrypted?
33
28
  encrypted = false
34
- if @otool.load_commands.nil?
35
- return "Error"
36
- end
37
- @otool.load_commands.each {|key, val|
38
- if val['cmd'].strip.start_with?('LC_ENCRYPTION_INFO') and val['cryptid'].strip == 1.to_s
29
+ return "Error" if @otool.load_commands.nil?
30
+ @otool.load_commands.each do |_key, val|
31
+ if val['cmd'].strip.start_with?('LC_ENCRYPTION_INFO') && (val['cryptid'].strip == 1.to_s)
39
32
  encrypted = true
40
33
  end
41
- }
42
- return encrypted
34
+ end
35
+ encrypted
43
36
  end
44
37
 
45
- def get_cryptid
46
- if @otool.load_commands.nil?
47
- return "Error"
38
+ def cryptid
39
+ return "Error" if @otool.load_commands.nil?
40
+ @otool.load_commands.each do |_key, val|
41
+ return val['cryptid'] if val['cmd'] == 'LC_ENCRYPTION_INFO'
48
42
  end
49
- @otool.load_commands.each {|key, val|
50
- if val['cmd'] == 'LC_ENCRYPTION_INFO'
51
- return val['cryptid']
52
- end
53
- }
54
- return nil
43
+ nil
55
44
  end
56
45
  end
57
- end
46
+ end