idb 1.3.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.DS_Store +0 -0
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +65 -0
- data/LICENSE.txt +22 -0
- data/README.md +29 -0
- data/Rakefile +2 -0
- data/bin/idb +5 -0
- data/idb.gemspec +41 -0
- data/lib/LICENSE +20 -0
- data/lib/README.md +54 -0
- data/lib/config/.dummy +0 -0
- data/lib/config/settings.yml +8 -0
- data/lib/gui/app_binary_tab_widget.rb +45 -0
- data/lib/gui/app_details_group_box.rb +213 -0
- data/lib/gui/app_list_dialog.rb +67 -0
- data/lib/gui/app_list_widget_item.rb +9 -0
- data/lib/gui/binary_strings_widget.rb +33 -0
- data/lib/gui/browse_filesystem_widget.rb +4 -0
- data/lib/gui/ca_manager_dialog.rb +137 -0
- data/lib/gui/cache_db_widget.rb +61 -0
- data/lib/gui/certificate_item.rb +5 -0
- data/lib/gui/console_widget.rb +163 -0
- data/lib/gui/cycript_console_widget.rb +68 -0
- data/lib/gui/cycript_thread.rb +81 -0
- data/lib/gui/device_info_group_box.rb +55 -0
- data/lib/gui/device_status_dialog.rb +351 -0
- data/lib/gui/file_system_events_widget.rb +4 -0
- data/lib/gui/fs_viewer_tab_widget.rb +245 -0
- data/lib/gui/i_device_syslog_thread.rb +47 -0
- data/lib/gui/images/check.png +0 -0
- data/lib/gui/images/folder.ico +0 -0
- data/lib/gui/images/iphone.ico +0 -0
- data/lib/gui/images/screenshot.png +0 -0
- data/lib/gui/key_chain_widget.rb +86 -0
- data/lib/gui/local_storage_tab_widget.rb +37 -0
- data/lib/gui/log_plain_text_edit.rb +18 -0
- data/lib/gui/log_widget.rb +71 -0
- data/lib/gui/main_tab_widget.rb +179 -0
- data/lib/gui/pasteboard_monitor_widget.rb +116 -0
- data/lib/gui/path_list_widget_item.rb +5 -0
- data/lib/gui/pb_watcher_thread.rb +63 -0
- data/lib/gui/plist_file_widget.rb +66 -0
- data/lib/gui/qt_ruby_variant.rb +16 -0
- data/lib/gui/screenshot_wizard.rb +169 -0
- data/lib/gui/settings_dialog.rb +69 -0
- data/lib/gui/settings_tab_widget.rb +149 -0
- data/lib/gui/shared_libraries_widget.rb +47 -0
- data/lib/gui/snoop_it_fs_events_widget.rb +150 -0
- data/lib/gui/snoop_it_keychain_widget.rb +172 -0
- data/lib/gui/snoop_it_sensitive_api_widget.rb +128 -0
- data/lib/gui/snoop_it_tab_widget.rb +27 -0
- data/lib/gui/snoop_it_update_thread.rb +48 -0
- data/lib/gui/sqlite_widget.rb +73 -0
- data/lib/gui/ssh_port_forward_tab_widget.rb +209 -0
- data/lib/gui/tool_widget.rb +94 -0
- data/lib/gui/url_handler_widget.rb +26 -0
- data/lib/gui/url_scheme_fuzz_widget.rb +103 -0
- data/lib/gui/url_scheme_widget.rb +60 -0
- data/lib/gui/weak_class_dump_widget.rb +89 -0
- data/lib/helper/ssh_port_forwarder.rb +72 -0
- data/lib/idb.rb +295 -0
- data/lib/idb/version.rb +3 -0
- data/lib/lib/CgBI.rb +153 -0
- data/lib/lib/abstract_device.rb +31 -0
- data/lib/lib/app.rb +286 -0
- data/lib/lib/app_binary.rb +57 -0
- data/lib/lib/ca_interface.rb +151 -0
- data/lib/lib/configuration.rb +0 -0
- data/lib/lib/console_launcher.rb +24 -0
- data/lib/lib/device.rb +438 -0
- data/lib/lib/device_ca_interface.rb +36 -0
- data/lib/lib/host_file_wrapper.rb +27 -0
- data/lib/lib/i_device_diagnostics_wrapper.rb +90 -0
- data/lib/lib/keychain_plist_parser.rb +15 -0
- data/lib/lib/local_operations.rb +67 -0
- data/lib/lib/otool_wrapper.rb +116 -0
- data/lib/lib/plist_util.rb +72 -0
- data/lib/lib/qt_thread_fix.rb +29 -0
- data/lib/lib/rsync_git_manager.rb +81 -0
- data/lib/lib/screen_shot_util.rb +59 -0
- data/lib/lib/settings.rb +67 -0
- data/lib/lib/simulator.rb +60 -0
- data/lib/lib/simulator_ca_interface.rb +16 -0
- data/lib/lib/snoop_it_wrapper.rb +80 -0
- data/lib/lib/ssh_operations.rb +136 -0
- data/lib/lib/ssh_port_forwarder.rb +43 -0
- data/lib/lib/tools.rb +11 -0
- data/lib/lib/url_scheme_fuzzer.rb +98 -0
- data/lib/lib/usb_muxd_wrapper.rb +32 -0
- data/lib/lib/weak_class_dump_wrapper.rb +62 -0
- data/lib/utils/dumpdecrypted/README +4 -0
- data/lib/utils/dumpdecrypted/dumpdecrypted_armv6.dylib +0 -0
- data/lib/utils/dumpdecrypted/dumpdecrypted_armv7.dylib +0 -0
- data/lib/utils/ios-ssl-kill-switch/com.isecpartners.nabla.sslkillswitch_v0.5-iOS_6.1.deb +0 -0
- data/lib/utils/keychain_dump/README +2 -0
- data/lib/utils/keychain_dump/keychain_dump +0 -0
- data/lib/utils/pbwatcher/pbwatcher +0 -0
- data/lib/utils/pcviewer/protectionclassviewer +0 -0
- data/lib/utils/weak_class_dump/README +5 -0
- data/lib/utils/weak_class_dump/weak_classdump.cy +726 -0
- metadata +412 -0
@@ -0,0 +1,26 @@
|
|
1
|
+
require_relative '../lib/url_scheme_fuzzer'
|
2
|
+
require_relative 'url_scheme_fuzz_widget'
|
3
|
+
require_relative 'url_scheme_widget'
|
4
|
+
|
5
|
+
module Idb
|
6
|
+
class URLHandlerWidget < Qt::TabWidget
|
7
|
+
|
8
|
+
def initialize *args
|
9
|
+
super *args
|
10
|
+
|
11
|
+
@tabs = Hash.new
|
12
|
+
|
13
|
+
@url_scheme = URLSchemeWidget.new self
|
14
|
+
@tabs[:scheme] = addTab(@url_scheme, "URL Schemes")
|
15
|
+
|
16
|
+
@url_fuzz = URLSchemeFuzzWidget.new self
|
17
|
+
@tabs[:fuzzer] = addTab(@url_fuzz, "Fuzzer")
|
18
|
+
end
|
19
|
+
|
20
|
+
def disable_for_simulator
|
21
|
+
@tabs[:fuzzer]
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module Idb
|
2
|
+
class URLSchemeFuzzWidget < Qt::Widget
|
3
|
+
|
4
|
+
def initialize *args
|
5
|
+
super *args
|
6
|
+
|
7
|
+
@fuzz_config_layout = Qt::GridLayout.new
|
8
|
+
setLayout @fuzz_config_layout
|
9
|
+
|
10
|
+
@fuzz_config_fuzz_strings = Qt::ListWidget.new self
|
11
|
+
@fuzz_config_fuzz_strings_label = Qt::Label.new "<b>Fuzz Strings:<b>"
|
12
|
+
@fuzzer = URLSchemeFuzzer.new
|
13
|
+
@fuzzer.default_fuzz_strings.each { |x|
|
14
|
+
@fuzz_config_fuzz_strings.addItem x
|
15
|
+
}
|
16
|
+
|
17
|
+
@fuzz_config_new_fuzz = Qt::LineEdit.new
|
18
|
+
@fuzz_config_add_fuzz = Qt::PushButton.new "Add"
|
19
|
+
@fuzz_config_add_fuzz.connect(SIGNAL :released) {
|
20
|
+
@fuzz_config_fuzz_strings.addItem @fuzz_config_new_fuzz.text
|
21
|
+
@fuzz_config_new_fuzz.text = ""
|
22
|
+
@fuzz_config_remove_fuzz.setEnabled(true)
|
23
|
+
}
|
24
|
+
@fuzz_config_remove_fuzz = Qt::PushButton.new "Remove"
|
25
|
+
@fuzz_config_remove_fuzz.connect(SIGNAL :released) {
|
26
|
+
row = @fuzz_config_fuzz_strings.current_row
|
27
|
+
@fuzz_config_fuzz_strings.takeItem row unless row.nil?
|
28
|
+
if @fuzz_config_fuzz_strings.count == 0
|
29
|
+
@fuzz_config_remove_fuzz.setEnabled(false)
|
30
|
+
end
|
31
|
+
}
|
32
|
+
|
33
|
+
|
34
|
+
@fuzz_strings = Qt::GroupBox.new self
|
35
|
+
@fuzz_strings.setTitle "Fuzz Strings"
|
36
|
+
@fuzz_strings_layout = Qt::GridLayout.new
|
37
|
+
@fuzz_strings.setLayout @fuzz_strings_layout
|
38
|
+
|
39
|
+
@fuzz_strings_layout.addWidget @fuzz_config_fuzz_strings, 1,0, 1, 2
|
40
|
+
@fuzz_strings_layout.addWidget @fuzz_config_new_fuzz, 2,0, 1 ,2
|
41
|
+
@fuzz_strings_layout.addWidget @fuzz_config_add_fuzz, 3,0
|
42
|
+
@fuzz_strings_layout.addWidget @fuzz_config_remove_fuzz, 3,1
|
43
|
+
|
44
|
+
|
45
|
+
|
46
|
+
@fuzz_template = Qt::GroupBox.new self
|
47
|
+
@fuzz_template.setTitle "Fuzz Template"
|
48
|
+
@fuzz_template_layout = Qt::GridLayout.new
|
49
|
+
@fuzz_template.setLayout @fuzz_template_layout
|
50
|
+
@fuzz_config_template_label = Qt::Label.new "Use $@$ to mark injection fuzz points"
|
51
|
+
@fuzz_config_template = Qt::LineEdit.new
|
52
|
+
|
53
|
+
|
54
|
+
@fuzz_config_button = Qt::PushButton.new "Fuzz"
|
55
|
+
@fuzz_config_button.connect(SIGNAL :released) {
|
56
|
+
@fuzzer.delete_old_reports
|
57
|
+
|
58
|
+
|
59
|
+
fuzz_strings = Array.new
|
60
|
+
0.upto(@fuzz_config_fuzz_strings.count-1) { |i|
|
61
|
+
fuzz_strings << @fuzz_config_fuzz_strings.item(i).text
|
62
|
+
}
|
63
|
+
input = @fuzzer.generate_inputs @fuzz_config_template.text, fuzz_strings
|
64
|
+
input.each { |url|
|
65
|
+
#TODO: progress bar
|
66
|
+
#TODO: kill app after each run
|
67
|
+
#TODO: check for crash report
|
68
|
+
crashed = @fuzzer.execute url
|
69
|
+
@log_window.append_message "#{url}\t#{crashed}"
|
70
|
+
break if crashed
|
71
|
+
Qt::CoreApplication.processEvents
|
72
|
+
sleep 2
|
73
|
+
Qt::CoreApplication.processEvents
|
74
|
+
}
|
75
|
+
}
|
76
|
+
|
77
|
+
@fuzz_template_layout.addWidget @fuzz_config_template_label, 0,0
|
78
|
+
@fuzz_template_layout.addWidget @fuzz_config_template, 1,0
|
79
|
+
@fuzz_template_layout.addWidget @fuzz_config_button, 2,0, 1, 2
|
80
|
+
|
81
|
+
|
82
|
+
@fuzz_result = Qt::GroupBox.new self
|
83
|
+
@fuzz_result.setTitle "Results"
|
84
|
+
@fuzz_result_layout = Qt::GridLayout.new
|
85
|
+
@fuzz_result.setLayout @fuzz_result_layout
|
86
|
+
@log_window = LogPlainTextEdit.new
|
87
|
+
@log_window.setReadOnly(true)
|
88
|
+
@fuzz_result_layout.addWidget @log_window, 0,0
|
89
|
+
|
90
|
+
|
91
|
+
@fuzz_config_layout.addWidget @fuzz_strings, 0,0
|
92
|
+
@fuzz_config_layout.addWidget @fuzz_template, 1, 0
|
93
|
+
@fuzz_config_layout.addWidget @fuzz_result, 0, 1, 2, 1
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
|
102
|
+
end
|
103
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Idb
|
2
|
+
class URLSchemeWidget < Qt::Widget
|
3
|
+
def initialize *args
|
4
|
+
super *args
|
5
|
+
|
6
|
+
@url_handler_list = Qt::GroupBox.new self
|
7
|
+
@url_handler_list.setTitle "List of registered URL Handlers"
|
8
|
+
@url_handler_list_layout = Qt::GridLayout.new
|
9
|
+
@url_handler_list.setLayout @url_handler_list_layout
|
10
|
+
|
11
|
+
@refresh = Qt::PushButton.new "Refresh"
|
12
|
+
@refresh.connect(SIGNAL :released) {
|
13
|
+
refresh
|
14
|
+
}
|
15
|
+
|
16
|
+
@list = Qt::ListWidget.new self
|
17
|
+
@list.connect(SIGNAL('itemClicked(QListWidgetItem*)')) { |item|
|
18
|
+
@url_open_string.text = item.text + "://"
|
19
|
+
}
|
20
|
+
|
21
|
+
@url_handler_list_layout.add_widget @list, 0, 0
|
22
|
+
@url_handler_list_layout.add_widget @refresh, 1, 0
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
@url_open = Qt::GroupBox.new self
|
27
|
+
@url_open.setTitle "Open URL"
|
28
|
+
@url_open_layout = Qt::GridLayout.new
|
29
|
+
@url_open.setLayout @url_open_layout
|
30
|
+
|
31
|
+
@url_open_string = Qt::LineEdit.new
|
32
|
+
@url_open_button = Qt::PushButton.new "Open"
|
33
|
+
@url_open_button.connect(SIGNAL :released) {
|
34
|
+
$device.open_url @url_open_string.text
|
35
|
+
}
|
36
|
+
@url_open_layout.addWidget @url_open_string, 0,0
|
37
|
+
@url_open_layout.addWidget @url_open_button, 1,0
|
38
|
+
|
39
|
+
layout = Qt::GridLayout.new do |v|
|
40
|
+
v.add_widget @url_handler_list, 0, 0
|
41
|
+
v.add_widget @url_open, 0, 1
|
42
|
+
v.add_widget @fuzz_config, 1, 0, 2, 2
|
43
|
+
|
44
|
+
end
|
45
|
+
setLayout(layout)
|
46
|
+
end
|
47
|
+
|
48
|
+
def refresh
|
49
|
+
@list.clear
|
50
|
+
url_handlers = $selected_app.get_url_handlers
|
51
|
+
url_handlers.each { |x|
|
52
|
+
@list.addItem x
|
53
|
+
}
|
54
|
+
end
|
55
|
+
|
56
|
+
def clear
|
57
|
+
@list.clear
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
require_relative '../lib/weak_class_dump_wrapper'
|
2
|
+
|
3
|
+
module Idb
|
4
|
+
class WeakClassDumpWidget < Qt::Widget
|
5
|
+
def initialize *args
|
6
|
+
super *args
|
7
|
+
|
8
|
+
|
9
|
+
|
10
|
+
@layout = Qt::GridLayout.new
|
11
|
+
setLayout @layout
|
12
|
+
|
13
|
+
@run = Qt::PushButton.new "Dump Classes"
|
14
|
+
@layout.addWidget @run, 0,0
|
15
|
+
@run.connect(SIGNAL :released) {
|
16
|
+
run_cycript
|
17
|
+
}
|
18
|
+
|
19
|
+
|
20
|
+
@results = Qt::PushButton.new "List Results"
|
21
|
+
@layout.addWidget @results, 0,1
|
22
|
+
|
23
|
+
@results.connect(SIGNAL :released) {
|
24
|
+
@weak_class_dump_wrapper.pull_header_files
|
25
|
+
refresh_header_list
|
26
|
+
}
|
27
|
+
|
28
|
+
@open_folder = Qt::PushButton.new "Open Folder"
|
29
|
+
@layout.addWidget @open_folder, 0,2
|
30
|
+
|
31
|
+
@open_folder.connect(SIGNAL :released) {
|
32
|
+
Launchy.open @local_path
|
33
|
+
}
|
34
|
+
|
35
|
+
|
36
|
+
@header_list = Qt::ListWidget.new self
|
37
|
+
@header_list_label = Qt::Label.new "<b>Header Files:<b>"
|
38
|
+
@header_list.connect(SIGNAL('itemClicked(QListWidgetItem*)')) { |item|
|
39
|
+
@content.clear
|
40
|
+
@content.appendHtml(CodeRay.scan_file(@local_path + "/" + item.text).page(
|
41
|
+
:line_numbers => nil,
|
42
|
+
:css => :style
|
43
|
+
))
|
44
|
+
}
|
45
|
+
|
46
|
+
@header_list.connect(SIGNAL('itemDoubleClicked(QListWidgetItem*)')) { |item|
|
47
|
+
$device.ops.open @local_path + "/" + item.text
|
48
|
+
}
|
49
|
+
|
50
|
+
@content = Qt::PlainTextEdit.new
|
51
|
+
@content.setReadOnly(true)
|
52
|
+
|
53
|
+
@splitter = Qt::Splitter.new
|
54
|
+
@splitter.addWidget @header_list
|
55
|
+
@splitter.addWidget @content
|
56
|
+
@splitter.setStretchFactor 1, 1.5
|
57
|
+
@splitter.setSizePolicy(Qt::SizePolicy::Expanding, Qt::SizePolicy::Expanding)
|
58
|
+
@layout.addWidget @splitter, 1, 0, 1, 3
|
59
|
+
|
60
|
+
end
|
61
|
+
|
62
|
+
def run_cycript
|
63
|
+
@local_path = "#{$selected_app.cache_dir}/weak_class_dump_headers"
|
64
|
+
@weak_class_dump_wrapper = WeakClassDumpWrapper.new @local_path
|
65
|
+
@weak_class_dump_wrapper.execute_cycript
|
66
|
+
|
67
|
+
error = Qt::MessageBox.new
|
68
|
+
error.setInformativeText("Cycript dumping the class information... This may take some time. On success the device will play the lock sound. You can then list the header files and view them.")
|
69
|
+
error.setIcon(Qt::MessageBox::Information)
|
70
|
+
error.exec
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
def refresh_header_list
|
75
|
+
@header_list.clear
|
76
|
+
@weak_class_dump_wrapper.get_header_files.each { |x|
|
77
|
+
@header_list.addItem x
|
78
|
+
}
|
79
|
+
end
|
80
|
+
|
81
|
+
|
82
|
+
def refresh
|
83
|
+
unless $selected_app.cache_dir.nil?
|
84
|
+
@local_path = "#{$selected_app.cache_dir}/weak_class_dump_headers"
|
85
|
+
@weak_class_dump_wrapper = WeakClassDumpWrapper.new @local_path
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require_relative '../lib/ssh_port_forwarder'
|
3
|
+
require_relative '../lib/settings'
|
4
|
+
require_relative '../lib/usb_muxd_wrapper'
|
5
|
+
require 'log4r'
|
6
|
+
|
7
|
+
module Idb
|
8
|
+
class SSHPortForwarderHelper
|
9
|
+
def self.run
|
10
|
+
|
11
|
+
# initialize log
|
12
|
+
$log = Log4r::Logger.new 'port_forward'
|
13
|
+
outputter = Log4r::Outputter.stdout
|
14
|
+
outputter.formatter = Log4r::PatternFormatter.new(:pattern => "[%l] %d :: %c :: %m")
|
15
|
+
$log.outputters = [ outputter ]
|
16
|
+
|
17
|
+
# load settings
|
18
|
+
settings_path = File.dirname(ENV['HOME'] + "/.idb/config/")
|
19
|
+
settings_filename = "settings.yml"
|
20
|
+
settings = Settings.new "#{settings_path}/#{settings_filename}"
|
21
|
+
|
22
|
+
if settings['device_connection_mode'] == "ssh"
|
23
|
+
$log.debug "Connecting via SSH"
|
24
|
+
|
25
|
+
# setup forwards
|
26
|
+
$ssh_forwards = SSHPortForwarder.new settings['ssh_username'], settings['ssh_password'], settings['ssh_host'], settings['ssh_port']
|
27
|
+
else
|
28
|
+
$log.debug "Connecting via USB"
|
29
|
+
|
30
|
+
$usbmuxd = USBMuxdWrapper.new
|
31
|
+
proxy_port = $usbmuxd.find_available_port
|
32
|
+
$log.debug "Using port #{proxy_port} for SSH forwarding"
|
33
|
+
|
34
|
+
$usbmuxd.proxy proxy_port, settings['ssh_port']
|
35
|
+
# setup forwards
|
36
|
+
$ssh_forwards = SSHPortForwarder.new settings['ssh_username'], settings['ssh_password'], 'localhost', proxy_port
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
$log.info 'Setting up port forwarding...'
|
41
|
+
|
42
|
+
# Special idb internal port
|
43
|
+
$ssh_forwards.add_remote_forward Integer(settings['idb_utility_port']), 'localhost', Integer(settings['idb_utility_port'])
|
44
|
+
|
45
|
+
unless settings['remote_forwards'].nil?
|
46
|
+
settings['remote_forwards'].each { |x|
|
47
|
+
$ssh_forwards.add_remote_forward Integer(x['remote_port']), x['local_host'], Integer(x['local_port'])
|
48
|
+
}
|
49
|
+
end
|
50
|
+
|
51
|
+
unless settings['local_forwards'].nil?
|
52
|
+
settings['local_forwards'].each { |x|
|
53
|
+
$ssh_forwards.add_local_forward Integer(x['local_port']), x['remote_host'], Integer(x['remote_port'])
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
# start event loop
|
58
|
+
$ssh_forwards.start
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
begin
|
63
|
+
SSHPortForwarderHelper.run
|
64
|
+
rescue SystemExit, Interrupt
|
65
|
+
$log.info "Cleaning up before exiting"
|
66
|
+
$log.info "Closing SSH connection"
|
67
|
+
$ssh_forwards.stop
|
68
|
+
$log.info "Stopping any SSH via USB forwarding"
|
69
|
+
$usbmuxd.stop_all
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
data/lib/idb.rb
ADDED
@@ -0,0 +1,295 @@
|
|
1
|
+
require 'Qt'
|
2
|
+
require 'awesome_print'
|
3
|
+
require_relative 'lib/settings'
|
4
|
+
require_relative 'lib/simulator'
|
5
|
+
require_relative 'lib/device'
|
6
|
+
require_relative 'lib/qt_thread_fix'
|
7
|
+
require_relative 'gui/app_list_widget_item'
|
8
|
+
require_relative 'gui/screenshot_wizard'
|
9
|
+
require_relative 'gui/app_details_group_box'
|
10
|
+
require_relative 'gui/app_list_dialog'
|
11
|
+
require_relative 'gui/main_tab_widget'
|
12
|
+
require_relative 'gui/settings_dialog'
|
13
|
+
require_relative 'gui/device_info_group_box'
|
14
|
+
require_relative 'gui/ca_manager_dialog'
|
15
|
+
|
16
|
+
module Idb
|
17
|
+
TARGET = "Hello"
|
18
|
+
|
19
|
+
# logging
|
20
|
+
require 'log4r'
|
21
|
+
|
22
|
+
$width = 1024
|
23
|
+
$height = 768
|
24
|
+
|
25
|
+
class Idb < Qt::MainWindow
|
26
|
+
|
27
|
+
def initialize
|
28
|
+
super
|
29
|
+
|
30
|
+
|
31
|
+
# initialize log
|
32
|
+
$log = Log4r::Logger.new 'idb'
|
33
|
+
outputter = Log4r::Outputter.stdout
|
34
|
+
outputter.formatter = Log4r::PatternFormatter.new(:pattern => "[%l] %d :: %c :: %m")
|
35
|
+
|
36
|
+
$log.outputters = [ outputter ]
|
37
|
+
|
38
|
+
if RUBY_VERSION.start_with? "2.0"
|
39
|
+
error = Qt::MessageBox.new
|
40
|
+
error.setInformativeText("You are using ruby 2.0 which does not work well with QT bindings: custom signals don't work. It is very likely that idb will not function as intended. Consider using ruby 1.9 or 2.1 instead.")
|
41
|
+
error.setIcon(Qt::MessageBox::Critical)
|
42
|
+
error.exec
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
|
47
|
+
# enable threading. See https://github.com/ryanmelt/qtbindings/issues/63
|
48
|
+
@thread_fix = QtThreadFix.new
|
49
|
+
settings_path = File.dirname(ENV['HOME'] + "/.idb/config/")
|
50
|
+
$tmp_path = ENV['HOME'] + "/.idb/tmp/"
|
51
|
+
puts $tmp_path
|
52
|
+
unless File.directory?(settings_path)
|
53
|
+
$log.info "Creating settings directory: #{settings_path}"
|
54
|
+
FileUtils.mkdir_p(settings_path)
|
55
|
+
end
|
56
|
+
|
57
|
+
settings_filename = "settings.yml"
|
58
|
+
$settings = Settings.new "#{settings_path}/#{settings_filename}"
|
59
|
+
|
60
|
+
setWindowTitle "idb"
|
61
|
+
Qt::CoreApplication::setApplicationName("idb")
|
62
|
+
setWindowIconText('idb')
|
63
|
+
init_ui
|
64
|
+
|
65
|
+
# size = Qt::Size.new($width, $height)
|
66
|
+
# size = size.expandedTo(self.minimumSizeHint())
|
67
|
+
# resize(size)
|
68
|
+
# resize $width, $height
|
69
|
+
|
70
|
+
# center
|
71
|
+
|
72
|
+
# showMaximized();
|
73
|
+
# show
|
74
|
+
# self.raise
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.execute_in_main_thread(blocking = false, sleep_period = 0.001)
|
78
|
+
if Thread.current != Thread.main
|
79
|
+
complete = false
|
80
|
+
QtThreadFix.ruby_thread_queue << lambda {|| yield; complete = true}
|
81
|
+
if blocking
|
82
|
+
until complete
|
83
|
+
sleep(sleep_period)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
else
|
87
|
+
yield
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def init_ui
|
92
|
+
# setup central widget and grid layout
|
93
|
+
@central_widget = Qt::Widget.new self
|
94
|
+
self.setCentralWidget @central_widget
|
95
|
+
@grid = Qt::GridLayout.new @central_widget
|
96
|
+
|
97
|
+
@grid.setColumnMinimumWidth(0,450)
|
98
|
+
|
99
|
+
|
100
|
+
# Box for App details
|
101
|
+
@app_details = AppDetailsGroupBox.new @central_widget
|
102
|
+
@app_details.connect(SIGNAL(:app_changed)) {
|
103
|
+
@main_tabs.app_changed
|
104
|
+
@app_binary.app_changed
|
105
|
+
@menu_item_screenshot.setEnabled(true)
|
106
|
+
}
|
107
|
+
@app_details.connect(SIGNAL(:show_device_status)) {
|
108
|
+
@device_status = DeviceStatusDialog.new
|
109
|
+
@device_status.exec
|
110
|
+
}
|
111
|
+
|
112
|
+
|
113
|
+
@grid.addWidget @app_details, 0,0
|
114
|
+
|
115
|
+
# App Binary Details
|
116
|
+
@app_binary = AppBinaryGroupBox.new @central_widget
|
117
|
+
@grid.addWidget @app_binary, 1,0
|
118
|
+
@app_binary.connect(SIGNAL('binary_analyzed()')) {
|
119
|
+
@main_tabs.refresh_app_binary
|
120
|
+
}
|
121
|
+
|
122
|
+
@spacer = Qt::SpacerItem.new 0,1, Qt::SizePolicy::Fixed, Qt::SizePolicy::Expanding
|
123
|
+
@grid.addItem @spacer, 2,0
|
124
|
+
|
125
|
+
# Main Tab Widget
|
126
|
+
@main_tabs = MainTabWidget.new @central_widget
|
127
|
+
@grid.addWidget @main_tabs, 0,1,3,1
|
128
|
+
|
129
|
+
# device Details
|
130
|
+
@device_details = DeviceInfoGroupBox.new @central_widget
|
131
|
+
@device_details.connect(SIGNAL :disconnect) {
|
132
|
+
@main_tabs.disable_all
|
133
|
+
@app_binary.clear
|
134
|
+
@app_binary.disable_analyze_binary
|
135
|
+
@app_details.clear
|
136
|
+
@app_details.disable_select_app
|
137
|
+
@usb_device.setChecked(false)
|
138
|
+
}
|
139
|
+
@grid.addWidget @device_details, 3,0,2,2
|
140
|
+
|
141
|
+
menu
|
142
|
+
|
143
|
+
end
|
144
|
+
|
145
|
+
|
146
|
+
def menu
|
147
|
+
|
148
|
+
##########################################
|
149
|
+
# MENU
|
150
|
+
##########################################
|
151
|
+
# File
|
152
|
+
menu_item_settings = Qt::Action.new "&Settings", self
|
153
|
+
menu_item_settings.connect(SIGNAL :triggered) {
|
154
|
+
setting = SettingsDialog.new self
|
155
|
+
setting.connect(SIGNAL :accepted) {
|
156
|
+
if $settings['device_connection_mode'] == "ssh"
|
157
|
+
@usb_device.setText("SSH Device")
|
158
|
+
else
|
159
|
+
@usb_device.setText("USB Device")
|
160
|
+
end
|
161
|
+
}
|
162
|
+
setting.exec
|
163
|
+
}
|
164
|
+
@menu_file = menuBar().addMenu "&File"
|
165
|
+
@menu_file.addAction menu_item_settings
|
166
|
+
|
167
|
+
@menu_item_screenshot = Qt::Action.new "&Screenshot", self
|
168
|
+
@menu_item_screenshot.setEnabled(false)
|
169
|
+
@menu_item_screenshot.connect(SIGNAL :triggered) {
|
170
|
+
tool = ScreenShotWizard::ScreenShotWizard.new_with_app $selected_app
|
171
|
+
}
|
172
|
+
@menu_item_cert = Qt::Action.new "&Certificate Manager", self
|
173
|
+
@menu_item_cert.setEnabled(false)
|
174
|
+
@menu_item_cert.connect(SIGNAL :triggered) {
|
175
|
+
ca = CAManagerDialog.new self
|
176
|
+
ca.exec
|
177
|
+
}
|
178
|
+
@menu_tools = menuBar().addMenu "&Tools"
|
179
|
+
@menu_tools.addAction @menu_item_screenshot
|
180
|
+
@menu_tools.addAction @menu_item_cert
|
181
|
+
|
182
|
+
|
183
|
+
#Devices
|
184
|
+
@sim_group = Qt::ActionGroup.new @menu_devices
|
185
|
+
|
186
|
+
@menu_devices = menuBar().addMenu "&Devices"
|
187
|
+
@usb_device = Qt::Action.new "USB Device", self
|
188
|
+
if $settings['device_connection_mode'] == "ssh"
|
189
|
+
@usb_device.setText("SSH Device")
|
190
|
+
else
|
191
|
+
@usb_device.setText("USB Device")
|
192
|
+
end
|
193
|
+
|
194
|
+
@usb_device.setCheckable(true)
|
195
|
+
@usb_device.connect(SIGNAL(:triggered)) { |x|
|
196
|
+
$device.disconnect unless $device.nil?
|
197
|
+
|
198
|
+
progress = Qt::ProgressDialog.new "Connecting to device. Please wait...", nil, 0, 2, @central_widget
|
199
|
+
progress.setWindowModality(Qt::WindowModal);
|
200
|
+
progress.setValue 1
|
201
|
+
progress.show
|
202
|
+
progress.raise
|
203
|
+
|
204
|
+
begin
|
205
|
+
$device = Device.new $settings.ssh_username,
|
206
|
+
$settings.ssh_password,
|
207
|
+
$settings.ssh_host,
|
208
|
+
$settings.ssh_port
|
209
|
+
rescue
|
210
|
+
|
211
|
+
end
|
212
|
+
unless $device.nil?
|
213
|
+
unless $device.configured?
|
214
|
+
puts "Y"
|
215
|
+
$log.info "Device not seen before. Opening status page."
|
216
|
+
error = Qt::MessageBox.new self
|
217
|
+
error.setInformativeText("This device has not been configured yet. Opening Status page to verify all required tools are installed on the device.")
|
218
|
+
error.setIcon(Qt::MessageBox::Warning)
|
219
|
+
error.exec
|
220
|
+
@device_status = DeviceStatusDialog.new
|
221
|
+
@device_status.exec
|
222
|
+
end
|
223
|
+
|
224
|
+
|
225
|
+
|
226
|
+
|
227
|
+
@app_details.enable_select_app
|
228
|
+
@device_details.update_device
|
229
|
+
@menu_item_cert.setEnabled(true)
|
230
|
+
@main_tabs.enableDeviceFunctions
|
231
|
+
|
232
|
+
end
|
233
|
+
|
234
|
+
progress.reset
|
235
|
+
}
|
236
|
+
menu_item = @menu_devices.addAction @usb_device
|
237
|
+
@sim_group.addAction @usb_device
|
238
|
+
|
239
|
+
|
240
|
+
x = @menu_devices.addSeparator
|
241
|
+
x.setText("Simulators")
|
242
|
+
|
243
|
+
Simulator.get_simulators.each { |s|
|
244
|
+
action = @menu_devices.addAction s
|
245
|
+
@sim_group.addAction action
|
246
|
+
action.setCheckable(true)
|
247
|
+
action.connect(SIGNAL(:triggered)) { |x|
|
248
|
+
$device = Simulator.new s
|
249
|
+
@app_details.enable_select_app
|
250
|
+
@device_details.update_device
|
251
|
+
@menu_item_cert.setEnabled(true)
|
252
|
+
}
|
253
|
+
|
254
|
+
@menu_devices.addAction action
|
255
|
+
}
|
256
|
+
|
257
|
+
|
258
|
+
|
259
|
+
|
260
|
+
end
|
261
|
+
|
262
|
+
|
263
|
+
def center
|
264
|
+
qdw = Qt::DesktopWidget.new
|
265
|
+
|
266
|
+
screenWidth = qdw.width
|
267
|
+
screenHeight = qdw.height
|
268
|
+
|
269
|
+
x = (screenWidth - $width) / 2
|
270
|
+
y = (screenHeight - $height) / 2
|
271
|
+
|
272
|
+
move x, y
|
273
|
+
end
|
274
|
+
|
275
|
+
def self.run
|
276
|
+
app = Qt::Application.new ARGV
|
277
|
+
app.setWindowIcon(Qt::Icon.new File.join(File.dirname(File.expand_path(__FILE__)), '/gui/images/iphone.ico'))
|
278
|
+
|
279
|
+
app.setApplicationName("idb")
|
280
|
+
|
281
|
+
idb = Idb.new
|
282
|
+
idb.setWindowState Qt::WindowActive
|
283
|
+
idb.showMaximized
|
284
|
+
idb.raise
|
285
|
+
app.exec
|
286
|
+
|
287
|
+
$log.info "Performing cleanup before exiting."
|
288
|
+
$device.close unless $device.nil?
|
289
|
+
$log.info "Thanks for using idb."
|
290
|
+
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
|
295
|
+
end
|