Skip to content

Commit c991c5e

Browse files
committed
Readd generic_sh encoder
1 parent 3daa1ed commit c991c5e

File tree

1 file changed

+146
-0
lines changed

1 file changed

+146
-0
lines changed

modules/encoders/cmd/generic_sh.rb

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

0 commit comments

Comments
 (0)