oledump & MSI Files

Published: 2023-02-26
Last Updated: 2023-02-26 18:29:54 UTC
by Didier Stevens (Version: 1)
0 comment(s)

We regularly write about MSI files, as it is one of the many fileformats used by attackers. For example, here is a diary entry from Xavier in 2018: "Malware Delivered via Windows Installer Files".

MSI files are ole files, that can be analyzed with my oledump tool. Unfortunately, the stream names are encoded, that why back then, I wrote a little plugin to decode the stream names: plugin_msi.py. This plugin is often enough for me, when I have to analyze macilious MSI files, as it will help to quickly find embedded payloads.

But recently, I had to dig deeper in MSI files, to look at the actions encoded in tables.

This weekend, I went down the rabbit hole and reversed the binary structures in MSI files to store numbers, strings and tables (apparently, Microsoft did not release a document for the binary structures found inside MSI files). This results in a new oledump plugin: plugin_msi_info.py.

This plugin will evolve, so the format of its output will probably change. For the moment, it dumps out all the tables, and provides and overview of streams that don't contain tables or table-supporting data. It does not use the Windows API, so you can run it on any operating system that supports Python.

Let's use it on an msi file created with exetomsi, the tool Xavier talked about in his 2018 diary entry.

First the plugin list all the tables. Table property is a table that Xavier looked at in his diary entry, to show you the exetomsi meta data. He did this with a custom VBS script, and with WIX.

My plugin dumps out all the tables, also the Property table (this table is in stream !Property):

When you take a look at the custom actions table, you will see a custom action to run an executable:

This PE file is stored inside a stream:

It's in stream 2, so if you need to extract it, you can just use oledump without plugin:



Didier Stevens
Senior handler
Microsoft MVP

Keywords: msi oledump
0 comment(s)


Diary Archives