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.
- checksums.yaml +4 -4
- data/.rubocop.yml +30 -0
- data/Gemfile.lock +5 -0
- data/idb.gemspec +1 -0
- data/lib/gui/app_binary_tab_widget.rb +7 -14
- data/lib/gui/app_details_group_box.rb +63 -88
- data/lib/gui/app_list_dialog.rb +29 -35
- data/lib/gui/app_list_widget_item.rb +1 -5
- data/lib/gui/app_tab_widget.rb +17 -22
- data/lib/gui/binary_strings_widget.rb +7 -15
- data/lib/gui/ca_manager_dialog.rb +32 -54
- data/lib/gui/cache_db_widget.rb +21 -26
- data/lib/gui/certificate_item.rb +2 -2
- data/lib/gui/default_protection_class_group_widget.rb +7 -12
- data/lib/gui/device_info_group_box.rb +26 -23
- data/lib/gui/main_tab_widget.rb +2 -21
- data/lib/gui/shared_libraries_widget.rb +1 -1
- data/lib/gui/sqlite_widget.rb +1 -3
- data/lib/gui/weak_class_dump_widget.rb +1 -1
- data/lib/idb.rb +3 -3
- data/lib/idb/version.rb +1 -1
- data/lib/lib/abstract_device.rb +7 -11
- data/lib/lib/app.rb +49 -59
- data/lib/lib/app_binary.rb +18 -29
- data/lib/lib/ca_interface.rb +46 -59
- data/lib/lib/device.rb +68 -155
- data/lib/lib/device_ca_interface.rb +7 -13
- data/lib/lib/host_file_wrapper.rb +6 -8
- data/lib/lib/ios8_last_launch_services_map_wrapper.rb +11 -18
- data/lib/lib/local_operations.rb +24 -32
- data/lib/lib/otool_wrapper.rb +30 -33
- data/lib/lib/rsync_git_manager.rb +26 -22
- data/lib/lib/screen_shot_util.rb +20 -28
- data/lib/lib/settings.rb +14 -17
- data/lib/lib/simulator.rb +11 -16
- data/lib/lib/simulator_ca_interface.rb +1 -3
- data/lib/lib/ssh_operations.rb +49 -65
- data/lib/lib/ssh_port_forwarder.rb +9 -13
- data/lib/lib/tools.rb +3 -3
- data/lib/lib/url_scheme_fuzzer.rb +41 -49
- data/lib/lib/usb_muxd_wrapper.rb +6 -8
- data/lib/lib/weak_class_dump_wrapper.rb +15 -16
- metadata +19 -9
- data/lib/gui/console_widget.rb +0 -163
- data/lib/gui/cycript_console_widget.rb +0 -68
- data/lib/gui/cycript_thread.rb +0 -81
- data/lib/lib/console_launcher.rb +0 -24
- data/lib/lib/i_device_diagnostics_wrapper.rb +0 -90
- 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
|
23
|
-
FileUtils.copy_file @db_path, "#{@db_path}-#{Time.now
|
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
|
29
|
-
FileUtils.copy_file @db_path, "#{@db_path}-#{Time.now
|
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
|
17
|
+
def save(text)
|
19
18
|
# upload
|
20
|
-
File.open(@cache_path,"w")
|
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
|
12
|
-
|
13
|
-
|
14
|
-
|
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
|
-
|
26
|
-
|
27
|
-
|
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
|
data/lib/lib/local_operations.rb
CHANGED
@@ -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
|
-
|
11
|
-
|
12
|
-
return true
|
7
|
+
def download(a, b)
|
8
|
+
FileUtils.copy_file(a, b)
|
9
|
+
true
|
13
10
|
end
|
14
11
|
|
15
|
-
|
16
|
-
|
17
|
-
File.directory? path
|
12
|
+
def directory?(path)
|
13
|
+
File.directory? path
|
18
14
|
end
|
19
15
|
|
20
|
-
def mtime
|
16
|
+
def mtime(path)
|
21
17
|
File.mtime path
|
22
18
|
end
|
23
19
|
|
24
|
-
def open
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
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
|
29
|
+
def list_dir(path)
|
36
30
|
Dir.entries path
|
37
31
|
end
|
38
32
|
|
39
|
-
def list_dir_full
|
33
|
+
def list_dir_full(path)
|
40
34
|
Dir.entries path
|
41
35
|
end
|
42
36
|
|
43
|
-
def dir_glob
|
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?
|
49
|
-
File.
|
42
|
+
def file_exists?(file)
|
43
|
+
File.exist? file
|
50
44
|
end
|
51
45
|
|
52
|
-
def execute
|
46
|
+
def execute(cmd)
|
53
47
|
`#{cmd}`
|
54
48
|
end
|
55
49
|
|
56
|
-
def execute_fork
|
50
|
+
def execute_fork(cmd)
|
57
51
|
(pid = fork) ? Process.detach(pid) : exec(cmd)
|
58
52
|
end
|
59
53
|
|
60
|
-
def launch_app
|
54
|
+
def launch_app(command, app)
|
61
55
|
$log.info "Executing #{command} #{app}"
|
62
|
-
|
56
|
+
execute_fork("#{command} \"#{app}\"")
|
63
57
|
end
|
64
|
-
|
65
|
-
|
66
58
|
end
|
67
|
-
end
|
59
|
+
end
|
data/lib/lib/otool_wrapper.rb
CHANGED
@@ -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
|
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
|
-
|
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 =
|
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
|
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?
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
if symbols.include? "_objc_release"
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
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 == ""
|
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
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
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 =
|
113
|
+
@load_commands = {}
|
116
114
|
|
117
|
-
@raw_load_output.split("\n").each
|
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 =
|
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
|
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, :
|
12
|
+
@g = Git.open(local_path, log: $log)
|
13
13
|
rescue
|
14
|
-
$log.debug "Repository could not be opened.
|
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, :
|
17
|
+
@g = Git.open(local_path, log: $log)
|
17
18
|
FileUtils.touch "#{local_path}/idb_dummy.placeholder"
|
18
|
-
@g.add(:
|
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}'
|
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
|
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)
|
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: /)
|
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
|
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(:
|
71
|
+
@g.add(all: true)
|
69
72
|
begin
|
70
|
-
@g.commit_all("Snapshot from #{Time.now
|
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
|
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
|