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,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
|