nex

Fooling malware like a boss with Cuckoo Sandbox

Blog Post created by nex on Apr 16, 2013

After several months of work, we finally released Cuckoo Sandbox 0.6.

 

This release represents an important step forward in the growth of the project; several new features have been introduced, along with extensive work to improve the overall stability and quality of the sandbox and the results it's now able to produce. Some of this closes down a few of the last milestones we had left in our plan for the Magnificent7 program, some others were designed and introduced as a result of our constant experimentation and tinkering with the latest malware out there.

 

The core focus of this release is the addition of a completely new mechanism for the exchange of results between the controller and the analysis machines. Mark and Jurriaan worked restlessly on what we now call netlog. Fundamentally it consists in a custom socket server called ResultServer that listens on the controller for incoming connections from the guests, which are now able to send back behavioral logs, dumped files, screenshots and memory dumps in real-time.

 

Previous versions of Cuckoo were packaging all the results and sending them back to the controller in a very expensive XMLRPC transaction which often resulted in memory errors, timeouts and other issues. The advantages of the netlog are multiple, but most importantly all previous stability issues should now be avoided and you are also now able to have an overview of the execution of the malware, even in extreme conditions where the analysis machine was made inaccessible, or in the face of any other issues that would result in the loss of the data.

 

If you now enable debug logging, during an analysis (in this case of a PoisonIvy sample) you are able to see results coming in in real-time:

 

2013-04-16 13:37:58,297 [lib.cuckoo.core.resultserver] DEBUG: New connection from: 192.168.56.101:1051
2013-04-16 13:37:58,298 [lib.cuckoo.core.resultserver] DEBUG: LogHandler for live analysis.log initialized.
2013-04-16 13:37:59,138 [lib.cuckoo.core.guest] DEBUG: cuckoo1: analysis not completed yet (status=2)
2013-04-16 13:37:59,578 [lib.cuckoo.core.resultserver] DEBUG: New connection from: 192.168.56.101:1052
2013-04-16 13:37:59,579 [lib.cuckoo.core.resultserver] DEBUG: File upload request for shots/0001.jpg
2013-04-16 13:37:59,608 [lib.cuckoo.core.resultserver] DEBUG: Connection closed: 192.168.56.101:1052
2013-04-16 13:38:00,143 [lib.cuckoo.core.guest] DEBUG: cuckoo1: analysis not completed yet (status=2)
2013-04-16 13:38:00,561 [lib.cuckoo.core.resultserver] DEBUG: New connection from: 192.168.56.101:1053
2013-04-16 13:38:00,562 [lib.cuckoo.core.resultserver] DEBUG: New process (pid=1044, ppid=504, name=poisonivy.exe, path=C:\DOCUME~1\Me\LOCALS~1\Temp\poisonivy.exe)
2013-04-16 13:38:00,562 [lib.cuckoo.core.resultserver] DEBUG: New thread (tid=1048, pid=1044)
2013-04-16 13:38:00,865 [lib.cuckoo.core.resultserver] DEBUG: Connection closed: 192.168.56.101:1053
2013-04-16 13:38:00,883 [lib.cuckoo.core.resultserver] DEBUG: New connection from: 192.168.56.101:1054
2013-04-16 13:38:00,884 [lib.cuckoo.core.resultserver] DEBUG: New process (pid=1528, ppid=1044, name=sa.exe, path=C:\DOCUME~1\Me\LOCALS~1\Temp\sa.exe)
2013-04-16 13:38:00,884 [lib.cuckoo.core.resultserver] DEBUG: New thread (tid=1532, pid=1528)
2013-04-16 13:38:00,919 [lib.cuckoo.core.resultserver] DEBUG: Connection closed: 192.168.56.101:1054
2013-04-16 13:38:00,940 [lib.cuckoo.core.resultserver] DEBUG: New connection from: 192.168.56.101:1055
2013-04-16 13:38:00,941 [lib.cuckoo.core.resultserver] DEBUG: New process (pid=124, ppid=1528, name=sa.exe, path=C:\DOCUME~1\Me\LOCALS~1\Temp\sa.exe)
2013-04-16 13:38:00,941 [lib.cuckoo.core.resultserver] DEBUG: New thread (tid=1952, pid=124)
2013-04-16 13:38:00,987 [lib.cuckoo.core.resultserver] DEBUG: Connection closed: 192.168.56.101:1055
2013-04-16 13:38:01,004 [lib.cuckoo.core.resultserver] DEBUG: New connection from: 192.168.56.101:1056
2013-04-16 13:38:01,005 [lib.cuckoo.core.resultserver] DEBUG: New process (pid=2004, ppid=1968, name=Explorer.EXE, path=C:\WINDOWS\Explorer.EXE)
2013-04-16 13:38:01,005 [lib.cuckoo.core.resultserver] DEBUG: New thread (tid=1888, pid=2004)
2013-04-16 13:38:01,017 [lib.cuckoo.core.resultserver] DEBUG: New connection from: 192.168.56.101:1057
2013-04-16 13:38:01,018 [lib.cuckoo.core.resultserver] DEBUG: File upload request for files/829536561/sa.exe
2013-04-16 13:38:01,022 [lib.cuckoo.core.resultserver] DEBUG: Connection closed: 192.168.56.101:1057






 

As you can see, the analysis machine initiates several connections, reports the analysis.log, stores some screenshots and some dropped files and notifies you of the creation of new processes which are consequently injected and monitored.

 

Another small improvement is the randomization of the components used to instrument the analysis machines. Despite Cuckoo not being largely and specifically detected by malware yet, we are actively working on finding effective ways to disguise possible indicators. Now Cuckoo is able to randomize all critical folders and pipe names used during the analysis:

 

2013-03-26 17:46:42,819 [root] INFO: Starting analyzer from: C:\qymloo
2013-03-26 17:46:42,819 [root] INFO: Storing results at: C:\utohbtqfei
2013-03-26 17:46:42,819 [root] INFO: Pipe server name: \\.\PIPE\mrjpigrzk






 

Instead of going after indicators of specific sandbox products, lately malware writers appear to be focusing on finding smart tricks to generically fool automated analysis systems. In the recent months there has been examples of Upclicker and Banechant triggering their execution by monitoring mouse movements, which are generally not emulated by malware sandboxes.

In a Cuckoo report you can in fact see that it triggers a signature:

 

hook.png

 

In Cuckoo Sandbox 0.6 we introduced a new category of modules called auxiliary modules: they are executed inside the guest in parallel to the execution of the malware and the operations defined within the analysis packages. In order to circumvent such anti-sandboxing tricks, we also added a default auxiliary module that emulates human interactions:

 

def foreach_child(hwnd, lparam):
    buttons = [
        "&yes",
        "&ok",
        "&accept",
        "&next",
        "&install",
        "&run",
        "&agree"
    ]

    classname = create_unicode_buffer(50)
    USER32.GetClassNameW(hwnd, classname, 50)

    # Check if the class of the child is button.
    if classname.value == "Button":
        # Get the text of the button.
        length = USER32.SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0)
        text = create_unicode_buffer(length + 1)
        USER32.SendMessageW(hwnd, WM_GETTEXT, length + 1, text)

        # Check if the button is "positive".
        for button in buttons:
            if text.value.lower().startswith(button):
                log.info("Found button \"%s\", clicking it" % text.value)
                KERNEL32.Sleep(1000)
                USER32.SendMessageW(hwnd, BM_CLICK, 0, 0)

# Callback procedure invoked for every enumerated window.
def foreach_window(hwnd, lparam):
    # If the window is visible, enumerate its child objects, looking
    # for buttons.
    if USER32.IsWindowVisible(hwnd):
        USER32.EnumChildWindows(hwnd, EnumChildProc(foreach_child), 0)

def move_mouse():
    x = random.randint(0, RESOLUTION["x"])
    y = random.randint(0, RESOLUTION["y"])

    USER32.mouse_event(1, x, y, 0, None)

def click_mouse():
    # mouse down
    USER32.mouse_event(2, 0, 0, 0, None)
    KERNEL32.Sleep(50)
    # mouse up
    USER32.mouse_event(4, 0, 0, 0, None)

class Human(Auxiliary, Thread):
    """Human after all"""

    def __init__(self):
        Thread.__init__(self)
        self.do_run = True

    def stop(self):
        self.do_run = False

    def run(self):
        while self.do_run:
            move_mouse()
            click_mouse()
            USER32.EnumWindows(EnumWindowsProc(foreach_window), 0)
            KERNEL32.Sleep(1000)

 

This very simple module fundamentally does three things:

  • Moves the mouse cursor to a random location every second.
  • Clicks the left mouse button.
  • Scans for windows and dialogs and automatically clicks on buttons.

As a result both in the cases of Upclicker and Banechant, they trigger execution and we are able to observe their full behavior .

As a matter of fact you can see in the Banechant report the hook being installed (HookIdentified 14 stands for WH_MOUSE_LL) and few seconds later being uninstalled:

 

hook2.png

And few seconds later it performs some HTTP requests:

 

connect.png

 

So there you go, APT.Banechant fooled like a boss.

 

That's all for now. You can read all the other major changes in the CHANGELOG.

As always, feel free to join us on IRC FreeNode #cuckoosandbox channel and on our mailing list to discuss, provide feedback and report issues!

Outcomes