MSWord script injection using DDE

for the past two weeks the infosec community didn’t stop talking about using DDE for macro-less command execution using office products, bypassing alerts and avoiding detection, and so I did, I’ve spent some time reading about DDE as I always refer to as “interprocess communications way” without trying it myself.


Dynamic Data Exchange (DDE)

it’s a client/server communication method implemented in Microsoft Windows operation system since early Windows 2.0 in 1987, based over Windows Messaging and using its functions to initiate a connection between two sides, the server listens to certain Topics and messages, acts upon them, responds to clients and terminate the connection at the end.

it was used to send parameters to applications like office products and browsers, send commands to shell -explorer- to create start menu groups and links and to integrate between different applications and services.

DDE consists of different messages to communicate like Poke, Request, Advise & Execute. each with its own purpose and usage, the DDE flow looks like so:

DDE conversation for IBM® Personal Communications. - ibm.com

MSWord as DDE client

what happened with published attacks is DDE used in Word, excel and others as a client, by telling it -using DDE formula- like the following:

cmd!”/c notepad”!A0
{DDEAUTO c:\\windows\\system32\\cmd.exe "/k calc.exe" }

so the formula tells the process to connect to a non-existing DDE server called CMD with topic “/c notepad”, the operation fails and process proceeds to start it by starting cmd.exe and pass the topic as a parameter, CMD executes the topic hence the command execution.

Word is trying to Initiate a DDE session with aApp=cmd & aTopic=”/k calc” and gets result=0
Word failed to initiate, asks to start the target DDE server

After clicking “Yes”, MSWord tries again to Initiate DDE session with newly spawned cmd, fails and shows this warning message to indicate that -after RCE happened anyways-.

Word can’t Initiate DDE session with started CMD

if it happens that the target is a valid DDE server, communications will continue with the flow by sending DDE Advises and Requests to get the remote data as intended.


MSWord as a DDE Server

even though DDE is being replaced with other methods for RPCs, an ancient DDE server still exists within office products, providing integration with other systems and forms, each product has its own server with its Topics, and is waiting for messages the moment the product is started.

By trying to send some DDE messages, I noticed that WinWord -Word DDE server- responds to WM_DDE_EXECUTE messages in a strange way.

if you send WinWord server a message on System topic, it will post it directly in the active sheet, but -let the fun begins- if you enclosed the message with [] brackets, Word puts the message in a macro function TmpDDE() within a module called WordTmpDDEMod, and executes it.

that means if we could trigger a DDE Execute with MSWord, we can inject our own code and execute it under Word.exe process.

to do so, I used David Naylor’s DDE client in python to send the execute code, then figured out there are other command line tools like CMCDDE and others that you can use for the same purpose.

now, if you tried to send a regular VB code, Word does the following:

  • it suffixes function like CreateObject with __.
  • it prefixes known functions like MsgBox with WordBasic. which renders most functions useless.
  • it replaces some dots with commas, defines undefined variables too.

so a valid command like:

[CreateObject(“Wscript.Shell”).Run “notepad”]

will be transformed into this:

CreateObject___(“Wscript.Shell”), Run “notepad”

which gives a Syntax error as it doesn’t recognize that function or as “,” isn’t well placed.

after some tries to find a running code, with the old “On error Resume Next” I figured out that WordBasic.Shell is a valid function, so by sending:

[shell “notepad”]

Word proceed to execute it as:

WinWord.Shell(“notepad”)

which pops notepad with Word process as a parent -with no log trace as no one records DDE messages-.

DDE Execute in action

in the current state, the method only works as a 2nd stage payload, as it requires Word to be running and a DDE client that we can control its Server, Topic and Data we send to Word.

I’ve also tried it with scenarios like :

  • run DDE client as a guest account in the same admin session: Successful.
  • run DDE client as another account remotely using psexc: Successful.

problem with above methods is Windows Messaging doesn’t work across sessions/desktops so you need an Admin|SYSTEM account to execute on other sessions -which is the least you will consider-.

I scanned my machine -Win10x64 with Office16- for any exe/dll that uses DdeClientTransaction and its related APIs and only found these:

  • shell32.dll: for running applications with /ddeexec, I guess.
  • twain_32.dll: I have no idea what a DDE client is used for in here.
  • vbe7.dll & msvbvm60.dll: for DDE scripting in VBA.
  • ieframe.dll: I may investigate more here and check its execution path.

it was fun reading through DDE documents and articles, specially Word95 wrdbasic help file.. I hope this article will lead others somewhere. special thanks to Etienne Stalmans and Saif El-Sherei for their work.

have a nice day.