Shopping for LOLbins

In this Twit that I posted a few weeks ago I demoed how to use older versions of Photoshop and Illustrator to execute calculator via their internal scripting engine that is accessible via COM from e.g. Visual Basic Script:

CreateObject("Photoshop.Application").DoJavaScript("File(""c:/windows/system32/calc.exe"").execute();")

or

CreateObject("Photoshop.Application").DoJavaScriptFile(JSPath)

where JSPath points to a JavaScript file with the following content:

File("c:/windows/system32/calc.exe").execute();

The “Photoshop.Application” object name (ProgID) can be replaced with “Illustrator.Application”, but the trick doesn’t work with “InDesign.Application” and “Soundbooth.Application”. And of course, you can use ProgID variants of the object names that are version-dependent e.g. “Photoshop.Application.<version>”.

One could potentially package some parts of Creative Suite, register appropriate Registry entries to ensure COM objects can be instantiated and potentially run the whole business logic from there (signed, trusted executables), but it would be cumbersome and it would quite easily detectable – all the processes would have the svchost.exe as a parent process and they use “/Automation” as their command line arguments.

A story about Procmon (no, not that one – its misbehaving client)

We all love Process Monitor, but what we love even more are its undocumented features.

Checking program’s accepted command line arguments we can quickly discover that it can be called with an option “/client”. When started like this Process Monitor creates a socket and starts listening on port 23219:

Now that we found how to make it listen on port the only thing to do is finding how to talk to it. Ater checking the Window Messaging callback procedure I noticed it includes code to handle message WM_COMMAND with wParam equal to 40072. Code like this is typically executed via Menu, or keyboard accelerators. After inspecting GUI and accelerators table in procmon resources I couldn’t find any way to trigger it. At this stage I have already suspected this is probably a legacy code that has never been removed from the program, so it’s time to play dirty.

There are many ways to trigger execution of the afrementioned code path – we could probably add a new shortcut to accelerator table and recompile the .exe using Resource Hacker. We could write a small snippet of code to find PROCMON_WINDOW_CLASS window and then send the message to it. Or, we can be lazy and use an existing tool to do just that. I chose the latter and used SendMessage64:

You must ensure the program is launched with admin privileges otherwise Procmon won’t be able to receive the window message.

Once we send the message, Procmon will use SHGetSpecialFolderLocation API with CSIDL_NETWORK parameter to allow us to select the computer from our local network:

Once we choose the computer, we will … crash Procmon 🙂

This pretty much confirms the hypothesis it’s a legacy code.

With that, I loaded procmon into xdbg, and made a breakpoint after SHGetSpecialFolderLocation, then checked where the crash happens. It was two hardcoded values <remote system root> and <remote computer name> which (due to lack of GUI) can’t be initialized with proper values. I initialized them manually in memory and while avoiding crash, managed to connect to the host (which in this case was the same box – yes, you can run two Procmon instances simultaneously in this setup).

This is where I hit the wall as this time it’s client Procmon that crashed anyway:

I suspect that a) I should not be running two Procmon instances on the system or b) the code is broken and it’s a miracle we got that far anyway or c) I have no idea 🙂

Still, in theory you should be able to connect to the client w/o crashing it. The only remaining bit is the protocol which may be a bit time-consuming to crack.