Nested .MSGs: Turtles All The Way Down

Published: 2020-10-12
Last Updated: 2020-10-12 17:38:49 UTC
by Didier Stevens (Version: 1)
1 comment(s)

A reader had problems extracting the attachment inside an .MSG file, and asked me for help.

Let me start with a simple .MSG file with one attachment (the same I used in diary entry "Analyzing MSG Files With plugin_msg_summary").

__attach_version1.0_#00000000 is a storage (a storage in OLE files is like a folder: it can contain streams (comparable to files) and storages).

__attach_version1.0_ tells us this is the storage for an attachment, and 00000000 tells us it is the first attachment.

Inside that storage, you have different streams: __properties_version1.0 and __substg1.0_*

The 37 in __substg1.0_37* tells us these streams contain data/metadata of the attachment.

For example, 3701 is the "attachment data" (content) of the attachment, and 0102 stands for "binary data":

And as you can see, for example, 3707 is metadata of the attachment: the long filename of the attachment in UNICODE (001F).

The short filename is an 8.3 filename.

To summarize: in .MSG files, the data (content) and metadata of attachments are stored inside streams that are stored inside a storage (one per attachment).

Now, the reader that asked me for help, had this:

Lots of entries with 3701000D. We know already that 3701 is the "attachment data", but what is 000D (0102 is binary data)? 000D is a directory, a storage.

And __substg1.0_3701000D is a storage this time (it is followed by /...), not a stream.

What's happening here, is that the attachment is an .MSG file. So this is an .MSG file, that contains another .MSG file as attachment.

In that case, Outlook will not store the attached .MSG file as a binary blob (37010102) but as an .MSG file with all its storages and streams (3701000D). So the attached .MSG file is not stored as a single data stream, but is decomposed in  all its elements (storages and streams) like a "normal" .MSG file is.

The direct result of this, is that you have much more streams and storages inside the "root" .MSG file.

An a practical result, is that you can directly search inside the attached .MSG file, without having to use a second instance of oledump to parse it.

For example, I can search for the subject of the .MSG files like this:

Here I'm grepping for 0037 (the code for Subject). I could also have grepped for string "Subject", but then I would have more output: I would also have streams like "Subject (normalized)", and I wanted to avoid this for this example.

We can see 2 subjects:

  1. "Microsoft Outlook Test Message" is the Subject of the attached .MSG file (stream 13)
  2. "Testing" is the Subject of the "root" .MSG file (stream 71)

So if you are dealing with attached .MSG files, their content is not stored inside a single stream (37010102), but it is decomposed in storages and streams, that are stored under one storage (3701000D) per attached .MSG file.

And this concept is recursive: you can have .MSG files inside .MSG files inside .MSG files ... "Turtles all the way down" :-)

Didier Stevens
Senior handler
Microsoft MVP

Keywords: msg ole
1 comment(s)


Two comments for doc 4ee30278ec4feabebdfad6c0a39728d737cb550766ab5ffa2aac5df584ba49cc

The VBAProject.bin is malformed:

A: word/vbaProject.bin
A1: 369 'PROJECT'
A2:41 'PROJECTwm'
A3: M63425369+973 'VBA/ThisDocument'
A5: 513 'VBA/dir'

VBA starts first Powershell, but then a C# code, like the masslogger xlsm ba5942dbbe9ab4b896fd2d10025192784c595839c4d0a0a5a5f4f45b5a6f08ae

Diary Archives