Exploit and Chill

>Slidin' in the DMZ

It Was Really Fun to Write C# Again – Outlook as a VSTO

I’ve been deep in KQL and PowerShell for a while so when the chance came up to write some C# I took it. Built a custom Report Phish button for Outlook as a VSTO add-in in VS 2022. The core logic is simple: grab the selected mail item, attach it…

I’ve been deep in KQL and PowerShell for a while so when the chance came up to write some C# I took it. Built a custom Report Phish button for Outlook as a VSTO add-in in VS 2022. The core logic is simple: grab the selected mail item, attach it as a .msg preserving all original headers, send it to the [redacted] mailbox. Getting the ribbon XML wired up correctly took some iteration and configuring Visual Studio for the first time in years was a total throw back.

Originally I wanted to route submissions straight to Microsoft’s Defender User Submissions endpoint but that didn’t work out. The endpoint expects headers that only get stamped on messages flowing through Online mailboxes:

  • X-Microsoft-Antispam-Message-Info: Preserves internal anti-spam metadata and diagnostics generated by Exchange Online Protection (EOP).
  • Message-Id: Contains the unique internet message ID (<GUID@ServerFQDN>) assigned to the message.
  • X-Ms-Exchange-Organization-Network-Message-Id: Provides the unique GUID network message identifier used to trace the email across delivery paths.
  • X-Ms-Exchange-Crosstenant-Id: Identifies the specific Microsoft 365 tenant ID associated with the message.

Our on-prem component means those headers aren’t there, so submissions go to a monitored mailbox and get forwarded to the helpdesk via an Outlook rule targeting subjects containing “Phish:” with the original message attached including the full header chain. We actually get more flexibility this way, and users get an easy way to flag anything that looks suspicious.

Still need to package it as an MSI for SCCM which comes with its own subset of headaches. VSTO add-ins need specific registry keys written to the right hive (HKLM vs HKCU) to tell Outlook where to load the DLL from, and getting that wrong in an MSI means the add-in either doesn’t show up for users or conflicts with itself and gets silently disabled. Outlook has a resiliency blocklist that will suppress add-ins that have ever crashed, so a bad test run during development can ghost the add-in even after you fix the underlying issue, and the installer has to actively clear those keys. These are things I did not know when I volunteered for this project LOL

Once it rolls out we’ll finally have visibility into what’s landing in inboxes that our filters aren’t catching, and users have an easy one-click way to tell us about it. Good project, happy I got to write some real C# again, and learned more about mailflow along the way.

Leave a Reply