idb 1.3.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 (103) hide show
  1. checksums.yaml +7 -0
  2. data/.DS_Store +0 -0
  3. data/.gitignore +19 -0
  4. data/Gemfile +4 -0
  5. data/Gemfile.lock +65 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +29 -0
  8. data/Rakefile +2 -0
  9. data/bin/idb +5 -0
  10. data/idb.gemspec +41 -0
  11. data/lib/LICENSE +20 -0
  12. data/lib/README.md +54 -0
  13. data/lib/config/.dummy +0 -0
  14. data/lib/config/settings.yml +8 -0
  15. data/lib/gui/app_binary_tab_widget.rb +45 -0
  16. data/lib/gui/app_details_group_box.rb +213 -0
  17. data/lib/gui/app_list_dialog.rb +67 -0
  18. data/lib/gui/app_list_widget_item.rb +9 -0
  19. data/lib/gui/binary_strings_widget.rb +33 -0
  20. data/lib/gui/browse_filesystem_widget.rb +4 -0
  21. data/lib/gui/ca_manager_dialog.rb +137 -0
  22. data/lib/gui/cache_db_widget.rb +61 -0
  23. data/lib/gui/certificate_item.rb +5 -0
  24. data/lib/gui/console_widget.rb +163 -0
  25. data/lib/gui/cycript_console_widget.rb +68 -0
  26. data/lib/gui/cycript_thread.rb +81 -0
  27. data/lib/gui/device_info_group_box.rb +55 -0
  28. data/lib/gui/device_status_dialog.rb +351 -0
  29. data/lib/gui/file_system_events_widget.rb +4 -0
  30. data/lib/gui/fs_viewer_tab_widget.rb +245 -0
  31. data/lib/gui/i_device_syslog_thread.rb +47 -0
  32. data/lib/gui/images/check.png +0 -0
  33. data/lib/gui/images/folder.ico +0 -0
  34. data/lib/gui/images/iphone.ico +0 -0
  35. data/lib/gui/images/screenshot.png +0 -0
  36. data/lib/gui/key_chain_widget.rb +86 -0
  37. data/lib/gui/local_storage_tab_widget.rb +37 -0
  38. data/lib/gui/log_plain_text_edit.rb +18 -0
  39. data/lib/gui/log_widget.rb +71 -0
  40. data/lib/gui/main_tab_widget.rb +179 -0
  41. data/lib/gui/pasteboard_monitor_widget.rb +116 -0
  42. data/lib/gui/path_list_widget_item.rb +5 -0
  43. data/lib/gui/pb_watcher_thread.rb +63 -0
  44. data/lib/gui/plist_file_widget.rb +66 -0
  45. data/lib/gui/qt_ruby_variant.rb +16 -0
  46. data/lib/gui/screenshot_wizard.rb +169 -0
  47. data/lib/gui/settings_dialog.rb +69 -0
  48. data/lib/gui/settings_tab_widget.rb +149 -0
  49. data/lib/gui/shared_libraries_widget.rb +47 -0
  50. data/lib/gui/snoop_it_fs_events_widget.rb +150 -0
  51. data/lib/gui/snoop_it_keychain_widget.rb +172 -0
  52. data/lib/gui/snoop_it_sensitive_api_widget.rb +128 -0
  53. data/lib/gui/snoop_it_tab_widget.rb +27 -0
  54. data/lib/gui/snoop_it_update_thread.rb +48 -0
  55. data/lib/gui/sqlite_widget.rb +73 -0
  56. data/lib/gui/ssh_port_forward_tab_widget.rb +209 -0
  57. data/lib/gui/tool_widget.rb +94 -0
  58. data/lib/gui/url_handler_widget.rb +26 -0
  59. data/lib/gui/url_scheme_fuzz_widget.rb +103 -0
  60. data/lib/gui/url_scheme_widget.rb +60 -0
  61. data/lib/gui/weak_class_dump_widget.rb +89 -0
  62. data/lib/helper/ssh_port_forwarder.rb +72 -0
  63. data/lib/idb.rb +295 -0
  64. data/lib/idb/version.rb +3 -0
  65. data/lib/lib/CgBI.rb +153 -0
  66. data/lib/lib/abstract_device.rb +31 -0
  67. data/lib/lib/app.rb +286 -0
  68. data/lib/lib/app_binary.rb +57 -0
  69. data/lib/lib/ca_interface.rb +151 -0
  70. data/lib/lib/configuration.rb +0 -0
  71. data/lib/lib/console_launcher.rb +24 -0
  72. data/lib/lib/device.rb +438 -0
  73. data/lib/lib/device_ca_interface.rb +36 -0
  74. data/lib/lib/host_file_wrapper.rb +27 -0
  75. data/lib/lib/i_device_diagnostics_wrapper.rb +90 -0
  76. data/lib/lib/keychain_plist_parser.rb +15 -0
  77. data/lib/lib/local_operations.rb +67 -0
  78. data/lib/lib/otool_wrapper.rb +116 -0
  79. data/lib/lib/plist_util.rb +72 -0
  80. data/lib/lib/qt_thread_fix.rb +29 -0
  81. data/lib/lib/rsync_git_manager.rb +81 -0
  82. data/lib/lib/screen_shot_util.rb +59 -0
  83. data/lib/lib/settings.rb +67 -0
  84. data/lib/lib/simulator.rb +60 -0
  85. data/lib/lib/simulator_ca_interface.rb +16 -0
  86. data/lib/lib/snoop_it_wrapper.rb +80 -0
  87. data/lib/lib/ssh_operations.rb +136 -0
  88. data/lib/lib/ssh_port_forwarder.rb +43 -0
  89. data/lib/lib/tools.rb +11 -0
  90. data/lib/lib/url_scheme_fuzzer.rb +98 -0
  91. data/lib/lib/usb_muxd_wrapper.rb +32 -0
  92. data/lib/lib/weak_class_dump_wrapper.rb +62 -0
  93. data/lib/utils/dumpdecrypted/README +4 -0
  94. data/lib/utils/dumpdecrypted/dumpdecrypted_armv6.dylib +0 -0
  95. data/lib/utils/dumpdecrypted/dumpdecrypted_armv7.dylib +0 -0
  96. data/lib/utils/ios-ssl-kill-switch/com.isecpartners.nabla.sslkillswitch_v0.5-iOS_6.1.deb +0 -0
  97. data/lib/utils/keychain_dump/README +2 -0
  98. data/lib/utils/keychain_dump/keychain_dump +0 -0
  99. data/lib/utils/pbwatcher/pbwatcher +0 -0
  100. data/lib/utils/pcviewer/protectionclassviewer +0 -0
  101. data/lib/utils/weak_class_dump/README +5 -0
  102. data/lib/utils/weak_class_dump/weak_classdump.cy +726 -0
  103. metadata +412 -0
@@ -0,0 +1,36 @@
1
+ require_relative 'ca_interface'
2
+
3
+ module Idb
4
+ class DeviceCAInterface < CAInterface
5
+
6
+ def initialize device
7
+ @device = device
8
+ @device_store_path = "/private/var/Keychains/TrustStore.sqlite3"
9
+ base_path = "#{$tmp_path}/device"
10
+ FileUtils.mkdir_p base_path
11
+ @db_path = "#{base_path}/TrustStore.sqlite3"
12
+
13
+
14
+ end
15
+
16
+
17
+ def get_certs
18
+ @device.ops.download @device_store_path, @db_path
19
+ super
20
+ end
21
+
22
+ def remove_cert cert
23
+ FileUtils.copy_file @db_path, "#{@db_path}-#{Time.now.to_s}"
24
+ super cert
25
+ @device.ops.upload @db_path, @device_store_path
26
+ end
27
+
28
+ def add_cert cert_file
29
+ FileUtils.copy_file @db_path, "#{@db_path}-#{Time.now.to_s}"
30
+ super cert_file
31
+ @device.ops.upload @db_path, @device_store_path
32
+ end
33
+
34
+
35
+ end
36
+ end
@@ -0,0 +1,27 @@
1
+ module Idb
2
+ class HostFileWrapper
3
+
4
+ def initialize
5
+ @cache_path = "#{$tmp_path}/device/hosts"
6
+ end
7
+
8
+ def content
9
+ FileUtils.mkpath "#{$tmp_path}/device" unless File.directory? "#{$tmp_path}/device"
10
+ $device.ops.download "/etc/hosts", @cache_path
11
+ begin
12
+ File.open(@cache_path,"r").read
13
+ rescue
14
+
15
+ end
16
+ end
17
+
18
+ def save text
19
+ # upload
20
+ File.open(@cache_path,"w") { |f|
21
+ f.puts text
22
+ }
23
+ $device.ops.upload(@cache_path, "/etc/hosts")
24
+
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,90 @@
1
+ require 'ffi'
2
+
3
+ module IMobileDevice
4
+ extend FFI::Library
5
+
6
+ ffi_lib 'libimobiledevice'
7
+ IDeviceEventType = enum(
8
+ :idevice_device_added, 1,
9
+ :idevice_device_remove
10
+ )
11
+
12
+ class IDeviceEventT < FFI::Struct
13
+ layout :event, IDeviceEventType,
14
+ :udid, :string,
15
+ :conn_type, :int
16
+ end
17
+
18
+ ConnectionType = enum(
19
+ :connection_usbmuxd, 1
20
+ )
21
+
22
+ class IDevicePrivate < FFI::Struct
23
+ layout :udid, :string,
24
+ :conn_type, ConnectionType,
25
+ :conn_data, :pointer
26
+ end
27
+
28
+
29
+
30
+ attach_function :idevice_get_device_list, [:pointer, :pointer], :int
31
+ attach_function :idevice_event_subscribe, [:pointer, :pointer], :int
32
+ attach_function :idevice_new, [:pointer, :string], :int
33
+ # attach_function :syslog_relay_client_start_service, [IDevicePrivate, :pointer, :string], :int
34
+ # attach_function :syslog_relay_start_capture, [:pointer, :pointer, :pointer], :int
35
+ # attach_function :syslog_relay_client_free, [:pointer], :int
36
+
37
+ def self.startLogging
38
+ ret = idevice_new(IDevicePrivate, @udid)
39
+ if ret != 0
40
+ puts "ERROR"
41
+ end
42
+
43
+
44
+
45
+
46
+ end
47
+ def self.stopLogging
48
+ puts "stopstopstop"
49
+
50
+ end
51
+
52
+ # DeviceEvn :device, [:pointer, :long, :uint8], :void
53
+
54
+ DeviceEventCB = FFI::Function.new(:void, [:pointer, :pointer]) do |event, userdata|
55
+ # cast event to struct
56
+ event_t = IDeviceEventT.new event
57
+ if event_t[:event] == :idevice_device_added
58
+ if @syslog.nil? or @syslog == false
59
+ if @udid.nil? or @udid == false
60
+ @udid = event_t[:udid]
61
+ end
62
+
63
+ if @udid == event_t[:udid]
64
+ #TODO error checking
65
+ puts "[*] Start Logging"
66
+ IMobileDevice.startLogging
67
+ end
68
+ end
69
+ elsif avent_t[:event] == :idevice_device_remove
70
+ if not @syslog.nil? and @udid == event_t[:udid]
71
+ puts "[*] Disconnected"
72
+ end
73
+ end
74
+ end
75
+ end
76
+
77
+ devices = FFI::MemoryPointer.new :pointer
78
+ num = FFI::MemoryPointer.new :int
79
+ x = IMobileDevice.idevice_get_device_list(devices, num)
80
+ device = devices.read_pointer.get_array_of_string(0,num.read_int).first
81
+ puts "Device #{device}"
82
+ IMobileDevice.idevice_event_subscribe(IMobileDevice::DeviceEventCB, nil)
83
+
84
+
85
+
86
+ while true
87
+
88
+ end
89
+
90
+
@@ -0,0 +1,15 @@
1
+ # encoding: utf-8
2
+ require 'nokogiri'
3
+ require 'plist4r'
4
+ require 'awesome_print'
5
+
6
+ module Idb
7
+ class KeychainPlistParser
8
+ attr_accessor :entries
9
+
10
+ def initialize plist_path
11
+ $log.info 'Parsing keychain plist file..'
12
+ @entries = Plist4r.open(plist_path)["Array"]
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,67 @@
1
+ module Idb
2
+ class LocalOperations
3
+
4
+
5
+ def file? path
6
+ File.file? path
7
+ end
8
+
9
+
10
+ def download a, b
11
+ FileUtils.copy_file(a,b)
12
+ return true
13
+ end
14
+
15
+
16
+ def directory? path
17
+ File.directory? path
18
+ end
19
+
20
+ def mtime path
21
+ File.mtime path
22
+ end
23
+
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
33
+ end
34
+
35
+ def list_dir path
36
+ Dir.entries path
37
+ end
38
+
39
+ def list_dir_full path
40
+ Dir.entries path
41
+ end
42
+
43
+ def dir_glob path, pattern
44
+ full_path = "#{path}/#{pattern}"
45
+ Dir.glob(full_path)
46
+ end
47
+
48
+ def file_exists? file
49
+ File.exists? file
50
+ end
51
+
52
+ def execute cmd
53
+ `#{cmd}`
54
+ end
55
+
56
+ def execute_fork cmd
57
+ (pid = fork) ? Process.detach(pid) : exec(cmd)
58
+ end
59
+
60
+ def launch_app command, app
61
+ $log.info "Executing #{command} #{app}"
62
+ self.execute_fork("#{command} \"#{app}\"")
63
+ end
64
+
65
+
66
+ end
67
+ end
@@ -0,0 +1,116 @@
1
+ require 'awesome_print'
2
+
3
+ module Idb
4
+ class OtoolWrapper
5
+ attr_accessor :load_commands, :shared_libraries, :pie, :arc, :canaries
6
+
7
+ def initialize binary
8
+ @otool_path = "/usr/bin/otool"
9
+ unless File.exist? @otool_path.to_s
10
+ $log.error "otool not available. Some functions will not work properly."
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.")
13
+ error.setIcon(Qt::MessageBox::Critical)
14
+ error.exec
15
+ @otool_path = nil
16
+
17
+ return
18
+ end
19
+
20
+ @binary = binary
21
+ parse_load_commands
22
+ parse_shared_libraries
23
+ parse_header
24
+ process_symbol_table
25
+ end
26
+
27
+
28
+ private
29
+ def parse_shared_libraries
30
+ if @otool_path.nil?
31
+ @shared_libraries = Array.new
32
+ @shared_libraries << "Error; otool not available"
33
+ return
34
+ end
35
+ @raw_shared_libraries_output = `#{@otool_path} -L '#{@binary}'`
36
+ lines = @raw_shared_libraries_output.split("\n")
37
+ @shared_libraries = lines[1,lines.size].map{ |x| x.strip} unless lines.nil?
38
+ end
39
+
40
+ def process_symbol_table
41
+ if @otool_path.nil?
42
+ @canaries = "Error"
43
+ @arc = "Error"
44
+ return
45
+ end
46
+ 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
58
+ end
59
+
60
+
61
+
62
+
63
+ def parse_header
64
+ if @otool_path.nil?
65
+ @pie = "Error"
66
+ return
67
+ end
68
+ pie_flag = 0x00200000
69
+ @raw_load_output = `#{@otool_path} -h '#{@binary}'`
70
+
71
+ # fourth row contains values. then split them up.
72
+ vals = @raw_load_output.split("\n")[3].split(" ")
73
+
74
+ #7th field contains the flags
75
+ flags = vals[7].to_i(16)
76
+
77
+ if flags & pie_flag == pie_flag
78
+ @pie = true
79
+ else
80
+ @pie = false
81
+ end
82
+
83
+
84
+ end
85
+
86
+ def parse_load_commands
87
+ if @otool_path.nil?
88
+ @load_commands = nil
89
+ return
90
+ end
91
+ @raw_load_output = `#{@otool_path} -l '#{@binary}'`
92
+ delim = "Load command"
93
+ regex_cmd = /Load command (\d+)/
94
+ regex_parse_key_vals = /\s*(cmd|cryptid)\s(.+)/
95
+
96
+ @load_commands = Hash.new
97
+
98
+ @raw_load_output.split("\n").each {|line|
99
+
100
+ if match = regex_cmd.match(line)
101
+ @load_commands[@cmd] = @command unless @cmd.nil?
102
+ @cmd = match[1]
103
+ @command = Hash.new
104
+ end
105
+
106
+ if match = regex_parse_key_vals.match(line)
107
+ @command[match[1]] = match[2]
108
+ end
109
+ }
110
+ end
111
+
112
+
113
+
114
+
115
+ end
116
+ end
@@ -0,0 +1,72 @@
1
+ require 'plist4r'
2
+ require 'rbconfig'
3
+ require 'nokogiri'
4
+ require 'coderay'
5
+
6
+ module Idb
7
+ class PlistUtil
8
+
9
+ attr_accessor :schemas, :binary_name, :bundle_identifier, :plist_data, :plist_file
10
+
11
+ def initialize(plist_file)
12
+ @plist_file = plist_file
13
+
14
+ @plutil = Pathname.new("/usr/bin/plutil")
15
+ if(!@plutil.exist?)
16
+ raise "plutil not found at #{@plutil}. aborting."
17
+ end
18
+
19
+ parse_plist_file
20
+ end
21
+
22
+ def parse_info_plist
23
+ extract_binary_name
24
+ extract_url_handlers
25
+ end
26
+
27
+ def dump
28
+ doc = Nokogiri::XML(File.open(@plist_file)) do |config|
29
+ config.nonet.noblanks
30
+ end
31
+ puts CodeRay.scan(doc.to_xml(:indent => 2), :xml).terminal
32
+ end
33
+
34
+ private
35
+ def parse_plist_file
36
+ $log.info 'Parsing plist file..'
37
+
38
+ # Make sure plist file is in xml and not binary
39
+ if RbConfig::CONFIG['host_os'] =~ /linux/
40
+ `#{@plutil.realpath} -i "#{@plist_file}" -o "#{@plist_file}"`
41
+ else
42
+ `#{@plutil.realpath} -convert xml1 "#{@plist_file}"`
43
+ end
44
+
45
+ # @plist_data = Plist::parse_xml(@plist_file)
46
+ @plist_data = Plist4r.open @plist_file
47
+ end
48
+
49
+ def extract_url_handlers
50
+ @schemas = Array.new
51
+
52
+ if @plist_data['CFBundleURLTypes'] != nil
53
+ for type in @plist_data['CFBundleURLTypes']
54
+ if !type.nil? and !type['CFBundleURLSchemes'].nil?
55
+ @schemas += type['CFBundleURLSchemes']
56
+ else
57
+ @schemas += ['None']
58
+ end
59
+ end
60
+ end
61
+ end
62
+
63
+ def extract_binary_name
64
+ @binary_name = @plist_data['CFBundleExecutable']
65
+ @bundle_identifier = @plist_data['CFBundleIdentifier']
66
+ end
67
+
68
+
69
+
70
+
71
+ end
72
+ end
@@ -0,0 +1,29 @@
1
+ require 'thread'
2
+
3
+ module Idb
4
+ class QtThreadFix < Qt::Object
5
+ slots 'ruby_thread_timeout()'
6
+ @@ruby_thread_queue = Queue.new
7
+
8
+ def initialize
9
+ super()
10
+ # Enable threading
11
+ @ruby_thread_sleep_period = 0.01
12
+ @ruby_thread_timer = Qt::Timer.new(self)
13
+ connect(@ruby_thread_timer, SIGNAL('timeout()'), SLOT('ruby_thread_timeout()'))
14
+ @ruby_thread_timer.method_missing(:start, 0)
15
+ end
16
+
17
+ def ruby_thread_timeout
18
+ unless @@ruby_thread_queue.empty?
19
+ proc_to_call = @@ruby_thread_queue.pop
20
+ proc_to_call.call
21
+ end
22
+ sleep(@ruby_thread_sleep_period)
23
+ end
24
+
25
+ def self.ruby_thread_queue
26
+ @@ruby_thread_queue
27
+ end
28
+ end
29
+ end