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,81 @@
1
+ require 'git'
2
+ require 'pty'
3
+ require 'expect'
4
+
5
+ module Idb
6
+ class RsyncGitManager
7
+ def initialize remote_path, local_path
8
+ @remote_path = remote_path
9
+ @local_path = local_path
10
+ FileUtils.mkdir_p @local_path unless Dir.exist? @local_path
11
+
12
+ begin
13
+ @g = Git.open(local_path, :log => $log)
14
+ rescue
15
+ $log.debug "Repository could not be opened. This is likely the first clone. Creating empty repo."
16
+ Git.init(local_path)
17
+ @g = Git.open(local_path, :log => $log)
18
+ FileUtils.touch "#{local_path}/idb_dummy.placeholder"
19
+ @g.add(:all=>true)
20
+ $log.debug "Committing placeholder to initialize the repo."
21
+ begin
22
+ @g.commit_all("Initial commit. Initializing the repo.")
23
+ rescue
24
+ $log.error "Initial commit failed."
25
+ end
26
+
27
+ end
28
+ end
29
+
30
+ def sync_new_revision
31
+ $log.info "Hard resetting work dir #{@local_path}..."
32
+ begin
33
+ @g.reset_hard
34
+ rescue
35
+ $log.error "Reset of repo failed. If this is the first time you run rsync+git for this app this may be okay."
36
+ end
37
+
38
+
39
+
40
+ if $settings['device_connection_mode'] == "ssh"
41
+ cmd = "rsync -avz -e 'ssh -oStrictHostKeyChecking=no -p #{$settings.ssh_port}' #{$settings.ssh_username}@#{$settings.ssh_host}:#{Shellwords.escape(@remote_path)}/ #{Shellwords.escape(@local_path)}/"
42
+ else
43
+ cmd = "rsync -avz -e 'ssh -oStrictHostKeyChecking=no -p #{$device.tool_port}' root@localhost:#{Shellwords.escape(@remote_path)}/ #{Shellwords.escape(@local_path)}/"
44
+ end
45
+
46
+
47
+ $log.info "Executing rsync command #{cmd}"
48
+ begin
49
+ PTY.spawn(cmd) { |rsync_out, rsync_in, pid |
50
+ STDOUT.flush
51
+ rsync_out.sync = true
52
+ rsync_in.sync = true
53
+ $expect_verbose = true
54
+
55
+ rsync_out.expect(/assword: /) { |x|
56
+ begin
57
+ $log.info "Supplying password for rsync if required..."
58
+ rsync_in.printf("#{$settings.ssh_password}\n")
59
+ rescue
60
+ $log.info "No password required for rsync...."
61
+ end
62
+ }
63
+
64
+ rsync_out.each { |x|
65
+ $log.info x
66
+ }
67
+ PTY.check
68
+ }
69
+ rescue
70
+ $log.info "Rsync Done. committing to git."
71
+ @g.add(:all=>true)
72
+ begin
73
+ @g.commit_all("Snapshot from #{Time.now.to_s}")
74
+ rescue
75
+ end
76
+ end
77
+
78
+ end
79
+
80
+ end
81
+ end
@@ -0,0 +1,59 @@
1
+ require_relative 'ssh_operations'
2
+
3
+ module Idb
4
+ class ScreenShotUtil
5
+
6
+ def initialize app_path, ops, sim = true
7
+ @app_path = app_path
8
+ @snapshot_path = "#{@app_path}/Library/Caches/Snapshots"
9
+ @ops = ops
10
+ @sim = sim
11
+ end
12
+
13
+ def mark
14
+ if @sim
15
+ #create snapshot dir!
16
+ if not Dir.exist? @snapshot_path
17
+ Dir.mkdir_p @snapshot_path
18
+ end
19
+ end
20
+ mark_time
21
+ end
22
+
23
+
24
+ def check
25
+ # there should really be only one directory in here which is named
26
+ # based on the bundle id of the app. lets go through all, just in case.
27
+
28
+ snap_dirs = @ops.list_dir("#{@snapshot_path}/").reject {|e| e =~ /^\.\.?$/}
29
+
30
+
31
+ snap_dirs.each { |dir|
32
+ full_snap_dir = "#{@snapshot_path}/#{dir}"
33
+ if @ops.directory? full_snap_dir
34
+
35
+ # walk through all files in snaphot dir
36
+ content = @ops.dir_glob(full_snap_dir,"**/*")
37
+
38
+ # see if any is younger than mark.
39
+ content.each { |f|
40
+ # full_path = "#{full_snap_dir}/#{f}"
41
+ full_path = f
42
+ if @ops.file? full_path and @ops.mtime(full_path) > @time
43
+ return full_path
44
+ end
45
+ }
46
+ end
47
+ }
48
+ return nil
49
+
50
+ end
51
+
52
+ private
53
+
54
+ def mark_time
55
+ @time = Time.now
56
+ end
57
+
58
+ end
59
+ end
@@ -0,0 +1,67 @@
1
+ # encoding: utf-8
2
+ require 'yaml'
3
+
4
+ YAML::ENGINE.yamler='syck'
5
+
6
+ module Idb
7
+ class Settings
8
+
9
+ def initialize file_name
10
+ @file_name = file_name
11
+ if file_name.nil?
12
+ @data = Hash.new
13
+ else
14
+ if not self.load
15
+ @data = Hash.new
16
+ end
17
+ end
18
+ end
19
+
20
+
21
+ def load
22
+ if File.exist? @file_name
23
+ $log.info "Loading configuration from #{@file_name}"
24
+ @data = YAML.load(File.open(@file_name).read)
25
+ @data["idb_utility_port"] = "4711" if @data["idb_utility_port"].nil?
26
+ true
27
+ else
28
+ $log.warn "No configuration found, generating default."
29
+ @data = Hash.new
30
+ @data["ssh_host"] = "localhost"
31
+ @data["ssh_port"] = 22
32
+ @data["ssh_username"] = "root"
33
+ @data["ssh_password"] = "alpine"
34
+ @data["manual_ssh_port"] = "2222"
35
+ @data["idb_utility_port"] = "4711"
36
+ @data["device_connection_mode"] = "usb"
37
+ $log.info "Storing new configuration at #{@file_name}"
38
+ store
39
+ load
40
+ end
41
+ end
42
+
43
+ def store
44
+ $log.info "Storing new configuration at #{@file_name}."
45
+ conf_file = File.open(@file_name,"w")
46
+ conf_file.puts(@data.to_yaml)
47
+ conf_file.close
48
+ end
49
+
50
+ private
51
+ def method_missing(method, *args, &block)
52
+ m = method.to_s
53
+ if @data.has_key?(m)
54
+ return @data[m]
55
+ elsif @data.has_key?(m.to_sym)
56
+ return @data[m.to_sym]
57
+ end
58
+ begin
59
+ @data.send(method, *args, &block)
60
+ rescue
61
+ nil
62
+ end
63
+ end
64
+
65
+
66
+ end
67
+ end
@@ -0,0 +1,60 @@
1
+ require_relative 'abstract_device'
2
+ require_relative 'simulator_ca_interface'
3
+ require_relative 'local_operations'
4
+
5
+ module Idb
6
+ class Simulator < AbstractDevice
7
+ attr_accessor :sim_dir
8
+
9
+ def initialize sim_dir
10
+ puts "Initializing simulator with #{sim_dir}"
11
+ @sim_dir = sim_dir
12
+ @apps_dir = @sim_dir + "/Applications"
13
+ @ops = LocalOperations.new
14
+
15
+ end
16
+
17
+ def open_installed?
18
+ true
19
+ end
20
+
21
+ def app_launch app
22
+ cmd = '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/Applications/iPhone\ Simulator.app/Contents/MacOS/iPhone\ Simulator -SimulateApplication '
23
+ $log.info "Launching app..."
24
+ @ops.launch_app cmd, app.binary_path
25
+ end
26
+
27
+
28
+ def self.get_simulators
29
+ basedir = ENV['HOME'] + '/Library/Application Support/iPhone Simulator'
30
+
31
+ return Array.new unless Dir.exists? basedir
32
+
33
+ dirs = Dir.glob("#{basedir}/**")
34
+ if dirs.length == 0
35
+ raise "No simulators found in #{basedir}."
36
+ end
37
+
38
+ return dirs
39
+ end
40
+
41
+ def ca_interface
42
+ SimulatorCAInterface.new @sim_dir
43
+ end
44
+
45
+ def disconnect
46
+ # nothing to do
47
+ end
48
+
49
+ def device?
50
+ false
51
+ end
52
+
53
+ def simulator?
54
+ true
55
+ end
56
+
57
+
58
+
59
+ end
60
+ end
@@ -0,0 +1,16 @@
1
+ require 'openssl'
2
+ require 'digest/sha1'
3
+ require 'sqlite3'
4
+ require_relative 'ca_interface'
5
+
6
+ module Idb
7
+ class SimulatorCAInterface < CAInterface
8
+
9
+ def initialize sim_path
10
+ @sim_path = sim_path
11
+ @store_path = "/Library/Keychains/TrustStore.sqlite3"
12
+ @db_path = @sim_path + @store_path
13
+ end
14
+
15
+ end
16
+ end
@@ -0,0 +1,80 @@
1
+ require 'awesome_print'
2
+ require 'xmlrpc/client'
3
+
4
+ module Idb
5
+ class SnoopItWrapper
6
+
7
+ def initialize
8
+ connection = Hash.new
9
+ connection[:host] = "127.0.0.1"
10
+ connection[:port] = "12345"
11
+ connection[:path] = "/xmlrpc"
12
+ # connection[:user] = "snoop-it"
13
+ # connection[:password] = "snoop-it"
14
+
15
+
16
+ @rpc = XMLRPC::Client.new3(connection)
17
+ end
18
+
19
+ def fsevents_after start = Time.now
20
+ start_timestamp = start.to_time.to_i
21
+ # result = @rpc.call("filesystemGetAccessListUpdate", {'lastId' => 0})
22
+ @rpc.call("filesystemGetAccessList", {'from' => start_timestamp})
23
+ end
24
+
25
+ def fsevents_delete
26
+ exec_rpc do
27
+ @rpc.call("filesystemDeleteAll")
28
+ end
29
+
30
+ end
31
+
32
+ def fsevents_after_id id
33
+ exec_rpc do
34
+ @rpc.call("filesystemGetAccessListUpdate", {'lastId' => id})
35
+ end
36
+ end
37
+
38
+ def keychain_after_id id
39
+ exec_rpc do
40
+ @rpc.call("keychainGetListUpdate", {'lastId' => id})
41
+ end
42
+ end
43
+
44
+ def keychain_details id
45
+ exec_rpc do
46
+ @rpc.call("keychainGetId", {'id' => id})
47
+ end
48
+ end
49
+
50
+ def sensitiveapi_after_id id
51
+ exec_rpc do
52
+ @rpc.call("sensitiveAPIGetListUpdate", {'lastId' => id})
53
+ end
54
+ end
55
+
56
+ def sensitiveapi_delete
57
+ exec_rpc do
58
+ @rpc.call("sensitiveAPIDeleteAll")
59
+ end
60
+ end
61
+
62
+ def exec_rpc
63
+ begin
64
+ yield
65
+ rescue
66
+ raise "Connection lost. Make sure the app under assessment is running on the device."
67
+ end
68
+
69
+
70
+
71
+ end
72
+
73
+ def is_alive?
74
+ result = @rpc.call("ping")
75
+ ap result
76
+
77
+ end
78
+
79
+ end
80
+ end
@@ -0,0 +1,136 @@
1
+ require 'net/ssh'
2
+ require 'net/sftp'
3
+ require 'launchy'
4
+
5
+ module Idb
6
+ class SSHOperations
7
+ attr_accessor :ssh
8
+
9
+ def initialize username, password, hostname, port
10
+ @hostname = hostname
11
+ @username = username
12
+ @password = password
13
+ @port = port
14
+
15
+ $log.info "Establishing SSH Session for #{username}@#{hostname}:#{port}"
16
+
17
+ begin
18
+ @ssh = Net::SSH.start hostname, username, :password => password, :port => port
19
+
20
+ # initiali:wze sftp connection and wait until it is open
21
+ $log.info 'Establishing SFTP Session...'
22
+ @sftp = Net::SFTP::Session.new @ssh
23
+ @sftp.loop { @sftp.opening? }
24
+ rescue Exception => ex
25
+ $log.error ex.message
26
+ error = Qt::MessageBox.new
27
+ error.setInformativeText("SSH connection could not be established: #{ex.message}")
28
+ error.setIcon(Qt::MessageBox::Critical)
29
+ error.exec
30
+ end
31
+ end
32
+
33
+ def disconnect
34
+ puts "[*] Closing SSH Session"
35
+ @ssh.close
36
+ end
37
+
38
+
39
+ def execute(command)
40
+ @ssh.exec! command
41
+ end
42
+
43
+ def chmod file, permissions
44
+ @sftp.setstat(file, :permissions => permissions)
45
+ end
46
+
47
+ def download_recursive(remote_path, local_path)
48
+ begin
49
+ @sftp.download! remote_path, local_path, :recursive => true
50
+ rescue
51
+ $log.error "Failed to download #{remote_path}."
52
+ return false
53
+ end
54
+ end
55
+
56
+ def download(remote_path, local_path = nil)
57
+ begin
58
+ if local_path.nil?
59
+ @sftp.download! remote_path
60
+ else
61
+ @sftp.download! remote_path, local_path
62
+ end
63
+ rescue
64
+ puts "Error downloading file."
65
+ return false
66
+ end
67
+ return true
68
+
69
+ end
70
+
71
+ def upload(local_path, remote_path)
72
+ @sftp.upload! local_path, remote_path
73
+ end
74
+
75
+ def list_dir dir
76
+ @sftp.dir.entries(dir).map {|x| x.name}
77
+ end
78
+
79
+ def list_dir_full dir
80
+ @sftp.dir.entries(dir)
81
+ end
82
+
83
+
84
+ def file_exists? path
85
+ begin
86
+ @sftp.stat!(path)
87
+ return true
88
+ rescue
89
+ return false
90
+ end
91
+
92
+ end
93
+
94
+ def launch path
95
+ @ssh.exec path
96
+ end
97
+
98
+ def dir_glob path, pattern
99
+ @sftp.dir.glob(path,pattern).map {|x| "#{path}/#{x.name}"}
100
+ end
101
+
102
+ def mkdir path
103
+ @sftp.mkdir path
104
+ end
105
+
106
+ def directory? path
107
+ begin
108
+ @sftp.stat!(path).directory?
109
+ rescue
110
+ nil
111
+ end
112
+ end
113
+
114
+ def file? path
115
+ begin
116
+ @sftp.stat!(path).file?
117
+ rescue
118
+ false
119
+ end
120
+ end
121
+
122
+ def mtime path
123
+ Time.new @sftp.stat!(path).mtime
124
+ end
125
+
126
+ def open path
127
+ Launchy.open path
128
+ end
129
+
130
+ def launch_app command, app
131
+ puts "#{command} \"#{app}\""
132
+ self.execute("#{command} \"#{app}\"")
133
+ end
134
+
135
+ end
136
+ end