Cerbero Suite 4.5 is out!

Because of some bureaucratic slowdowns this release took longer than usual. On the upside, it comes packed with news!

We have added support for the XLSB format (via pyxlsb2), so that now Cerbero Suite decompiles both XLS and XLSB formulas. Not only that, Cerbero Suite now previews spreadsheets even better than Microsoft Excel does!

But even more exciting, we have introduced the Silicon Excel Emulator to emulate Microsoft Excel formulas.

In order to emulate a formula, it’s enough to select it in the spreadsheet and to press “Ctrl+E” (or using the context menu).

While the emulator doesn’t support all the functions available in Excel, we made it extremely simple to extend it from Python. When a function is not supported, the emulator simply prints out its arguments:

warning: unimplemented function 'CALL'
    arg_0: "Shell32"
    arg_1: "ShellExecuteA"
    arg_2: "JJCCCCJ"
    arg_3: 0
    arg_4: "Open"
    arg_5: "C:\ProgramData\nCjBmqQ.exe"
    arg_6: 
    arg_7: 0
    arg_8: 0

In most cases, this is enough to understand what’s happening. When it isn’t and we need something more, we can easily hook into the emulator engine via Python and extend it:

from Pro.SiliconSpreadsheet import *
from Pro.UI import proContext

class EmulatorHelper(SiliconExcelEmulatorHelper):

    def __init__(self):
        super(EmulatorHelper, self).__init__()
        
    def evaluateFunction(self, emu, ctx, opts, depth, e):
        function_name = e.toString()
        print(function_name)
        return SiliconExcelEmulatorValue()

v = proContext().findView("Analysis [file name]")
if v.isValid():
    view = SiliconSpreadsheetWorkspaceView(v)
    helper = EmulatorHelper()
    emu = view.getExcelEmulator()
    emu.setHelper(helper)
else:
    print("error: couldn't find view")

This little snippet of Python code does nothing else than to hook the Silicon Excel Emulator being used in a spreadsheet preview and to log every function being called. We can, however, just as easily modify the behavior of a function or implement its functionality by returning a valid value. We’ll show you how to do this in future articles and videos.

The new version of Cerbero Suite comes also with other improvements. For instance, it is now possible to edit the prototype of functions in the decompiler by pressing “Y”.

And you can now edit the prototype of a function in the same way also in the native UI for Ghidra.

This is the complete list of news for version 4.5:

– added spreadsheet preview for XLS and XLSB files
– added XLSB format support
+ added Microsoft Excel macro emulator
+ added editing of function prototypes in the decompiler
+ added editing of function prototypes in the native UI for Ghidra
+ improved Ghidra native UI
– improved XLS macro decompiler
– improved XLS format support
– exposed XLS classes to Python
– exposed new cell table view to Python
– minor improvements

We’ll soon publish material to demonstrate how to reverse engineer malicious Excel documents.

Happy hacking!

Cerbero Suite 4.4 is out!

This time it took a bit longer for the release as we’re undergoing some organizational changes, but we’ll make up for it in the upcoming months!

This is the list of news for version 4.4:

added Excel macro decompiler
added word highlighting to text editor
added password brute-forcers
+ improved C++ support in the decompiler
+ improved disassembly view
– improved detection of Excel malware

Excel Macro Decompiler

The major news of this release is the addition of a decompiler for Excel macros. We’ll continue to build and improve upon this feature in the upcoming releases!

C++ Decompiler Improvements

We have improved C++ support in the decompiler. A small improvement makes the code much easier to read!

Text Editor: Word Highlighting

Cerbero Suite now provides the word highlighting feature available in the disassembly/decompiler also in the text editor. This makes the analysis of VBA macros, JavaScript and other managed languages much easier.

Password Brute-Forcers

“infected” is such an ubiquitous password for sharing Zip archives containing malware that starting with this release you don’t even have to enter it when opening a file.

We’ve also added optional common passwords dictionary-based brute-forcers as a bonus. You can activate them from the extensions page.

More is coming soon…

Happy hacking!

Malicious Windows Link with Embedded Microsoft Cabinet

You can find the original analysis for this malware at malwarebytes. As a bonus, in the video we show how to improve the static analysis of the final payload by resolving API calls.

This script converts the decrypted blob hashes into a call index → api name dictionary.

blob = bytes([
    0x6B, 0x65, 0x72, 0x6E, 0x65, 0x6C, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x31, 0x33, 0x38,
    0x36, 0x35, 0x31, 0x35, 0x38, 0x33, 0x38, 0x00, 0x31, 0x33, 0x30, 0x30, 0x36, 0x38, 0x33, 0x31,
    0x31, 0x34, 0x00, 0x2D, 0x32, 0x30, 0x39, 0x30, 0x39, 0x37, 0x30, 0x37, 0x38, 0x36, 0x00, 0x2D,
    0x31, 0x30, 0x37, 0x36, 0x33, 0x33, 0x30, 0x35, 0x31, 0x36, 0x00, 0x36, 0x38, 0x32, 0x36, 0x35,
    0x37, 0x37, 0x34, 0x37, 0x00, 0x2D, 0x31, 0x31, 0x32, 0x31, 0x31, 0x39, 0x38, 0x30, 0x38, 0x30,
    0x00, 0x2D, 0x39, 0x32, 0x32, 0x37, 0x39, 0x35, 0x39, 0x34, 0x39, 0x00, 0x2D, 0x35, 0x37, 0x39,
    0x39, 0x32, 0x39, 0x31, 0x30, 0x38, 0x00, 0x39, 0x37, 0x30, 0x39, 0x31, 0x30, 0x32, 0x33, 0x34,
    0x00, 0x39, 0x38, 0x32, 0x34, 0x34, 0x34, 0x35, 0x37, 0x30, 0x00, 0x31, 0x33, 0x33, 0x39, 0x39,
    0x37, 0x32, 0x38, 0x32, 0x36, 0x00, 0x31, 0x33, 0x35, 0x31, 0x35, 0x30, 0x37, 0x31, 0x36, 0x32,
    0x00, 0x38, 0x33, 0x36, 0x36, 0x35, 0x36, 0x30, 0x32, 0x36, 0x00, 0x38, 0x34, 0x38, 0x31, 0x39,
    0x30, 0x33, 0x36, 0x32, 0x00, 0x31, 0x32, 0x33, 0x39, 0x33, 0x30, 0x38, 0x39, 0x35, 0x34, 0x00,
    0x31, 0x32, 0x35, 0x30, 0x38, 0x34, 0x33, 0x32, 0x39, 0x30, 0x00, 0x2D, 0x31, 0x36, 0x35, 0x34,
    0x36, 0x34, 0x36, 0x37, 0x33, 0x35, 0x00, 0x2D, 0x38, 0x34, 0x38, 0x34, 0x30, 0x30, 0x33, 0x33,
    0x38, 0x00, 0x32, 0x30, 0x38, 0x35, 0x34, 0x38, 0x30, 0x34, 0x35, 0x39, 0x00, 0x2D, 0x36, 0x35,
    0x32, 0x32, 0x33, 0x31, 0x35, 0x33, 0x37, 0x00, 0x33, 0x38, 0x39, 0x36, 0x30, 0x38, 0x37, 0x38,
    0x37, 0x00, 0x2D, 0x38, 0x38, 0x35, 0x38, 0x30, 0x35, 0x33, 0x36, 0x30, 0x00, 0x2D, 0x32, 0x30,
    0x34, 0x39, 0x36, 0x33, 0x31, 0x30, 0x30, 0x38, 0x00, 0x2D, 0x32, 0x35, 0x31, 0x31, 0x33, 0x31,
    0x30, 0x33, 0x32, 0x00, 0x2D, 0x31, 0x37, 0x33, 0x38, 0x37, 0x33, 0x33, 0x32, 0x32, 0x30, 0x00,
    0x2D, 0x32, 0x31, 0x31, 0x31, 0x31, 0x37, 0x30, 0x32, 0x31, 0x34, 0x00, 0x31, 0x34, 0x37, 0x31,
    0x33, 0x34, 0x32, 0x30, 0x33, 0x39, 0x00, 0x36, 0x35, 0x36, 0x38, 0x39, 0x38, 0x36, 0x34, 0x36,
    0x00, 0x31, 0x34, 0x37, 0x33, 0x31, 0x32, 0x31, 0x30, 0x35, 0x30, 0x00, 0x33, 0x35, 0x35, 0x32,
    0x35, 0x31, 0x34, 0x38, 0x39, 0x00, 0x31, 0x38, 0x31, 0x38, 0x33, 0x37, 0x33, 0x35, 0x30, 0x37,
    0x00, 0x2D, 0x38, 0x30, 0x33, 0x37, 0x38, 0x36, 0x36, 0x34, 0x31, 0x00, 0x31, 0x31, 0x38, 0x32,
    0x36, 0x34, 0x39, 0x34, 0x34, 0x34, 0x00, 0x39, 0x31, 0x37, 0x30, 0x35, 0x34, 0x36, 0x32, 0x37,
    0x00, 0x2D, 0x31, 0x39, 0x36, 0x35, 0x30, 0x37, 0x35, 0x34, 0x39, 0x37, 0x00, 0x32, 0x31, 0x31,
    0x30, 0x32, 0x30, 0x36, 0x30, 0x38, 0x36, 0x00, 0x2D, 0x31, 0x30, 0x38, 0x37, 0x31, 0x32, 0x30,
    0x32, 0x36, 0x34, 0x00, 0x36, 0x30, 0x35, 0x39, 0x36, 0x30, 0x39, 0x35, 0x38, 0x00, 0x33, 0x39,
    0x37, 0x36, 0x36, 0x35, 0x37, 0x33, 0x37, 0x00, 0x31, 0x35, 0x33, 0x39, 0x37, 0x31, 0x30, 0x33,
    0x37, 0x35, 0x00, 0x39, 0x35, 0x38, 0x37, 0x38, 0x36, 0x32, 0x32, 0x37, 0x00, 0x38, 0x32, 0x31,
    0x39, 0x38, 0x30, 0x39, 0x34, 0x37, 0x00, 0x2D, 0x31, 0x37, 0x39, 0x39, 0x37, 0x38, 0x30, 0x38,
    0x32, 0x37, 0x00, 0x31, 0x34, 0x30, 0x38, 0x30, 0x35, 0x39, 0x31, 0x34, 0x36, 0x00, 0x2D, 0x32,
    0x31, 0x32, 0x37, 0x36, 0x38, 0x35, 0x36, 0x33, 0x35, 0x00, 0x31, 0x33, 0x36, 0x39, 0x31, 0x30,
    0x33, 0x34, 0x34, 0x36, 0x00, 0x32, 0x39, 0x38, 0x32, 0x37, 0x30, 0x30, 0x34, 0x39, 0x00, 0x31,
    0x34, 0x33, 0x37, 0x39, 0x33, 0x34, 0x37, 0x39, 0x31, 0x00, 0x2D, 0x31, 0x33, 0x39, 0x32, 0x33,
    0x34, 0x39, 0x36, 0x31, 0x38, 0x00, 0x6E, 0x74, 0x64, 0x6C, 0x6C, 0x2E, 0x64, 0x6C, 0x6C, 0x00,
    0x2D, 0x31, 0x39, 0x36, 0x38, 0x38, 0x35, 0x32, 0x38, 0x31, 0x37, 0x00, 0x2D, 0x31, 0x31, 0x33,
    0x35, 0x39, 0x32, 0x35, 0x30, 0x32, 0x36, 0x00, 0x39, 0x36, 0x31, 0x30, 0x31, 0x34, 0x33, 0x32,
    0x35, 0x00, 0x2D, 0x35, 0x39, 0x33, 0x32, 0x35, 0x30, 0x38, 0x33, 0x00, 0x2D, 0x38, 0x35, 0x31,
    0x36, 0x32, 0x34, 0x32, 0x33, 0x38, 0x00, 0x31, 0x34, 0x35, 0x34, 0x38, 0x34, 0x33, 0x36, 0x36,
    0x32, 0x00, 0x2D, 0x31, 0x34, 0x36, 0x37, 0x34, 0x38, 0x34, 0x33, 0x30, 0x35, 0x00, 0x75, 0x73,
    0x65, 0x72, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x2D, 0x35, 0x33, 0x31, 0x31, 0x33, 0x31,
    0x35, 0x39, 0x37, 0x00, 0x2D, 0x35, 0x33, 0x35, 0x30, 0x34, 0x36, 0x36, 0x30, 0x35, 0x00, 0x2D,
    0x31, 0x34, 0x36, 0x33, 0x30, 0x34, 0x35, 0x39, 0x32, 0x37, 0x00, 0x77, 0x73, 0x32, 0x5F, 0x33,
    0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x2D, 0x38, 0x35, 0x33, 0x30, 0x36, 0x32, 0x37, 0x38, 0x34,
    0x00, 0x2D, 0x38, 0x34, 0x33, 0x36, 0x33, 0x30, 0x34, 0x30, 0x30, 0x00, 0x2D, 0x38, 0x31, 0x38,
    0x31, 0x36, 0x34, 0x31, 0x37, 0x33, 0x00, 0x31, 0x38, 0x35, 0x31, 0x33, 0x38, 0x33, 0x37, 0x38,
    0x33, 0x00, 0x31, 0x35, 0x33, 0x34, 0x32, 0x31, 0x36, 0x35, 0x36, 0x38, 0x00, 0x2D, 0x37, 0x31,
    0x38, 0x39, 0x31, 0x34, 0x36, 0x38, 0x38, 0x00, 0x31, 0x38, 0x33, 0x31, 0x32, 0x39, 0x31, 0x32,
    0x35, 0x33, 0x00, 0x31, 0x33, 0x32, 0x38, 0x31, 0x37, 0x32, 0x30, 0x38, 0x32, 0x00, 0x2D, 0x38,
    0x31, 0x35, 0x35, 0x39, 0x34, 0x31, 0x35, 0x33, 0x00, 0x31, 0x36, 0x34, 0x37, 0x38, 0x38, 0x39,
    0x38, 0x39, 0x37, 0x00, 0x2D, 0x31, 0x31, 0x35, 0x30, 0x37, 0x31, 0x34, 0x34, 0x31, 0x36, 0x00,
    0x2D, 0x36, 0x32, 0x32, 0x37, 0x30, 0x32, 0x34, 0x34, 0x38, 0x00, 0x2D, 0x35, 0x30, 0x39, 0x36,
    0x34, 0x39, 0x39, 0x39, 0x36, 0x00, 0x2D, 0x32, 0x30, 0x39, 0x39, 0x32, 0x32, 0x37, 0x30, 0x35,
    0x33, 0x00, 0x2D, 0x32, 0x30, 0x39, 0x37, 0x38, 0x31, 0x34, 0x33, 0x34, 0x39, 0x00, 0x2D, 0x35,
    0x37, 0x33, 0x39, 0x32, 0x34, 0x36, 0x34, 0x35, 0x00, 0x2D, 0x31, 0x37, 0x35, 0x34, 0x39, 0x32,
    0x32, 0x33, 0x32, 0x31, 0x00, 0x2D, 0x31, 0x37, 0x35, 0x34, 0x39, 0x32, 0x32, 0x33, 0x32, 0x34,
    0x00, 0x31, 0x35, 0x32, 0x36, 0x33, 0x36, 0x38, 0x34, 0x31, 0x32, 0x00, 0x31, 0x32, 0x39, 0x36,
    0x37, 0x36, 0x30, 0x31, 0x31, 0x35, 0x00, 0x31, 0x34, 0x34, 0x37, 0x37, 0x31, 0x37, 0x36, 0x32,
    0x37, 0x00, 0x2D, 0x38, 0x37, 0x37, 0x33, 0x33, 0x31, 0x37, 0x34, 0x39, 0x00, 0x31, 0x33, 0x33,
    0x32, 0x39, 0x32, 0x36, 0x37, 0x30, 0x37, 0x00, 0x32, 0x30, 0x30, 0x36, 0x32, 0x33, 0x31, 0x30,
    0x39, 0x31, 0x00, 0x41, 0x64, 0x76, 0x61, 0x70, 0x69, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00,
    0x31, 0x36, 0x30, 0x32, 0x33, 0x36, 0x32, 0x39, 0x30, 0x30, 0x00, 0x31, 0x39, 0x34, 0x33, 0x30,
    0x38, 0x38, 0x38, 0x30, 0x35, 0x00, 0x31, 0x35, 0x39, 0x35, 0x31, 0x36, 0x37, 0x31, 0x37, 0x00,
    0x38, 0x32, 0x37, 0x31, 0x39, 0x39, 0x36, 0x33, 0x33, 0x00, 0x2D, 0x31, 0x35, 0x32, 0x31, 0x35,
    0x39, 0x39, 0x31, 0x30, 0x37, 0x00, 0x39, 0x37, 0x38, 0x36, 0x39, 0x32, 0x39, 0x36, 0x39, 0x00,
    0x37, 0x34, 0x32, 0x38, 0x33, 0x36, 0x35, 0x31, 0x33, 0x00, 0x37, 0x34, 0x30, 0x34, 0x37, 0x37,
    0x31, 0x38, 0x35, 0x00, 0x31, 0x33, 0x38, 0x31, 0x31, 0x36, 0x33, 0x36, 0x36, 0x39, 0x00, 0x52,
    0x70, 0x63, 0x72, 0x74, 0x34, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x31, 0x38, 0x36, 0x36, 0x33, 0x34,
    0x32, 0x38, 0x36, 0x33, 0x00, 0x57, 0x69, 0x6E, 0x68, 0x74, 0x74, 0x70, 0x2E, 0x64, 0x6C, 0x6C,
    0x00, 0x33, 0x30, 0x38, 0x36, 0x31, 0x33, 0x31, 0x36, 0x38, 0x00, 0x31, 0x38, 0x34, 0x34, 0x38,
    0x37, 0x33, 0x32, 0x33, 0x35, 0x00, 0x2D, 0x36, 0x32, 0x36, 0x33, 0x34, 0x32, 0x36, 0x33, 0x00,
    0x32, 0x36, 0x38, 0x39, 0x38, 0x32, 0x38, 0x34, 0x36, 0x00, 0x31, 0x39, 0x35, 0x34, 0x30, 0x32,
    0x32, 0x34, 0x38, 0x35, 0x00, 0x32, 0x33, 0x35, 0x36, 0x39, 0x38, 0x35, 0x39, 0x39, 0x00, 0x35,
    0x34, 0x31, 0x37, 0x35, 0x37, 0x33, 0x35, 0x39, 0x00, 0x31, 0x31, 0x34, 0x32, 0x32, 0x31, 0x30,
    0x39, 0x38, 0x30, 0x00, 0x2D, 0x33, 0x31, 0x34, 0x36, 0x35, 0x30, 0x32, 0x38, 0x00, 0x2D, 0x36,
    0x30, 0x39, 0x31, 0x37, 0x39, 0x32, 0x31, 0x00, 0x2D, 0x36, 0x34, 0x35, 0x33, 0x37, 0x30, 0x34,
    0x38, 0x39, 0x00, 0x35, 0x38, 0x36, 0x36, 0x30, 0x38, 0x39, 0x31, 0x36, 0x00, 0x38, 0x31, 0x33,
    0x35, 0x33, 0x35, 0x38, 0x36, 0x37, 0x00, 0x2D, 0x32, 0x31, 0x33, 0x31, 0x33, 0x31, 0x32, 0x31,
    0x35, 0x38, 0x00, 0x2D, 0x32, 0x31, 0x33, 0x30, 0x36, 0x30, 0x33, 0x32, 0x38, 0x34, 0x00, 0x31,
    0x35, 0x32, 0x37, 0x33, 0x39, 0x30, 0x30, 0x32, 0x00, 0x49, 0x70, 0x68, 0x6C, 0x70, 0x61, 0x70,
    0x69, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x38, 0x30, 0x36, 0x34, 0x37, 0x33, 0x33, 0x35, 0x36, 0x00,
    0x43, 0x72, 0x79, 0x70, 0x74, 0x33, 0x32, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x31, 0x34, 0x33, 0x34,
    0x31, 0x38, 0x33, 0x31, 0x38, 0x39, 0x00, 0x2D, 0x31, 0x32, 0x30, 0x38, 0x36, 0x30, 0x33, 0x32,
    0x00, 0x53, 0x68, 0x6C, 0x77, 0x61, 0x70, 0x69, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x2D, 0x31, 0x31,
    0x36, 0x30, 0x32, 0x39, 0x30, 0x30, 0x37, 0x30, 0x00, 0x55, 0x72, 0x6C, 0x6D, 0x6F, 0x6E, 0x2E,
    0x64, 0x6C, 0x6C, 0x00, 0x2D, 0x37, 0x37, 0x36, 0x37, 0x36, 0x35, 0x30, 0x36, 0x34, 0x00, 0x6D,
    0x73, 0x76, 0x63, 0x72, 0x74, 0x2E, 0x64, 0x6C, 0x6C, 0x00, 0x31, 0x38, 0x30, 0x31, 0x31, 0x32,
    0x30, 0x31, 0x31, 0x35, 0x00, 0x31, 0x36, 0x35, 0x36, 0x39, 0x34, 0x35, 0x34, 0x39, 0x35, 0x00,
    0x31, 0x32, 0x36, 0x36, 0x38, 0x37, 0x31, 0x33, 0x34, 0x37, 0x00, 0x31, 0x32, 0x36, 0x32, 0x31,
    0x35, 0x32, 0x35, 0x36, 0x33, 0x00, 0x2D, 0x31, 0x34, 0x34, 0x31, 0x36, 0x31, 0x33, 0x32, 0x32,
    0x32, 0x00, 0x2D, 0x37, 0x31, 0x38, 0x33, 0x31, 0x36, 0x37, 0x33, 0x36, 0x00, 0x2D, 0x33, 0x34,
    0x35, 0x38, 0x31, 0x37, 0x37, 0x39, 0x38, 0x00, 0x2D, 0x33, 0x34, 0x37, 0x31, 0x39, 0x38, 0x35,
    0x32, 0x38, 0x00, 0x31, 0x38, 0x30, 0x37, 0x36, 0x35, 0x37, 0x39, 0x36, 0x38, 0x00, 0x31, 0x31,
    0x36, 0x30, 0x31, 0x39, 0x39, 0x30, 0x39, 0x38, 0x00, 0x2D, 0x39, 0x38, 0x37, 0x32, 0x38, 0x34,
    0x36, 0x30, 0x38, 0x00, 0x31, 0x31, 0x31, 0x32, 0x39, 0x31, 0x31, 0x38, 0x33, 0x32, 0x00, 0x2D,
    0x35, 0x32, 0x30, 0x37, 0x30, 0x31, 0x30, 0x33, 0x31, 0x00, 0x2D, 0x35, 0x32, 0x30, 0x37, 0x30,
    0x34, 0x37, 0x31, 0x31, 0x00, 0x00
    ])

from Pro.Core import *
from Pro.PE import *
from Pro.ccast import *

ror = lambda val, r_bits, max_bits: \
    ((val & (2**max_bits-1)) >> r_bits%max_bits) | \
    (val << (max_bits-(r_bits%max_bits)) & (2**max_bits-1))

def getAPIs(dllpath):
    apis = {}
    c = createContainerFromFile(dllpath)
    dll = PEObject()
    if not dll.Load(c):
        print("error: couldn't load dll")
        return apis
    ordbase = dll.ExportDirectory().Num("Base")
    functions = dll.ExportDirectoryFunctions()
    names = dll.ExportDirectoryNames()
    nameords = dll.ExportDirectoryNameOrdinals()
    n = functions.Count()
    it = functions.iterator()
    for x in range(n):
        func = it.next()
        ep = func.Num(0)
        if ep == 0:
            continue
        apiord = str(ordbase + x)
        n2 = nameords.Count()
        it2 = nameords.iterator()
        name_found = False
        for y in range(n2):
            no = it2.next()
            if no.Num(0) == x:
                name = names.At(y)
                offs = dll.RvaToOffset(name.Num(0))
                name, ret = dll.ReadUInt8String(offs, 500)
                apiname = name.decode("ascii")
                apis[apiname] = apiord
                apis[apiord] = apiname
                name_found = True
                break
        if not name_found:
            apis[apiord] = apiord
    return apis
    
def hash(name):
    x = 0
    for c in name:
        x = ror(x, 0xD, 32)
        x += ord(c)
    x = ror(x, 0xD, 32)
    return x
    
def hashAPIs(apis):
    hapis = {}
    for i, name in apis.items():
        hapis[hash(name)] = name
    return hapis
    
def walkBlob():
    i = 0
    idxs = {}
    pos = 0
    while i < len(blob):
        e = blob.find(b"\x00", i)
        if i == e:
            break
        s = blob[i:e].decode("ascii")
        i = e + 1
        if "." in s:
            dllname = s
            apis = getAPIs("C:\\Windows\\System32\\" + dllname)
            apis = hashAPIs(apis)
        else:
            x = dword(int(s))
            apiname = apis[x]
            idxs[pos] = apiname
            pos += 0x10
            print(apiname)
    return idxs
            
idxs = walkBlob()
print(idxs)

This script uses the index dictionary from the previous script to comment register-based call instructions in the disassembly with the resolved API name.

idxs = {0: 'VirtualAlloc', 16: 'Sleep', 32: 'CreateThread', 48: 'CloseHandle', 64: 'ReadFile', 80: 'CreateFileA', 96: 'WriteFile', 112: 'GetFileSize', 128: 'lstrlenA', 144: 'lstrlenW', 160: 'lstrcpyA', 176: 'lstrcpyW', 192: 'lstrcatA', 208: 'lstrcatW', 224: 'lstrcmpA', 240: 'lstrcmpW', 256: 'VirtualFree', 272: 'WaitForSingleObject', 288: 'TerminateThread', 304: 'GetTickCount', 320: 'FormatMessageA', 336: 'GetLastError', 352: 'EnterCriticalSection', 368: 'LeaveCriticalSection', 384: 'InitializeCriticalSection', 400: 'DeleteCriticalSection', 416: 'LocalFree', 432: 'MultiByteToWideChar', 448: 'WideCharToMultiByte', 464: 'GetComputerNameW', 480: 'GetModuleFileNameW', 496: 'GetCurrentProcessId', 512: 'GetLocalTime', 528: 'QueryPerformanceFrequency', 544: 'QueryPerformanceCounter', 560: 'IsWow64Process', 576: 'GetCurrentProcess', 592: 'GetVersionExA', 608: 'GlobalFree', 624: 'VirtualFreeEx', 640: 'DuplicateHandle', 656: 'DebugBreak', 672: 'CreateEventW', 688: 'DeviceIoControl', 704: 'DeleteFileA', 720: 'GetTempPathA', 736: 'GetTempFileNameA', 752: 'SetErrorMode', 768: 'FreeLibrary', 784: 'RtlGetNtVersionNumbers', 800: 'RtlNtStatusToDosError', 816: 'RtlDecompressBuffer', 832: 'RtlCompressBuffer', 848: 'RtlGetCompressionWorkSpaceSize', 864: 'NtQuerySystemInformation', 880: 'NtQueryObject', 896: 'PeekMessageW', 912: 'GetMessageW', 928: 'PostThreadMessageW', 944: 'send', 960: 'recv', 976: 'closesocket', 992: 'WSAStartup', 1008: 'socket', 1024: 'bind', 1040: 'listen', 1056: 'accept', 1072: 'connect', 1088: 'WSACleanup', 1104: 'inet_addr', 1120: 'inet_ntoa', 1136: 'htons', 1152: 'getaddrinfo', 1168: 'freeaddrinfo', 1184: 'WSAAddressToStringA', 1200: 'setsockopt', 1216: 'getsockopt', 1232: 'recvfrom', 1248: 'sendto', 1264: 'shutdown', 1280: 'WSAGetLastError', 1296: 'select', 1312: 'getpeername', 1328: 'CryptAcquireContextW', 1344: 'CryptDestroyHash', 1360: 'CryptCreateHash', 1376: 'CryptHashData', 1392: 'CryptGetHashParam', 1408: 'CryptDeriveKey', 1424: 'CryptEncrypt', 1440: 'CryptDecrypt', 1456: 'GetUserNameW', 1472: 'UuidCreate', 1488: 'WinHttpGetIEProxyConfigForCurrentUser', 1504: 'WinHttpOpen', 1520: 'WinHttpGetProxyForUrl', 1536: 'WinHttpCloseHandle', 1552: 'WinHttpConnect', 1568: 'WinHttpOpenRequest', 1584: 'WinHttpAddRequestHeaders', 1600: 'WinHttpSendRequest', 1616: 'WinHttpWriteData', 1632: 'WinHttpQueryDataAvailable', 1648: 'WinHttpQueryOption', 1664: 'WinHttpReceiveResponse', 1680: 'WinHttpReadData', 1696: 'WinHttpSetOption', 1712: 'WinHttpSetCredentials', 1728: 'WinHttpQueryAuthSchemes', 1744: 'GetAdaptersInfo', 1760: 'CryptBinaryToStringA', 1776: 'CryptStringToBinaryA', 1792: 'StrStrIA', 1808: 'URLDownloadToFileA', 1824: 'memset', 1840: 'memmove', 1856: 'memcpy', 1872: 'memcmp', 1888: '_wcsicmp', 1904: 'time', 1920: 'strstr', 1936: 'atoi', 1952: '_itow', 1968: 'srand', 1984: 'rand', 2000: '_wcsnicmp', 2016: 'sprintf', 2032: 'printf'}

from Pro.UI import proContext
from Pro.Carbon import *
from Pro.capstone import *
import re

def commentAPIs():
    md = Cs(CS_ARCH_X86, CS_MODE_64)
    v = proContext().getCurrentView()
    ca = v.getCarbon()
    db = ca.getDB()
    e = caASEntry()
    e.end = 0
    while db.getNextASEntry(e.end, e):
        if e.type_id != CarbonType_I_x64:
            continue
        buf = ca.read(e.start, e.end - e.start)
        insns = md.disasm(buf, 0)
        i = next(insns, None)
        if i.mnemonic != "call":
            continue
        print(i.mnemonic, i.op_str)
        if i.op_str.find("rip") != -1:
            continue
        j = i.op_str.find("+ 0x")
        if j == -1:
            continue
        idx = int(i.op_str[j+2:-1], 16)
        if idx > 0x1000:
            continue
        apiname = idxs.get(idx, None)
        if not apiname:
            continue
        c = caComment()
        if db.getComment(e.start, c) and c.text:
            continue
        c.address = e.start
        c.text = apiname
        db.setComment(c)
        print("   ", apiname)
    # update the view
    v.update()
    
commentAPIs()

Cerbero Suite 4.2 is out!

The new version of Cerbero Suite is out with the following news:

– added CAB format support
– added convert/from_array and convert/to_array filters
– added detection of external resources in Office documents
+ improved renaming of variables in the decompiler
– improved dev/array filter
– included OpenSSL executable
– fixed bugs

We’ll be soon publishing videos detailing some of these additions!

Cerbero Suite 4.1 is out!

The new version of Cerbero Suite is out with the following news:

+ added Carbon option to import PDB types into the project header
+ improved x86/x64 decompiler
– fixed bugs

The option in Carbon to import types into the header of a project when loading a PDB comes handy when a crash dump is associated to a structure.

In this case the BugCheck information tells us that at a specific address there’s an EPROCESS structure. By importing the types along with the symbols of ntoskrnl.exe, we import the correct EPROCESS structure to map onto memory.

Of course, Cerbero Suite contains kernel symbols for all version of Windows x86/x64, but by relying on the structures in the PDB we don’t need to load the correct Windows header from the headers folder: just import the types and then open the header of the project!

Cerbero Suite 4.0 is out!

We’re proud to announce the release of Cerbero Suite 4.0!

There are many new features, especially in the advanced version. Support for ARM32/ARM64 in Carbon and the inspection of Windows crash dumps stand out as two major additions.

All of our customers can upgrade at a 50% discount their licenses for the next 3 months! We value our customers and everyone who has bought a license since June should have already received a free upgrade for Cerbero Suite 4! If you fall in that category and haven’t received a new license, please check your spam folder and in case contact us at sales@cerbero.io. Everyone who has acquired a license before June, but in the last 3 months, will get an additional discount.

Starting today we’ll be contacting all of our existing customers and provide them with a discount coupon. If you don’t get an email from us in the next two days, please contact us at sales@cerbero.io!

This is the full list of news:

+ added Carbon loader for Windows user address space
+ added Carbon loader for Windows DMP files
+ added Carbon support for ARM32 and ARM64
+ added Carbon support for PDB symbols
+ added support in Carbon to define data types
+ added memory analysis support for latest Windows 10 versions
added Windows x64 setup
added UI hook extensions
+ improved Windows memory analysis support
+ improved Windows DMP support
+ improved Carbon disassembly
+ improved Ghidra plugin and setup
+ improved decompiler output
improved Hex Editor
improved file stats view
improved symbol demangling
improved Python speed
– improved headers
– improved PE debug directory support
improved PDB support
– improved dark mode support on macOS
improved update check
improved single view mode
improved settings
improved Python SDK
– updated SQLite to 3.32.0
– fixed bugs

Windows crash dumps

Inspecting Windows crash dumps is important for many software developers. Cerbero Suite lets you easily inspect both kernel and mini-dumps. You can view the code, load PDB symbols, inspect the call stack, threads, exception information, bug check information, memory and much more.

This feature does not rely on WinDBG and works on every supported platform!

Carbon support for ARM32 and ARM64

ARM32 and ARM64 are now supported in Carbon and naturally also in the Sleigh decompiler!

Carbon loader for Windows user address space

Every Windows address space can now be explored in Carbon, be it from a physical image or from a crash dump.

Carbon support for PDB symbols

PDB files can be automatically downloaded and imported into Carbon. This feature does not rely on Windows APIs and works on every supported platform.

Defining data types in Carbon

Data types can be defined in Carbon by pressing “D” or via the context menu.

The same data type can be reapplied by pressing “W”.

Memory analysis on the latest Windows 10 versions

We added the headers necessary to perform memory analysis on the latest Windows 10 versions.

Throughout the lifetime of the 4.x series, we’ll continue improving on the support for Windows 10!

Windows x64 edition

A Windows x64 edition has been long overdue, but we didn’t want to deprive our users from being able to run Cerbero Suite on older 32-bit versions of Windows, so we decided to keep both x86 and x64 editions!

UI hook extensions

A new type of extension has been introduced. The purpose of this extension type is to provide additional UI elements for specific parts of the UI. We currently use it to create Python plugins in our settings page.

Improved Carbon disassembly

We have improved Carbon all over the place: the analysis, UI, lists. The experience is now much more refined.

Improved Ghidra plugin and setup

We improved the native UI for Ghidra. By default now the assembly is shown in lower case, as we think it’s easier to read (this feature is configurable).

We also added one more toolbar button in Ghidra for the Cerbero Launcher, a way to launch Cerbero tools on the file currently open in Ghidra.

Setting up the native UI for Ghidra is now easier than ever: just go to the settings in Cerbero under ‘Ghidra’ and click on ‘Install Ghidra plugin’, select the root folder of Ghidra and that’s it! Cerbero will take care of the installation for you!

Improved decompiler output

We have improved the decompiler output by inferring the detection of deferred calls and literals from Carbon to it. A before/after screenshot comparison is worth more than a thousand words!

Hex Editor

Apart from fixing some bugs, we have improved the hex editor by providing a wait dialog with progress and abort to every major data operation.

File stats view

We tried to improve the file stats view by providing additional useful information for all the file formats which warranted it.

Improved symbol demangling

We have greatly improved symbols demangling both for Visual C++ and GCC. All type of mangled symbols are supported now!

Improved speed of Python

We now deploy the bytecode files for all our Python plugins in order to decrease their load time.

Improved updates

Cerbero Suite 4 makes the update process even easier than before. Hashes for updates have always been cryptographically verified, but now you can opt to download the update directly from the UI and that too is verified.

Improved PDB support

More PDB strucutres are now explorable from the UI.

Improved settings

Apart from the Ghidra plugin installer, there’s a new tab in the settings to create a portable distribution of Cerbero Suite 4.

Improved SDK

We have increased the amout of exposed SDK and added new APIs. Among the many things we have exposed is the Sleigh decompiler. Here’s a small code sample:

from Pro.UI import *
from Pro.Carbon import *

v = proContext().getCurrentView()
c = v.getCarbon()
d = CarbonSleighDecompiler(c)
s = d.decompileToString(0x004028C9)
print(s)

A Carbon instance can be created entirely from Python of course.

Improved single view mode

Single view mode is perhaps a barely known feature in Cerbero, but a rather useful one. If you press “Ctrl+Alt+S” while in a view, it will hide all other views. Pressing the shortcut again restores the previous state.

In Cerbero Suite 4 we have introduced the concept of dependent views and have updated single view mode to include them.

We can see an example of this by looking at a crash dump. When we are in the disassembly we would like to keep dependent views (like the call stack or the decompiler) visible when switching to single view mode.

Normal state:

Single view mode:

Apart from the news listed here, we have added many refinements and fixed many bugs.

We hope you enjoy this new release!

Happy hacking!

Cerbero Suite 3.4 is out!

We’re happy to announce the release of Cerbero Suite 3.4!

This release comes with tons of improvements:

– added script editor for Python and JavaScript
– added Python editor workspace
– added Python snippet action
– added Mariana theme
– improved deployment on OS X
+ improved Ghidra native UI
– improved filters
– improved hex workspace
– improved JS debugger
– improved Monokai theme
+ updated Ghidra support to 9.1-BETA
– fixed Header Manager crash due to themes
– fixed some bugs

As you can see from the screen-shots in this post, we have introduced the Mariana theme. I think it’s even easier on the eyes, than the Monokai one.

The Ghidra native UI is now compatible with the latest 9.1-BETA and has been further improved!

Deployment on OS X has been greatly improved by removing the external Python dependency. Just as in the Windows and Linux version, the OS X version now embeds Python.

Also interesting for OS X users: a new instance of Cerbero can be spawned from anywhere in the program by pressing Ctrl+Alt+N (or by clicking the relative toolbar button). This works on other platforms as well, but on OS X it’s especially useful.

The main new feature is the introduction of a script editor for Python and JavaScript. You can open as many editor as you like in a single workspace by running the relative action (or in the case of the Python editor by clicking on on the toolbar button).

Script editors are intended to make writing scripts and executing them extremely fast. They provide a simple mechanism to save scripts and open them by just setting the name of the script. The JavaScript editor also offers a debugging shortcut.

To make the writing of scripts even easier, there’s a new action to insert a Python code snippet.

You can choose from a selection of useful snippets.

This is especially useful to avoid looking up the SDK even for simple things and in time the selection of snippets will grow.

We also improved and added new misc filters.

I personally played many CTFs using Cerbero Suite before working on this release and the improvements are directly related to that. I hope that our users will enjoy these improvements as much as we do!

Happy hacking!

Cerbero Suite 3.3 is out!

We’re happy to announce the release of Cerbero Suite 3.3!

While the most anticipated feature may have been theme support, there’s much more:

added theme support
added MachO Carbon loader
added Monokai theme
improved Ghidra native UI
– improved disassembly view
made Windows XP compatible
– fixed some bugs

Improved Ghidra native UI

Apart from themes, most of the work went into improving the Ghidra native UI. Specifically we improved navigation, added comments in the decompiler, added support for renaming variables and parameters both in the disassembly and the decompiler, improved cross references, added make code / undefine commands, added status updates, fixed bugs.

Also, if you’d like to run Ghidra and the native UI on two different machines, just open the install.pdf in util/ghidra.zip to learn how. 🙂

Carbon: MachO loader

We also added support for x86/x64 MachO files in Carbon!

XP compatibility

Cerbero can now run on Windows XP.

Everything is working apart from the Python ssl module (we might provide support for it in the future). So if you need a malware triage tool or just a Python3 interpreter on XP, you can use Cerbero. 🙂

Happy hacking!

Cerbero Suite 3.2 is out!

This is a rather unusual release and as you can see the change-list is short:

+ added experimental native UI for Ghidra
+ improved disassembly speed
– fixed SSL on Linux

The main addition in version 3.2 is an experimental native UI for Ghidra. Here are a few screen-shots on all supported platforms.

Windows:

Linux:

OS X:

Since this experimental UI has been more of a personal project, I discussed it in more depth on my blog.

As this is a proof of concept, it will be of fundamental importance whether or not you, the user, want this project to mature. Feedback is highly appreciated and will be taken into consideration in order to prioritize this feature and decide how much time to invest into it. Even curses are considered valuable feedback! 🙂

Supporting Ghidra has already had its benefits even considering other features. In fact, in version 3.2 the disassembly view of Carbon has been made faster as a positive side-effect. More of these benefits are about to come as we’re preparing a lot of cool new additions for the upcoming releases. 🙂

Happy hacking!