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.
- 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,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
|
data/lib/lib/settings.rb
ADDED
|
@@ -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
|