Skip to main content

Alternative Execution: A Macro Saga (part 2)

In the previous blog in this series, we worked through a scenario making use of the ActiveX control InkPicture to trigger macro execution. Macro execution utilizing the InkPicture object can be achieved without resorting to the more common Document_Open() or Workbook_Open() event handlers available within Microsoft Word or Excel and can be used to bypass prevention controls that alert on typical rules for malicious documents (maldocs).

But what if I were to tell you that InkPicture isn’t the only embeddable ActiveX control with event handlers that can be used in this way? I’m sure you’re not very shocked.

In the remaining blogs in this series we’ll work through some research I’ve been performing over the past few weeks to identify additional ActiveX controls that can be abused in Microsoft Office documents, and how to use them.

To be completely transparent, I haven’t reached 100% thoroughness in analyzing all available ActiveX controls that Office allows for insertion. There’s over 100 on my system alone, and I still have a day job to do at White Oak Security. Regardless, and as I mentioned in the previous blog, I hope that other offensive teams can make use of these techniques during assessments, and that leadership at organizations take great care to consider disabling Office Macros enterprise-wide via GPO. We’ve had around 20 years of maldocs, and they’re a delivery mechanism that’s easy to remediate.

Windows Media Player

If you scan through the list of available ActiveX controls, eventually you’ll come across the Windows Media Player control, almost at the bottom of the list. As it turns out, this control has at least three event handlers that can be utilized via VBA to obtain execution of malicious macros. Each ActiveX control has both a CLSID (GUID) and ProgID (friendly program name) associated with it. In the case of the Windows Media Player control we have the following:

  • CLSID: 6BF52A52-394A-11d3-B153-00C04F79FAA6
  • ProgID: WMPlayer.OCX (WMPlayer.OCX.7)

With a little bit of Googling, we can find that Microsoft did a great job documenting this ActiveX object as well:


Let’s get started and embed a WMPlayer object in a sample Word document. We’ll walk through the process used in the previous blog. Let’s open Word and select the Developer tab. In the Developer tab you’ll see a toolbox icon in the Controls submenu:


After you click the Toolbox icon, you’ll see a submenu containing Legacy Forms and ActiveX Controls. Then within the ActiveX Controls section you’ll find an icon of a screwdriver and wrench.


After you click that screwdriver/wrench icon the list of embeddable ActiveX controls will open.


Let’s skip all the way to the bottom to find Windows Media Player.


And then we’ll click OK to insert the Windows Media Player control.


As we noted during the previous blog, “Design Mode” is highlighted, allowing to resize the inserted control. During testing it appears that there’s a minimum size for this control, and even if you shrink it smaller the control will resize when it’s rendered to its minimum.

But now that we have this object embedded, what can we do with it? You can actually configure the control with a URL to stream a video when the control is rendered. Let’s take a quick look at the control’s properties, because we’ll need to modify the URL property for some of the triggering methods. To open its Properties, you can either Right-Click the control and select Properties from the context menu, or you can select the control and click “Properties” right below “Design Mode”.


In this properties menu all of the values can be modified via mouse/keyboard. If you rename the (Name) property from WindowsMediaPlayer1 to something else, all VBA event handlers will need to make use of this new name.

So, let’s do two things: change the (Name) property, and set the URL property to a website that does NOT contain a media file. Regarding the URL parameter, we’re setting a bad value now, because it’ll be useful later.


So, we’ve changed the value for the (Name) property to TestObject and the value for URL to

If you remember the previous blog, if you double-click a usable control Word will fill in an event handler routine in VBA for you. Let’s do that now and see what Word give us.


Word inserted the event handler TestObject_OpenStateChange() for us. This corresponds to the Player.OpenStateChange() event handler listed in Microsoft’s documentation. And guess what: this event handler is usable out of the box without modification. I’ll note that this event handler can definitely fire multiple times, so we’ll need to setup a global variable to control our payload. We’ll do that now before we save the document.


Now let’s save our document as a macro-enabled Word document named WMPlayer.docm, close the doc, and reopen it.

Similar to the previous blog post, we received a “Security Warning” regarding the ActiveX object. Your victims will click “Enable Content”, though, so let’s do that and see what happens.


Excellent! Worked on the first try!

Taking This Two Steps Further

When I was originally testing the OpenStateChange() event handler, it didn’t fire correctly on the first try. In fact, I didn’t realize that I had to set the URL property before the event handler would fire, and I ended up taking the long route by using another tool (one that we’ll use in the next post) to identify all of the event handlers, rather than going to Microsoft’s reference documentation first. But it all paid off, because I found two additional event handlers that can be used to trigger execution that way:

  • Player.MediaError() – Fires when the media source (URL) doesn’t contain valid media
    • Triggered Once
  • Player.PlayStateChange() – Fires when Media Player’s playing state has changed
    • Triggered Multiple Times

Let’s go about implementing these event handlers too. We’ll do it all in one shot so we can save a little time!

Reviewing the Player.MediaError() handler’s documentation, we find that the sample code is written in client-side JavaScript (e.g. JScript):




Microsoft’s documentation isn’t very specific about the variable type of pMediaObject, but it turns out we can just use the generic Object type in the handler code without any issues.

And if we look at the Player.PlayStateChange() handler’s documentation, we see the following code sample (also in JScript):




Microsoft’s documentation was kind enough to tell us that NewState should be a Long type, just like OpenStateChange().

Then in our VBA Editor we’ll want the following test code:


Now we’ll save our document and reopen it to see the handlers fire! First Player.OpenStateChange() fires.


Then Player.MediaError() fires.


Then Player.PlayStateChanged() fires.



Additional Remarks

In practice, you don’t need to make use of all three event handlers to trigger your payloads. You certainly could, but it’s really unnecessary. Additionally, none of the parameters in the subroutines’ parameter lists need to have the names that I implemented. For reference purposes and clarity, it makes a lot of sense to develop the event handlers in accordance with the documented variable names whenever possible, but you could just as easily set the parameter names to something completely random if you’re going up against prevention that uses poorly defined regular expressions.

Also, if you look through the Windows Media Player documentation, there are several additional event handlers that can be used beyond the three discussed previously. Most of them require that the URL parameter be configured to point at a valid video file. I’ll leave implementing those handlers up to the crafty offensive researcher reading this post!


In this blog we covered abuse of the Windows Media Player ActiveX control to trigger macro execution at the point in which a maldoc is opened. We identified and implemented reference code for three event handlers that can be used without specifying a valid media file for Windows Media Player to load. These methods of executing malicious VBA code do not depend on the Document_Open() or Workbook_Open() event handlers that are more commonly utilized by malicious actors to obtain code execution.

So far so good! We have a few more blog posts in this series. So, grab your popcorn, this only gets better!