ileitch-hijack 0.1.8 → 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +1 -1
- data/TODO +0 -3
- data/lib/hijack/console.rb +1 -6
- data/lib/hijack/gdb.rb +39 -11
- data/lib/hijack/payload.rb +7 -13
- data/tasks/gem.rake +1 -1
- metadata +2 -2
data/README.rdoc
CHANGED
@@ -14,7 +14,7 @@ Hijack uses DRb over a unix socket file, so you need to be on the same machine a
|
|
14
14
|
|
15
15
|
== Using ruby-debug
|
16
16
|
|
17
|
-
Hijack can be used
|
17
|
+
Hijack can be used to start ruby-debug in your target process, for example:
|
18
18
|
|
19
19
|
$ hijack 61378
|
20
20
|
=> Hijacked 61378 (/opt/local/bin/thin) (ruby 1.8.7 [i686-darwin9])
|
data/TODO
CHANGED
@@ -1,5 +1,2 @@
|
|
1
|
-
* Use thread local stdout & stderr capture.
|
2
|
-
* assigning a variable doesn't work
|
3
1
|
* Improve startup experience
|
4
|
-
* Require actual remote script if possible so that if it defines any classes we can dump those too.
|
5
2
|
* Add a hijack_exec helper to execute a local .rb on the target
|
data/lib/hijack/console.rb
CHANGED
@@ -8,7 +8,6 @@ module Hijack
|
|
8
8
|
$stdout.write(str)
|
9
9
|
$stdout.flush
|
10
10
|
Payload.inject(@pid)
|
11
|
-
signal_drb_start
|
12
11
|
connect
|
13
12
|
$stdout.write("\b" * str.size)
|
14
13
|
$stdout.flush
|
@@ -32,15 +31,11 @@ module Hijack
|
|
32
31
|
end
|
33
32
|
end
|
34
33
|
|
35
|
-
def
|
36
|
-
Process.kill('USR2', @pid.to_i)
|
34
|
+
def connect
|
37
35
|
loop do
|
38
36
|
break if File.exists?(Hijack.socket_path_for(@pid))
|
39
37
|
sleep 0.01
|
40
38
|
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def connect
|
44
39
|
@remote = DRbObject.new(nil, Hijack.socket_for(@pid))
|
45
40
|
end
|
46
41
|
|
data/lib/hijack/gdb.rb
CHANGED
@@ -3,35 +3,63 @@
|
|
3
3
|
module Hijack
|
4
4
|
class GDB
|
5
5
|
def initialize(pid)
|
6
|
+
@pid = pid
|
6
7
|
@verbose = Hijack.options[:gdb_debug]
|
7
|
-
exec_path = File.join(Config::CONFIG['bindir'], Config::CONFIG['RUBY_INSTALL_NAME'] + Config::CONFIG['EXEEXT'])
|
8
|
-
|
9
|
-
wait
|
8
|
+
@exec_path = File.join(Config::CONFIG['bindir'], Config::CONFIG['RUBY_INSTALL_NAME'] + Config::CONFIG['EXEEXT'])
|
9
|
+
attach
|
10
10
|
end
|
11
11
|
|
12
|
-
def
|
13
|
-
backtrace.any? {|line| line =~ /
|
12
|
+
def ensure_attached_to_ruby_process
|
13
|
+
unless backtrace.any? {|line| line =~ /rb_/}
|
14
|
+
puts "\n=> #{@pid} doesn't appear to be a Ruby process!"
|
15
|
+
detach
|
16
|
+
exit 1
|
17
|
+
end
|
14
18
|
end
|
15
19
|
|
16
|
-
def
|
17
|
-
backtrace.any? {|line| line =~ /rb_thread_join/}
|
20
|
+
def ensure_main_thread_not_blocked_by_join
|
21
|
+
if backtrace.any? {|line| line =~ /rb_thread_join/}
|
22
|
+
puts "\n=> Unable to hijack #{@pid} because the main thread is blocked waiting for another thread to join."
|
23
|
+
puts "=> Check that you are using the most recent version of hijack, a newer version may have solved this shortcoming."
|
24
|
+
detach
|
25
|
+
exit 1
|
26
|
+
end
|
18
27
|
end
|
19
28
|
|
20
29
|
def eval(cmd)
|
21
|
-
set_trap_pending
|
22
|
-
set_breakpoint
|
23
|
-
continue
|
24
|
-
clear_breakpoint
|
25
30
|
call("(void)rb_eval_string(#{cmd.strip.gsub(/"/, '\"').inspect})")
|
26
31
|
end
|
27
32
|
|
28
33
|
def detach
|
34
|
+
return unless @gdb
|
29
35
|
exec('detach')
|
30
36
|
exec('quit')
|
37
|
+
@backtrace = nil
|
31
38
|
@gdb.close
|
39
|
+
@gdb = nil
|
32
40
|
end
|
33
41
|
|
34
42
|
protected
|
43
|
+
def attach
|
44
|
+
loop do
|
45
|
+
@gdb = IO.popen("gdb -q #{@exec_path} #{@pid} 2>&1", 'r+')
|
46
|
+
wait
|
47
|
+
if backtrace.first =~ /Previous frame inner to this frame/
|
48
|
+
detach
|
49
|
+
sleep 0.1
|
50
|
+
else
|
51
|
+
break
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
ensure_attached_to_ruby_process
|
56
|
+
ensure_main_thread_not_blocked_by_join
|
57
|
+
set_trap_pending
|
58
|
+
set_breakpoint
|
59
|
+
continue
|
60
|
+
clear_breakpoint
|
61
|
+
end
|
62
|
+
|
35
63
|
def backtrace
|
36
64
|
@backtrace ||= exec('bt').reverse
|
37
65
|
end
|
data/lib/hijack/payload.rb
CHANGED
@@ -1,20 +1,15 @@
|
|
1
1
|
module Hijack
|
2
2
|
class Payload
|
3
3
|
def self.inject(pid)
|
4
|
-
gdb =
|
5
|
-
|
6
|
-
puts
|
7
|
-
|
8
|
-
exit 1
|
9
|
-
end
|
10
|
-
if gdb.main_thread_blocked_by_join?
|
11
|
-
puts "\n=> Unable to hijack #{pid} because the main thread is blocked waiting for another thread to join."
|
12
|
-
puts "=> Check that you are using the most recent version of hijack, a newer version may have solved this shortcoming."
|
13
|
-
gdb.detach
|
14
|
-
exit 1
|
4
|
+
gdb = nil
|
5
|
+
trap('SIGINT') do
|
6
|
+
puts
|
7
|
+
@received_sigint = true
|
15
8
|
end
|
9
|
+
gdb = GDB.new(pid)
|
16
10
|
gdb.eval(payload(pid))
|
17
11
|
gdb.detach
|
12
|
+
exit if @received_sigint
|
18
13
|
end
|
19
14
|
|
20
15
|
def self.payload(pid)
|
@@ -108,8 +103,7 @@ module Hijack
|
|
108
103
|
end
|
109
104
|
end
|
110
105
|
end
|
111
|
-
|
112
|
-
Signal.trap('USR2') { Hijack.start(__hijack_context) }
|
106
|
+
Hijack.start(self)
|
113
107
|
RUBY
|
114
108
|
end
|
115
109
|
end
|
data/tasks/gem.rake
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ileitch-hijack
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Leitch
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-09-
|
12
|
+
date: 2009-09-19 21:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
|