Analysis Packages¶
As explained in Analysis Packages, analysis packages are structured Python scripts that allow you to customize the analysis procedure inside the virtualized Windows environment.
By default Cuckoo provides some default packages you can already use, but you are able to create and use some of your own.
Creating new packages is really easy and just requires minimal knowledge of the Python language.
Getting started¶
As first example we’ll take a look at the default package for analyzing generic Windows executables (located at shares/setup/packages/exe.py):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 import os import sys sys.path.append("\\\\VBOXSVR\\setup\\lib\\") from cuckoo.execute import cuckoo_execute from cuckoo.monitor import cuckoo_monitor # The package main function "cuckoo_run" should follow a fixed structure in # order for Cuckoo to correctly handle it and its results. def cuckoo_run(target_path): # Every analysis package can retrieve a list of multiple process IDs it # might have generated. All processes added to this list will be added to # the monitored list, and Cuckoo will wait for all of the to complete their # execution before ending the analysis. pids = [] # The following functions are used to launch a process with the simplified # "cuckoo_execute" function. This function takes as arguments (in specific # order): # - a path to the executable to launch # - arguments to be passed on execution # - a boolean value to specify if the process have to be created in # suspended mode or not (it's recommended to set it to True if the # process is supposed to be injected and monitored). suspended = True (pid, h_thread) = cuckoo_execute(target_path, None, suspended) # The function "cuckoo_monitor" invoke the DLL injection and resume the # process if it was suspended. It needs the process id and the main thread # handle returned by "cuckoo_execute" and the same boolean value to tell it # if it needs to resume the process. cuckoo_monitor(pid, h_thread, suspended) # Append all the process IDs you want to the list, and return the list. pids.append(pid) return pids def cuckoo_check(): return True def cuckoo_finish(): return True
Let’s walk through the given code.
At line 1 and 2 we import the os
and sys
Python modules.
At line 4 we append “\\VBOXSVR\setup\lib\” to Python’s modules paths list:
this will allow us to invoke Cuckoo’s modules directly from the shared folder.
Then we can see that three functions are defined:
In the given example the package just executes the binary located at target_path
in suspended mode and instructs Cuckoo to inject the process and start
monitoring it.
A slightly more complex example is the PDF analysis package (located at shares/setup/packages/pdf.py):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 import os import sys sys.path.append("\\\\VBOXSVR\\setup\\lib\\") from cuckoo.execute import cuckoo_execute from cuckoo.monitor import cuckoo_monitor def cuckoo_run(target_path): pids = [] # Customize this Path with the correct one on your Windows setup. adobe_reader = "C:\\Program Files\\Adobe\\Reader 9.0\\Reader\\AcroRd32.exe" suspended = True (pid, h_thread) = cuckoo_execute(adobe_reader, "\"%s\"" % target_path, suspended) cuckoo_monitor(pid, h_thread, suspended) pids.append(pid) return pids def cuckoo_check(): return True def cuckoo_finish(): return True
In this example we have the same structure, with the only difference being that instead of executing the file at target_path, it executes Adobe Reader with target_path as argument. In this way it basically instructs Cuckoo to monitor what Adobe Reader is doing while opening the given PDF file. As you understand, this opens a large spectrum of possibilities on what Cuckoo can be used for.
cuckoo_run()
¶
This function is the starting point of the analysis. In this block you should define every operation that should performed as initialization of the analysis.
This could include the execution of processes, creation of files, injection of processes and whatever you might need to perform.
It should return a list of PIDs that will be used by Cuckoo to monitor their process status: when all monitored processes complete their execution, Cuckoo will terminate the analysis and exit earlier. If none are returned, Cuckoo will assume that there is no process monitored and will just run for the amount of seconds specified by the analysis timeout.
cuckoo_check()
¶
This function is performed regularly every second during the analysis. It can be used to perform custom checks or any other operation needed.
If the cuckoo_check()
function returns False, Cuckoo will assume that the
package matched a conditional check and it will terminate the analysis earlier.
cuckoo_finish()
¶
This function is executed when the analysis is completed. It can be used for any post-analysis purpose such as copying files or any other operation you might need to perform before the virtual machine is shut down.
Cuckoo Modules¶
As you noticed in the packages examples, Cuckoo provides some custom functions that facilitates some complex Windows actions.
These functions are defined in some Python modules that Cuckoo provide by default. You can use any of these modules in your analysis packages.
Following is a list of available modules and the contained functions.
cuckoo.checkprocess
¶
Function
check_process()
:Prototype:
def check_process(pid)
Description: check if the specified process is still active and running.
Parameter
pid
: process ID of the process to check.Return: True if the process is active, otherwise False.
Usage Example:
1 2 3 4 5 6
from cuckoo.checkprocess import check_process if check_process(pid): print "Process is active!" else: print "Process is NOT active!"
cuckoo.execute
¶
Function
cuckoo_execute()
:Prototype:
def cuckoo_execute(target_path, args = None, suspend = False)
Description: creates a process from the specified file.
Parameter
target_path
: path to the file to execute.Parameter
args
: arguments to pass to the process.Parameter
suspend
: set to True if should be created in suspended mode, otherwise set to False.Return: returns a list with PID and thread handle.
Usage Example:
1 2 3
from cuckoo.execute import cuckoo_execute (pid, h_thread) = cuckoo_execute("C:\\binary.exe")
cuckoo.inject
¶
Function
cuckoo_inject()
:Prototype:
def cuckoo_inject(pid, dll_path)
Description: injects the process with the specified PID with the DLL located at dll_path.
Parameter
pid
: ID of the process to inject.Parameter
dll_path
: path to the DLL to be injected.Return: returns True if injection succeeded, otherwise False.
Usage Example:
1 2 3 4 5 6
from cuckoo.inject import cuckoo_inject if cuckoo_inject(pid, "C:\\library.dll"): print "Process injected successfully!" else: print "Injection failed!"
cuckoo.monitor
¶
Function
cuckoo_resumethread()
:Prototype:
def cuckoo_resumethread(h_thread = -1)
Description: resumes a thread from suspended mode.
Parameter
h_thread
: handle to the thread to be resumed (as returned bycuckoo_execute()
.Return: returns True if resume succeeded, otherwise False.
Usage Example:
1 2 3 4 5 6
from cuckoo.monitor import cuckoo_resumethread if cuckoo_resumethread(h_thread): print "Process resumed!" else: print "Process resume failed!"
Function
cuckoo_monitor()
:Prototype:
def cuckoo_monitor(pid = -1, h_thread = -1, suspended = False, dll_path = None)
Description: instructs Cuckoo to inject and monitor the specified process.
Parameter
pid
: ID of the process to monitor.Parameter
h_thread
: handle to the main thread of the process to monitor (as returned bycuckoo_execute()
).Parameter
suspended
: set to True if the process was created suspended and has to be resumed, otherwise False.Parameter
dll_path
(optional): path to the DLL to inject into the process. If none is specified it will use the default one.Return: returns True if monitor succeeded, otherwise False.
Usage Example:
1 2 3 4 5 6
from cuckoo.monitor import cuckoo_monitor if cuckoo_monitor(pid, h_thread, True): print "Process monitoring started successfully!" else: print "Process monitoring failed!"
cuckoo.trace
¶
Function
cuckoo_trace()
:Prototype:
def cuckoo_trace(pid = -1)
Description: instructs Cuckoo to trace assembly instructions from the specified process.
Parameter
pid
: ID of the process to monitor.Return: returns True if tracing was successful, otherwise False.
Usage Example:
1 2 3 4 5 6
from cuckoo.trace import cuckoo_trace if cuckoo_trace(pid): print "Process traced successfully!" else: print "Process trace failed!"