Didier Stevens

Friday 27 February 2015

Update oledump.py Version 0.0.10

Filed under: Malware,My Software,Update — Didier Stevens @ 0:00

This version handles corrupt VBA macro streams without crashing. Corrupt VBA macro streams are marked with an E indicator (error).

And an update to the plugin_http_heuristics and plugin_dridex plugins.

oledump_V0_0_10.zip (https)
MD5: 450C28232254F8FF3AF5E289F58D2DAB
SHA256: 139671E5E69200CECCE0EF730365C1BF1B7B8904B90E3B1E08E55AB040464C73

Thursday 19 February 2015

Update: oledump.py Version 0.0.9

Filed under: Malware,My Software,Update — Didier Stevens @ 22:19

The plugin_dridex plugin was updated.

And oledump.py has a new option: –quiet: only print output from plugins.

oledump_V0_0_9.zip (https)
MD5: 849C26F32397D2508381A8472FE40F90
SHA256: 74887EA3D4362C46CCBF67B89BB41D7AACE9E405E4CB5B63888FEDCE20FD6A07

Tuesday 17 February 2015

Update: oledump.py Version 0.0.8

Filed under: Malware,My Software,Update — Didier Stevens @ 0:00

This new version brings support for multiple YARA rule files.

The plugin_http_heuristics plugin was updated, and there is a new plugin: plugin_dridex.

oledump_V0_0_8.zip (https)
MD5: 29EBF73F5512B0BC250CD0A0977A2C72
SHA256: 09C451116FCDE7763173E1538C687734D92267A0D192499AFD118D8D923165B9

Sunday 15 February 2015

Update: YARA Rule JPEG_EXIF_Contains_eval

Filed under: Forensics,Malware,Update — Didier Stevens @ 11:21

Now that YARA version 3.3.0 supports word boundaries in regular expressions, I’ve updated my YARA Rule for Detecting JPEG Exif With eval().

yara-rules-V0.0.5.zip (https)
MD5: 298EB636B3A3CB6A073815A83A6D1BA6
SHA256: EA00D044A3A0FE29265817407E382034593E0DAAD9887416E7FC128DA24B8830

Tuesday 10 February 2015

Update: oledump.py Version 0.0.7

Filed under: Malware,My Software,Update — Didier Stevens @ 0:00

This new version adds support for the new office file format (.docx, .xlsx, …) stored inside a ZIP file (so a ZIP inside a ZIP) and an option to print YARA strings.

And the HTTP heuristics plugin has some extra heuristics.

oledump_V0_0_7.zip (https)
MD5: 7A953BAFFA1E5285651699996FA2DF84
SHA256: F5DC5F650F005E530A7D0CF510C33E3A4EF29AD85B1DA2618B237F53A46B86B5

Thursday 22 January 2015

Converting PEiD Signatures To YARA Rules

Filed under: Forensics,Malware,My Software — Didier Stevens @ 0:56

I converted Jim Clausing’s PEiD rules to YARA rules so that I can use them to detect executable code in suspect Microsoft Office Documents with my oledump tool.

Of course, I wrote a program to do this automatically: peid-userdb-to-yara-rules.py

This program converts PEiD signatures to YARA rules. These signatures are typically found in file userdb.txt. Since PEiD signature names don’t need to be unique, and can contain characters that are not allowed in YARA rules, the name of the YARA rule is prefixed with PEiD_ and a running counter, and non-alphanumeric characters are converted to underscores (_).
Signatures that can not be parsed are ignored.

Here is an example:
PEiD signature:

 [!EP (ExE Pack) V1.0 -> Elite Coding Group]
 signature = 60 68 ?? ?? ?? ?? B8 ?? ?? ?? ?? FF 10
 ep_only = true

Generated YARA rule:

 rule PEiD_00001__EP__ExE_Pack__V1_0____Elite_Coding_Group_
         description = "[!EP (ExE Pack) V1.0 -> Elite Coding Group]"
         ep_only = "true"
         $a = {60 68 ?? ?? ?? ?? B8 ?? ?? ?? ?? FF 10}

PEiD signatures have an ep_only property that can be true or false. This property specifies if the signature has to be found at the PE file’s entry point (true) or can be found anywhere (false).
This program will convert all signatures, regardless of the value of the ep_only property. Use option -e to convert only rules with ep_only property equal to true or false.

Option -p generates rules that use YARA’s pe module. If a signature has ep_only property equal to true, then the YARA rule’s condition becomes $a at pe.entry_point instead of just $a.


 import "pe"

 rule PEiD_00001__EP__ExE_Pack__V1_0____Elite_Coding_Group_
         description = "[!EP (ExE Pack) V1.0 -> Elite Coding Group]"
         ep_only = "true"
         $a = {60 68 ?? ?? ?? ?? B8 ?? ?? ?? ?? FF 10}
         $a at pe.entry_point

Specific signatures can be excluded with option -x. This option takes a file that contains signatures to ignore (signatures like 60 68 ?? ?? ?? ?? B8 ?? ?? ?? ?? FF 10, not names like [!EP (ExE Pack) V1.0 -> Elite Coding Group]).

Download my YARA Rules.

peid-userdb-to-yara-rules_V0_0_1.zip (https)
MD5: D5B9B6FA7EC50A107A70419D30FEC9ED

Tuesday 20 January 2015

YARA Rule: Detecting JPEG Exif With eval()

Filed under: Forensics,Malware — Didier Stevens @ 20:39

My first release of 2015 was a new YARA rule to detect JPEG images with an eval() function inside their Exif data.

Such images are not new, but I needed an example to develop a complex YARA rule:

rule JPEG_EXIF_Contains_eval
        author = "Didier Stevens (https://DidierStevens.com)"
        description = "Detect eval function inside JPG EXIF header (http://blog.sucuri.net/2013/07/malware-hidden-inside-jpg-exif-headers.html)"
        method = "Detect JPEG file and EXIF header ($a) and eval function ($b) inside EXIF data"
        $a = {FF E1 ?? ?? 45 78 69 66 00}
        $b = /\Weval\s*\(/
        uint16be(0x00) == 0xFFD8 and $a and $b in (@a + 0x12 .. @a + 0x02 + uint16be(@a + 0x02) - 0x06)

Here is an example of such an image:


The YARA rule has 3 conditions that must be satisfied:

  1. JPEG magic header FFD8, tested with: uint16be(0x00) == 0xFFD8
  2. Exif structure: FF E1 ?? ?? 45 78 69 66 00
  3. eval function inside Exif data, tested with a regular expression: \Weval\s*\(

Condition 1 is straightforward: the file must start with FFD8. I’m using test uint16be(0x00) == 0xFFD8 instead of searching for {FF D8} at 0x00. FF D8 is a short string, searching for {FF D8} can cause performance problems (you’ll get a warning from YARA when it compiles rules with such short strings).

Condition 2 checks for the presence of the Exif data header. Bytes 3 and 4 (?? ??) encode the length of the Exif Data.

Condition 3 checks for the presence of the eval function. To reduce the number of false positives that would occur when searching for string eval, we use a regular expression that matches string eval, possibly followed by whitespace characters (\s*), and an opening parenthesis: \(. And we don’t want letters or numbers before the string eval (we don’t want to match a string like deval), eval must be the start of a word. To achieve this with regular expressions, you use a word boundary: \b. So our regular expression would be \beval\s*\(. Unfortunately, YARA’s regular expression engine does not support word boundaries, so I had to come up with something else. I match any character that is not alphanumeric: \W. Be warned that there is a small difference between \W and \b. \b also matches the beginning of a string (like $), while \W has to match a character. So the regular expression I use is \Weval\s*\(.

The eval function must also be found inside the Exif data. We don’t want to trigger on the eval function if it is found somewhere else in the image. That’s where YARA’s in ( .. ) syntax comes in.

The first 18 bytes of the Exif structure are various headers which we ignore, so our eval function $b must start at @a + 0x12 or further.

The total size of the Exif structure is given by expression 0x02 + uint16be(@a + 0x02). We add this to the start of the Exif header (@a): @a + 0x02 + uint16be(@a + 0x02). And finally, we have to subtract the size of the string matched by the regular expression. Unfortunately, YARA has no function to calculate this length. So we will use the minimum length our regular expression can match: 6 characters. So our eval function $b must start no further than @a + 0x02 + uint16be(@a + 0x02) – 0x06. Putting all this together gives: $b in (@a + 0x12 .. @a + 0x02 + uint16be(@a + 0x02) – 0x06)

FYI: Victor told me that he plans to add a string length function to YARA, so our condition will then become: $b in (@a + 0x12 .. @a + 0x02 + uint16be(@a + 0x02) – &b)

You can find all my YARA rules here: YARA Rules.

Friday 16 January 2015

Update: oledump.py Version 0.0.6

Filed under: Malware,My Software,Update — Didier Stevens @ 16:11

My last software release for 2014 was oledump.py V0.0.6 with support for the “ZIP/XML” Microsoft Office fileformat and YARA.

In this post I will highlight support for the “new” Microsoft Office fileformat (.docx, .docm, .xlsx, .xlsm, …), which is mainly composed of XML files stored inside a ZIP container. Except macros which are still stored with OLE files (inside the ZIP container).

When oledump.py detects that the file is actually a ZIP file, it searches through all the files stored inside the ZIP container for OLE files, and analyses these.

Here is an example of a simple spreadsheet with macros. The xlsm file contains one OLE file: xl/vbaProject.bin. oledump gives it the identifier A. All the streams inside the OLE file are reported, and their index is prefixed with the identifier (A in this example).


If you want to select the stream with the macros, you use A6, like this: oledump.py -s A1

oledump also supports the analysis of an OLE file stored in a password protected ZIP file (typically, malware samples are stored inside ZIP files with password infected). When oledump.py analyses a ZIP file with extension .zip, it assumes that the file is NOT using the “new” Microsoft Office fileformat. Only when the file is a ZIP file but the extension is not .zip does oledump assume that the file is using the “new” Microsoft Office fileformat.

I have another example in my Internet Storm Center Guest Diary Entry.

oledump_V0_0_6.zip (https)
MD5: E32069589FEB7B53707D00D7E0256F79
SHA256: 8FCEFAEF5E6A2779FC8755ED96FB1A8DACDBE037B98EE419DBB974B5F18E578B

Wednesday 24 December 2014

Update: oledump.py Version 0.0.5

Filed under: Malware,My Software,Update — Didier Stevens @ 18:10

A quick bugfix and a new feature.

oledump will now correctly handle OLE files with an empty storage. Here is an example with a malicious sample that blog readers reported to me:


And when the OLE file contains a stream with VBA code, but this code is just a set of Attribute statements and nothing else, then the indicator will be a lowercase letter m instead of an uppercase letter M.


This way, you can quickly identify interesting VBA streams to analyze.

oledump_V0_0_5.zip (https)
MD5: A712DCF508C2A0184F751B74FE7F513D
SHA256: E9106A87386CF8512467FDD8BB8B280210F6A52FCBACEEECB405425EFE5532D9

Tuesday 23 December 2014

oledump: Extracting Embedded EXE From DOC

Filed under: Malware,My Software — Didier Stevens @ 0:00

RECHNUNG_vom_18122014.doc (6a574342b3e4e44ae624f7606bd60efa) is a malicious Word document with VBA macros that extract and launch an embedded EXE.

This is nothing new, but I want to show you how you can analyze this document with oledump.py. I also have a video on my video blog.

First we have a look at the streams (I put the Word document inside a password (= infected) protected ZIP file to avoid AV interference, oledump can handle such files):


Stream 7 contains VBA macros, let’s have a look:


Subroutine v45 is automatically executed when the document is opened. It creates a temporary file, searches for string “1234” inside the text of the Word document (ActiveDocument.Range.Text), writes the encoded bytes following it to disk, and then executes it.

If you take a look at the content of the Word document (stream 14), you’ll see this:


Following string “1234” you’ll see &H4d&H5a&h90…

&Hxx is the hexadecimal notation for a byte in VBA. It can be converted with function cbyte. We can also convert this sequence of hexadecimally encoded bytes using a decoder specially written for this. The decoder (written in Python) searchers for strings &Hxx with a regular expression, converts the xx hex values to characters and concatenates them into a string, which is returned to oledump.

#!/usr/bin/env python

__description__ = '&H decoder for oledump.py'
__author__ = 'Didier Stevens'
__version__ = '0.0.1'
__date__ = '2014/12/19'


Source code put in public domain by Didier Stevens, no Copyright
Use at your own risk

  2014/12/19: start


import re

class cAmpersandHexDecoder(cDecoderParent):
    name = '&H decoder'

    def __init__(self, stream, options):
        self.stream = stream
        self.options = options
        self.done = False

    def Available(self):
        return not self.done

    def Decode(self):
        decoded = ''.join([chr(int(s[2:], 16)) for s in re.compile('&H[0-9a-f]{2}', re.IGNORECASE).findall(self.stream)])
        self.name = '&H decoder'
        self.done = True
        return decoded

    def Name(self):
        return self.name


This decoder allows us to analyze the embedded file with the following command: oledump.py -s 14 -D decoder_ah.py RECHNUNG_vom_18122014.doc.zip


From the MZ and PE headers, you can identify it as a PE file. We can check this with pecheck like this:

oledump.py -s 14 -D decoder_ah.py -d RECHNUNG_vom_18122014.doc.zip | pecheck.py


oledump_V0_0_4.zip (https)
MD5: 8AD542ED672E45C45222E0A934033852
SHA256: F7B8E094F5A5B31280E0CDF11E394803A6DD932A74EDD3F2FF5EC6DF99CBA6EF

« Previous PageNext Page »

The Rubric Theme. Blog at WordPress.com.


Get every new post delivered to your Inbox.

Join 342 other followers