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,71 @@
1
+ require_relative 'log_plain_text_edit'
2
+ require_relative 'i_device_syslog_thread'
3
+ require 'htmlentities'
4
+
5
+ module Idb
6
+ class LogWidget < Qt::Widget
7
+
8
+ def initialize *args
9
+ super *args
10
+
11
+ @start = Qt::PushButton.new "Start"
12
+ @start.connect(SIGNAL :released) {
13
+ @start.setEnabled(false)
14
+ @stop.setEnabled(true)
15
+ start_log
16
+ }
17
+
18
+ @stop = Qt::PushButton.new "Stop"
19
+ @stop.setEnabled(false)
20
+ @stop.connect(SIGNAL :released) {
21
+ @start.setEnabled(true)
22
+ @stop.setEnabled(false)
23
+ stop_log
24
+ }
25
+
26
+ @log_window = LogPlainTextEdit.new
27
+ @log_window.setReadOnly(true)
28
+
29
+ layout = Qt::VBoxLayout.new do |v|
30
+ v.add_widget(@log_window)
31
+ v.add_widget(@start)
32
+ v.add_widget(@stop)
33
+ end
34
+ setLayout(layout)
35
+ @colored = true
36
+
37
+ end
38
+
39
+
40
+ def start_log
41
+ h = HTMLEntities.new
42
+ @log_window.append_message "Please wait.. Streaming device syslog..."
43
+ @log_thread = IDeviceSyslogThread.new
44
+ @log_thread.connect(SIGNAL('new_entry(QString)')) {|line|
45
+ color = 'black'
46
+ if @colored
47
+ if line.include? "<Notice>"
48
+ color = 'grey'
49
+ elsif line.include? "<Error>"
50
+ color = 'red'
51
+ elsif line.include? "<Warning>"
52
+ color = 'Orange'
53
+ elsif line.include? "<Debug>"
54
+ color = 'Green'
55
+ end
56
+ end
57
+
58
+
59
+
60
+ line = line.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_')
61
+
62
+ @log_window.append_message "<font color='#{color}'>#{h.encode(line.chomp)}</font>"
63
+ }
64
+ end
65
+
66
+ def stop_log
67
+ @log_thread.stop
68
+ end
69
+
70
+ end
71
+ end
@@ -0,0 +1,179 @@
1
+ require_relative 'local_storage_tab_widget'
2
+ require_relative 'url_handler_widget'
3
+ require_relative 'app_binary_tab_widget'
4
+ require_relative 'log_widget'
5
+ require_relative 'snoop_it_tab_widget'
6
+ require_relative 'cycript_console_widget'
7
+ require_relative 'pasteboard_monitor_widget'
8
+ require_relative 'fs_viewer_tab_widget'
9
+ require_relative 'key_chain_widget'
10
+ require_relative 'tool_widget'
11
+ require 'Qt'
12
+
13
+ module Idb
14
+ class MainTabWidget < Qt::TabWidget
15
+
16
+
17
+ def initialize *args
18
+ super *args
19
+ @tabs = Hash.new
20
+
21
+ @local_storage = LocalStorageTabWidget.new self
22
+ @local_storage.setEnabled(false)
23
+ @tabs[:local_storage] = addTab(@local_storage, "Storage")
24
+ @local_storage.connect(SIGNAL('currentChanged(int)')) { |x|
25
+ #@local_storage.currentWidget.refresh
26
+ }
27
+
28
+ @url_handler = URLHandlerWidget.new self
29
+ @url_handler.setEnabled(false)
30
+ @tabs[:url_handlers] = addTab(@url_handler, "URL Handlers")
31
+ connect(SIGNAL('currentChanged(int)')) { |x|
32
+ # if isTabEnabled(@tabs[:url_handlers]) and
33
+ # @tabs[:url_handlers] == currentIndex
34
+ #
35
+ # @url_handler.refresh
36
+ # end
37
+ }
38
+
39
+ @app_binary = AppBinaryTabWidget.new self
40
+ @app_binary.setEnabled(false)
41
+ @tabs[:app_binary] = addTab(@app_binary, "Binary")
42
+ @app_binary.connect(SIGNAL('currentChanged(int)')) { |x|
43
+ @app_binary.currentWidget.refresh
44
+ }
45
+
46
+ @fs_viewer = FsViewerTabWidget.new self
47
+ @fs_viewer.setEnabled(false)
48
+ @tabs[:fs_viewer] = addTab(@fs_viewer, "Filesystem")
49
+
50
+ @tools = ToolWidget.new self
51
+ @tools.setEnabled(false)
52
+ @tabs[:tools] = addTab(@tools, "Tools")
53
+
54
+ # @isnoop = SnoopItTabWidget.new self
55
+ # @isnoop.setEnabled(false)
56
+ # @tabs[:isnoop] = addTab(@isnoop, "Snoop-It")
57
+ # 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.")
58
+
59
+ @log = LogWidget.new self
60
+ @log.setEnabled(false)
61
+ @tabs[:log] = addTab(@log, "Log")
62
+
63
+ @keychain = KeyChainWidget.new self
64
+ @keychain.setEnabled(false)
65
+ @tabs[:keychain] = addTab(@keychain, "Keychain")
66
+
67
+ # @cycript = CycriptConsoleWidget.new self
68
+ # @cycript.setEnabled(false)
69
+ # @tabs[:cycript] = addTab(@cycript, "Cycript")
70
+ # setTabToolTip(@tabs[:cycript],"Cycript needs proper terminal emulation. At the moment this tab is not very useful and disabled.")
71
+
72
+ @pasteboard = PasteboardMonitorWidget.new self
73
+ @pasteboard.setEnabled(false)
74
+ @tabs[:pasteboard] = addTab(@pasteboard, "Pasteboard")
75
+
76
+ disable_all
77
+ end
78
+
79
+ def enableLog
80
+ @log.setEnabled(true)
81
+ setTabEnabled(@tabs[:log], true)
82
+ end
83
+
84
+ def enableAppBinary
85
+ @app_binary.setEnabled(true)
86
+ setTabEnabled(@tabs[:app_binary], true)
87
+ @app_binary.enableTabs
88
+ end
89
+
90
+ def enableCycript
91
+ # @cycript.setEnabled(true)
92
+ # setTabEnabled(@tabs[:cycript], true)
93
+ end
94
+
95
+ def enableLocalStorage
96
+ @local_storage.setEnabled(true)
97
+ setTabEnabled(@tabs[:local_storage], true)
98
+ end
99
+
100
+ def enableURLHandlers
101
+ @url_handler.setEnabled(true)
102
+ setTabEnabled(@tabs[:url_handlers], true)
103
+ end
104
+
105
+ def enablePasteboard
106
+ @pasteboard.setEnabled(true)
107
+ setTabEnabled(@tabs[:pasteboard], true)
108
+ end
109
+
110
+ def enableFSViewer
111
+ @fs_viewer.setEnabled(true)
112
+ setTabEnabled(@tabs[:fs_viewer], true)
113
+ end
114
+
115
+ def enableTools
116
+ @tools.setEnabled(true)
117
+ setTabEnabled(@tabs[:tools], true)
118
+ end
119
+
120
+
121
+ def enableKeychain
122
+ @keychain.setEnabled(true)
123
+ setTabEnabled(@tabs[:keychain], true)
124
+ end
125
+
126
+
127
+ def enableDeviceFunctions
128
+ enableCycript
129
+ enableLog
130
+ enablePasteboard
131
+ enableKeychain
132
+ end
133
+
134
+ def disable_all
135
+ setTabEnabled(@tabs[:local_storage], false)
136
+ setTabEnabled(@tabs[:log], false)
137
+ setTabEnabled(@tabs[:app_binary],false)
138
+ setTabEnabled(@tabs[:url_handlers],false)
139
+ setTabEnabled(@tabs[:pasteboard],false)
140
+ # setTabEnabled(@tabs[:cycript],false)
141
+ # setTabEnabled(@tabs[:isnoop],false)
142
+ setTabEnabled(@tabs[:fs_viewer],false)
143
+ setTabEnabled(@tabs[:keychain],false)
144
+ setTabEnabled(@tabs[:tools],false)
145
+ end
146
+
147
+ def clear
148
+ @tabs.each { |tab|
149
+ tab.clear
150
+ }
151
+
152
+ end
153
+
154
+ def refresh_current_tab
155
+ currentWidget.refresh_current_tab
156
+ end
157
+
158
+ def refresh_app_binary
159
+ enableAppBinary
160
+ end
161
+
162
+ def app_changed
163
+ clear
164
+ enableLocalStorage
165
+ enableURLHandlers
166
+ # refresh_current_tab
167
+ @app_binary.refresh
168
+ enableFSViewer
169
+ @fs_viewer.set_start $selected_app.app_dir
170
+ enableTools
171
+ @tools.enable_screenshot
172
+
173
+
174
+ end
175
+
176
+
177
+
178
+ end
179
+ end
@@ -0,0 +1,116 @@
1
+ require_relative 'pb_watcher_thread'
2
+ require_relative 'log_plain_text_edit'
3
+
4
+ module Idb
5
+ class PasteboardMonitorWidget < Qt::Widget
6
+
7
+ def initialize *args
8
+ super *args
9
+
10
+ @pbs_to_watch = Hash.new
11
+ @pbs_to_watch["general"] = ""
12
+
13
+
14
+ @stop = Qt::PushButton.new "Stop"
15
+ @stop.setEnabled(false)
16
+ @stop.connect(SIGNAL :released) {
17
+ @start.setEnabled(true)
18
+ @stop.setEnabled(false)
19
+ stop_log
20
+ @pb_config.setEnabled(true)
21
+ }
22
+
23
+ @log_window = LogPlainTextEdit.new
24
+ @log_window.setReadOnly(true)
25
+
26
+ @start = Qt::PushButton.new "Start"
27
+ @start.connect(SIGNAL :released) {
28
+ unless $device.pbwatcher_installed?
29
+ error = Qt::MessageBox.new
30
+ error.setInformativeText("pbwatcher not found on the device. Please visit the status dialog and install it.")
31
+ error.setIcon(Qt::MessageBox::Critical)
32
+ error.exec
33
+ else
34
+ @pb_config.setEnabled(false)
35
+ @start.setEnabled(false)
36
+ @stop.setEnabled(true)
37
+ launch_process
38
+ end
39
+ }
40
+
41
+
42
+ @pb_config = Qt::GroupBox.new self
43
+ @pb_config.setTitle "Pasteboard Names"
44
+ @pb_config_layout = Qt::GridLayout.new
45
+ @pb_config.setLayout @pb_config_layout
46
+
47
+ @pb_names = Qt::ListWidget.new @self
48
+
49
+ @pb_add = Qt::PushButton.new "Add"
50
+ @pb_add.connect(SIGNAL :released) {
51
+ @pbs_to_watch[@pb_text.text] = ""
52
+ @pb_names.addItem @pb_text.text
53
+ @pb_text.text = ""
54
+ @pb_remove.setEnabled(true)
55
+ }
56
+
57
+
58
+ @pb_remove = Qt::PushButton.new "Remove"
59
+ @pb_remove.setEnabled(false)
60
+ @pb_remove.connect(SIGNAL :released) {
61
+ removed_pb = @pb_names.item(@pb_names.current_row)
62
+ @pbs_to_watch.delete removed_pb.text unless removed_pb.nil?
63
+
64
+ row = @pb_names.current_row
65
+ @pb_names.takeItem row unless row.nil?
66
+ if @pb_names.count == 0
67
+ @pb_remove.setEnabled(false)
68
+ end
69
+ }
70
+
71
+ @pb_text = Qt::LineEdit.new
72
+
73
+ @pb_config_layout.addWidget @pb_names, 0, 0, 1, 2
74
+ @pb_config_layout.addWidget @pb_text, 1, 0, 1, 2
75
+ @pb_config_layout.addWidget @pb_add, 2, 0, 1, 1
76
+ @pb_config_layout.addWidget @pb_remove, 2, 1, 1, 1
77
+
78
+
79
+ layout = Qt::GridLayout.new do |h|
80
+ h.add_widget @log_window, 0,0
81
+ h.add_widget @pb_config, 0,1
82
+
83
+ h.add_widget @start, 1, 0, 1, 2
84
+ h.add_widget @stop, 2, 0, 1, 2
85
+ end
86
+ setLayout(layout)
87
+
88
+ end
89
+
90
+
91
+ def launch_process
92
+ h = HTMLEntities.new
93
+ @log_window.append_message "Please wait.."
94
+ @pbwatcher_thread = PBWatcherThread.new
95
+ @pbwatcher_thread.connect(SIGNAL('new_entry(QString)')) {|line|
96
+ color = 'black'
97
+ date, time, app, payload = line.split " ", 4
98
+ pb, data = payload.split ":", 2
99
+ if @pbs_to_watch[pb] != data
100
+ @pbs_to_watch[pb] = data
101
+ new_entry = "#{time} #{pb} => #{data}"
102
+ new_entry = new_entry.encode('utf-8', :invalid => :replace, :undef => :replace, :replace => '_')
103
+ @log_window.append_message "<font color='#{color}'>#{h.encode(new_entry.chomp)}</font>"
104
+ end
105
+
106
+
107
+ }
108
+ @pbwatcher_thread.start_pbwatcher_thread @pbs_to_watch.select{|x,y| x != 'general' }.map{|x,y| "\"#{x}\""}.join ' '
109
+
110
+ end
111
+
112
+ def stop_log
113
+ @pbwatcher_thread.stop
114
+ end
115
+ end
116
+ end
@@ -0,0 +1,5 @@
1
+ module Idb
2
+ class PathListWidgetItem < Qt::ListWidgetItem
3
+ attr_accessor :full_path
4
+ end
5
+ end
@@ -0,0 +1,63 @@
1
+ module Idb
2
+ class PBWatcherThread < Qt::Object
3
+ signals "new_entry(QString)"
4
+
5
+ def initialize *args
6
+ super *args
7
+ $terminate_pbwatcher_thread = false
8
+ end
9
+
10
+
11
+ def stop
12
+ $terminate_pbwatcher_thread = true
13
+ end
14
+
15
+
16
+ def start_pbwatcher_thread pbs
17
+ @pbwatcher_thread = Thread.new do
18
+ channel = $device.ssh.open_channel do |ch|
19
+ ch.request_pty do |ch, success|
20
+ cmd = "/var/root/pbwatcher 1 #{pbs}"
21
+ $log.info "Executing pbwatcher: #{cmd}"
22
+ ch.exec cmd do |ch, success|
23
+ $log.error "could not execute command" unless success
24
+
25
+ # "on_data" is called when the process writes something to stdout
26
+ ch.on_data do |c, data|
27
+ emit new_entry(data)
28
+ end
29
+
30
+ # "on_extended_data" is called when the process writes something to stderr
31
+ ch.on_extended_data do |c, type, data|
32
+ emit new_entry(data)
33
+ end
34
+
35
+ ch.on_close { |ch|
36
+ $log.info "pbwatcher terminated"
37
+ }
38
+ end
39
+ end
40
+ end
41
+
42
+ loop do
43
+ #TODO mutex to protect device?
44
+ #even better: make one central thread that calls process.
45
+ # and all functions using it call it to ensure its running. or auto start it.
46
+ sleep 0.5
47
+ $device.ssh.process
48
+ #$device.ssh.process 0
49
+ if $terminate_pbwatcher_thread
50
+ $log.info "Terminating pbwatcher"
51
+ channel.close
52
+ break
53
+ end
54
+ end
55
+ $log.info "Terminating thread"
56
+ end
57
+
58
+
59
+ end
60
+
61
+
62
+ end
63
+ end
@@ -0,0 +1,66 @@
1
+ require_relative 'path_list_widget_item'
2
+
3
+ module Idb
4
+ class PlistFileWidget < Qt::Widget
5
+
6
+ def initialize *args
7
+ super *args
8
+
9
+ @refresh = Qt::PushButton.new "Refresh"
10
+ @refresh.connect(SIGNAL :released) {
11
+ refresh
12
+ }
13
+
14
+
15
+ @list = Qt::ListWidget.new self
16
+ @list.connect(SIGNAL('itemDoubleClicked(QListWidgetItem*)')) { |item|
17
+ cache_name = $selected_app.cache_file item.full_path
18
+ if cache_name.nil?
19
+ $log.error "File #{item.full_path} could not be downloaded. Either the file does not exist (e.g., dead symlink) or there is a permission problem."
20
+ else
21
+ $device.ops.open cache_name
22
+ end
23
+ }
24
+ # @list.setContextMenuPolicy(Qt::CustomContextMenu);
25
+ # @list.connect(SIGNAL('customContextMenuRequested(QPoint)')) { |item|
26
+ # menu = Qt::Menu.new("Context menu", self)
27
+ # menu.addAction(Qt::Action.new("Hello", self));
28
+ # menu.exec(mapToGlobal(pos));
29
+ #
30
+ # }
31
+
32
+
33
+ # "Launch app"
34
+
35
+ layout = Qt::VBoxLayout.new do |v|
36
+ v.add_widget(@list)
37
+ v.add_widget(@refresh)
38
+ end
39
+ setLayout(layout)
40
+ end
41
+
42
+ def clear
43
+ @list.clear
44
+ end
45
+
46
+ def refresh
47
+ @list.clear
48
+ plist_files = $selected_app.find_plist_files
49
+ plist_files.each { |full_path|
50
+ item = PathListWidgetItem.new
51
+ if $device.simulator?
52
+ item.setText full_path.sub($selected_app.app_dir,'')
53
+ else
54
+ pc = $device.protection_class full_path
55
+ item.setText full_path.sub($selected_app.app_dir,'') + " => " + pc.strip
56
+ end
57
+ item.full_path = full_path
58
+ @list.addItem item
59
+ }
60
+ end
61
+
62
+
63
+
64
+
65
+ end
66
+ end