There have been some time since there were any updates to loffice and frankly, there have been updates but they haven't been pushed. Mainly cause I had an initial plan which simply grew as new techniques were deployed by bad actors.
The updates are in short:
- Better logging and reporting
- Insight into antis
- Evade "Recent documents"
- Detect code injection
- New exit mode
Better logging and reportingFor those who ran the old version, logging was simply done to stdout which required the user to scroll through enough rows to get frustrated. This have changed, a directory is created in which each run will be saved instead of stdout.
Feedback will still be given on what is going on while the macro is executed as shown below.
After a session is terminated, either manually or via the selected exit mode, loffice will output a summary on what has been going on.
A complete picture is available in the log located in the "logs" directory.
This is what was shown in the console in the old version. Also, the images above show an example on how it will look if loffice detect that code injection is going on. More on this further down.
Insight into antisThis have been one of the more interesting features to add. In the old version loffice could battle antis by patching WMI queries for example, in this version it will give an insight or hint if you will, rather than patching and trying to bypass anti-analysis attempts.
The number of antis deployed and can be deployed are simply huge, but a common denominator between a large number of them are to detect strings within strings. This can for example be checking if the document name contains the string "malwr_", "malware" or ".bin". One of the functions used to check this is via the VBA function InStr. As the function where strings could easily be extracted on comparison wasn't exported I needed to locate the function statically regardless of the VBA DLL (vbe7.dll). This was done with pefile and capstone.
The result of this is that it's now possible to see if the macro is trying to profile the machine it's running on. The below image show the result of a malicious document being able to detect VMware Tools.
So if no malicious activity is noted be sure to check the last lines of the log for hints on why there wasn't any malicious actions.
Evade "Recent documents"One of the earlier tricks of detecting sandboxes was to check the number of recently opened documents. If it was under a certain value the macro would fail.
Loffice will check this on start by counting the number of entries from the registry. Should it find that there are less than three items it will suggest adding a random number of documents with random names so that it would seem that there have been more activity that it actually have. This will be done for the whole Office suite (Word, PowerPoint and Excel).
Even though Word never been launced, loffice will add recent files and make it look it has been "used".
New exit mode & detecting code injectionThis was one of the techniques I was simply waiting for in the wild; macros that use shellcode to perform RunPE-like operations.
When injecting a PE to a remote process there are a couple of things that needs to be done such as writing memory to the remote process, setup thread context and resume the remote suspended thread. These steps are used to increase a counter inject which will be used to determine if loffice should exit when the ZwResumeThread is called.
In the above image the summary loffice have noted that a suspended process has been created and that the "inject" threshold is above 2 which result in termination upon calling ZwResumeThread. A reminder will be displayed that the suspended process is still "running" which means that the injected data can be retrieved. Depending on the data written, the log file might reveal where to look:
CommentsHopefully loffice have come to be more useful and user friendly than before. I have had sessions where loffice failed to set breakpoints (winappdbg issue) so be sure to run this in a VM. The issue can be spotted if you get a "RuntimeWarning", all the breakpoints for that particular module will not be set. This have been very random.
This version will be the end of the current layout, I will make it more configurable in the future, mainly to make it easy for anyone to contribute and make it modular. As always, if you have comments, suggestions or anything else, let me know.
The code is available on Github. As the project have outgrown itself, the quality of the code have gone the same way, re-work will be done, promise :)