So, lately I've been working on a project involving malware which gets spread via MS Office documents and, among other things, I need to detect the VBA code in appropriate document streams.

I've read most parts of the Office VBA File Format Structure, from which it seems to me that the correct way of detecting the beginning of the compressed code is by parsing the dir stream which contains the PROJECTMODULES Record and which contains the MODULEOFFSET Record whose element TextOffset contains the actual offset to the compressed source code inside the appropriate ModuleStream. I've also found a project officeparser which performs the VBA code detection in the following way, but according to the project site on Github, there hasn't been any work on the project in the last few years.

However, I've also found two other projects that deal with the same problem in a different way and which are more up to date. The projects are oledump and oletools and the way they detect the beginning of the compressed VBA code inside a stream is by searching for the pattern \x00Attribut and then positioning 3 bytes back from that position. I haven't found any official documentation on this method so what I would like to know is if this method is some heuristic way of searching for the compressed code or am I missing some parts of the documentation?


That part of the code you referred to is for manually parsing malformed ole only if the documented(?) method didnt work.

Not sure if office will open it correctly or provide a repair option (M$ is very liberal with its own specifications), but you may still want to know VBA is there even if it doesnt work 'as is'.

There is of course no official documentation on how the 'malformed' ole should look like :)

  • 1
    Yes, you are right, the oletools have both methods supported. I completely missed that part where the author uses the documented approach. The oledump project, however, only uses the heuristic one. I've implemented both methods in my project so guess that is the way to go. Thanks for the help.
    – ubnix
    Jun 23 '17 at 9:44
  • glad it helped :)
    – Sigtran
    Jun 23 '17 at 10:06

You should note that the code exists in up to 3 compiled states within the file, with the compressed source code being the source of last resort.

The VBA engine will prefer the code in execode format (where the file and the current VBA environment are a match), and then the p-code (where the file and VBA environment can match more loosely) and only then the compressed source code.

It is possible for the p-code to be different to the compressed source code, and where the environment doesn't differ, the source code will be ignored.

When you open a file containing VBA, the VBE usually decodes the p-code into the source that you see in the visual basic editor.

A malicious actor can embed source-code that looks benign, but the p-code is malicious.

See this the pcodedmp project that leverages OLETools, and attempts to decode the p-code.

  • Great answer! I wasn't aware of this at all. Do you maybe know of any good papers/sites where I could read more about this? Also, if you know of any hashes or have samples showing the 2 different states I haven't covered, I would be very grateful
    – ubnix
    Jun 28 '17 at 15:47
  • 1
    In addition to the README.md on the pcodedmp project, there's an article from 2005 by the same author. Evidently more detail is available from MS if you sign an NDA. With just a hex editor, it is possible to find and edit a string literal (change the characters, not the length) in the p-code section of a file, and then open the file in VBE, and you'll see the p-code version of the string literal appears in the code-pane, and not the source-code's string-literal. Jun 29 '17 at 1:19

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.