对于恶意软件动态恶意软件分析,我正在使用自动恶意软件分析 - Cuckoo Sandbox。现在我想添加新的模块来分析恶意软件。我研究过杜鹃沙盒的开发文档。但目前我无法添加我的自定义脚本来对恶意软件/样本进行静态分析。此处提供 Python 脚本。
谁能指导我如何在杜鹃沙箱处理模块中添加更多模块/分析脚本。如果他们在网上有任何文章,请分享。
谢谢
根据文档:
分析包是 Cuckoo Sandbox 的核心组件。它们包含在结构化的 Python 类中,当在客户机中执行时,描述了 Cuckoo 的分析器组件应该如何进行分析。
因此,分析包负责执行处理文件所需的操作。
示例(在 Windows 来宾上)
"C:\\WINDOWS\\system32\\rundll32.exe"
因此,您编写了一个 Analisys 包来告诉 cuckoo 如何打开或执行文件。用于处理文件并提取报告信息的处理模块(报告模块)。
如果要进行静态分析,不需要编写Analisis Package而是编写Processing Module。如果要添加新的行为分析,则需要同时实现.
这个答案是关于编写处理模块的,因为你的问题是关于静态分析的。
我使用文档的最新版本。在文档中我发现了许多有用的东西,其他的东西(比如如何在 html 界面中显示模块报告)我在测试和错误过程中发现了自己并破解了代码。
为了成为处理模块,您的脚本必须满足一些要求。下面,您将看到这些要求是什么以及如何将它们组合在一起以获得处理模块。
分析完成后,Cuckoo 将调用 modules/processing/ 目录中所有可用的处理模块。然后每个模块都将被初始化并执行,返回的数据将附加到我们称为 全局容器的数据结构中。这个容器只是一个大的 Python 字典,它包含由所有模块产生的所有抽象结果,这些模块按其定义的键排序。
处理模块的结果数据将被添加到全局容器中,这样其他模块(例如报告模块)可以访问该信息。
一个基本的处理模块(我们称之为 simple_module)可能如下所示:
# simple_module.py
from lib.cuckoo.common.abstracts import Processing
class SimpleModule(Processing): # A class inheriting Processing.
def run(self): # A run() function
self.key = "simple_info" # The name that will have the returned data in the global container.
data = "This is the data returned by simple_module."
return data # A set of data (list, dictionary or string etc.) that will be appended to the global container.
# under the key secified in `self.key`.
有几个模块类别,如果您查看 cuckoo 的目录层次结构,您会modules
在一些目录中找到一个名为 and 的目录:
signature
意思有不同的想法)。你要关心的目录是:处理。在那里你将放置你的新模块。
在文件中添加如下部分conf/processing.conf
:
[simple_module]
enabled = yes
在处理模块对分析原始结果进行处理和抽象并生成全局容器(参考Processing Modules)后,Cuckoo 会将其传递给所有可用的报告模块,这些模块将对其进行一些使用,并使它以不同的格式访问和消费。
是的!!我们需要其他模块才能看到新处理模块的输出。最简单的方法是将结果记录到文件中:
您可以访问报告模块文档,您会发现如下示例:
让我们为我们的处理模块 simple_module 实现一个报告:
# simple_report.py
import os
from lib.cuckoo.common.abstracts import Report
from lib.cuckoo.common.exceptions import CuckooReportError
class SimpleReport(Report):
def run(self, results): # IMPORTANT!! Here the parameter result will be the Global Container we saw before
try:
report = open(os.path.join(self.reports_path, "simple_report.txt"), "w")
report.write(results["simple_info"]) # We add our information to the Global Container under the key: simple_info
# now we are querying that info to write it down to a file.
report.close()
except (TypeError, IOError) as e:
raise CuckooReportError("Failed to make a simple report, :(")
您还需要启用此报告模块:
每个模块在文件 conf/reporting.conf 中也应该有一个专门的部分,例如,如果您创建一个模块 module/reporting/foobar.py,则必须将以下部分附加到 conf/reporting.conf
[simple_report]
enabled = on
现在当您运行新的分析时,您将能够在文件夹中找到一个名为“simple_report.txt”的storage/analyses/<analysis-number>/reports
文件。
嗯......那有点复杂。如果您查看该文件modules/reporting/reporthtml.py
,您会发现一个类ReportHtml
在某些时候具有如下代码:
try:
tpl = env.get_template("report.html") # Ahhhh, so cuckoo is using a template for this.
html = tpl.render({"results": results}) # Look, the template receives the Global Container (this dude again!!!, it must be a VIP).
except Exception as e:
raise CuckooReportError("Failed to generate HTML report: %s" % e)
try:
with codecs.open(os.path.join(self.reports_path, "report.html"), "w", encoding="utf-8") as report:
report.write(html)
except (TypeError, IOError) as e:
raise CuckooReportError("Failed to write HTML report: %s" % e)
模板在web/templates/analysis
那里你可以找到report.html
。阅读该文件,您会注意到两个重要的代码块:
标签的代码:
<ul class="nav nav-tabs">
<li class="active"><a href="#overview" data-toggle="tab">Quick Overview</a></li>
<li><a href="#static" data-toggle="tab">Static Analysis</a></li>
{% if analysis.behavior.processes %}<li><a href="#behavior" data-toggle="tab" id="graph_hook">Behavioral Analysis</a></li>{% endif %}
<li><a href="#network" data-toggle="tab">Network Analysis</a></li>
<li><a href="#dropped" data-toggle="tab">Dropped Files</a></li>
{% if analysis.procmemory %}<li><a href="#procmemory" data-toggle="tab">Process Memory</a></li>{% endif %}
{% if analysis.memory %}<li><a href="#memory" data-toggle="tab">Memory Analysis</a></li>{% endif %}
<li><a href="#admin" data-toggle="tab">Admin</a></li>
</ul>
以及内容代码(为简洁起见省略了一些代码):
<div class="tab-content">
<div class="tab-pane fade in active" id="overview">
{% include "analysis/overview/index.html" %}
</div>
<div class="tab-pane fade" id="static">
{% include "analysis/static/index.html" %}
</div>
{% if analysis.behavior.processes %}
<div class="tab-pane fade" id="behavior">
{% include "analysis/behavior/index.html" %}
</div>
{% endif %}
...
...
</div>
好的,很明显,我们需要添加我们的模板,让我们继续:
1-创建一个文件,web/templates/analysis/simple_module/index.html
{{analysis.simple_info}}
在上面的行analysis
中指向字典 Global Results 的根。简单信息是我们的流程模块 simple_module 添加到此类字典中的键。
这将替换{{analysis.simple_info}}
为我们在 Global Conatiner 中为该键设置的值。另请参阅Django 模板语言:适用于 Python 程序员。
2-更新web/templates/analysis/report.html
以包含您的模板
添加行
<li class="active"><a href="#simple_module" data-toggle="tab">Simple Module</a></li>
到标签部分。内容部分的以下几行:
<div class="tab-pane fade" id="simple_module">
{% include "analysis/simple_module/index.html" %}
</div>
还有……恶作剧……
需要注意的是,如果您只想以html格式显示结果,则不必实现报表模块,只需创建相应的模板并使用相应的变量即可。
我为此写了一个不同的答案。为了回答 Nika 的问题(他/她在问题上创建了赏金)。
为了回答您的主要问题,我将首先回答您作为评论发布的问题:
Nika:我应该添加还是修改现有的“exe”包?
您应该添加另一个模块,您可以在提交时指定分析包。
#analizer.py
...
# If no analysis package was specified at submission, we try to select
# one automatically.
if not self.config.package:
log.debug("No analysis package specified, trying to detect "
"it automagically.")
...
Nika:脚本将在哪里执行,客户端还是主机?
我认为“客户”是指“客人”。
脚本在来宾中“执行”,如果您查看代码,agent.py
您会看到如下内容:
from SimpleXMLRPCServer import SimpleXMLRPCServer
并且:
def add_analyzer(self, data):
"""Add analyzer.
@param data: analyzer data.
@return: operation status.
"""
data = data.data
if not self._initialize():
return False
try:
zip_data = StringIO()
zip_data.write(data)
with ZipFile(zip_data, "r") as archive:
archive.extractall(ANALYZER_FOLDER)
finally:
zip_data.close()
self.analyzer_path = os.path.join(ANALYZER_FOLDER, "analyzer.py")
return True
这两个代码片段表明:首先,代理使用RCP,其次,分析器被复制到目标虚拟机,所有这些都表明 sripts 在来宾系统中执行。
事实上,有一个函数显示了它是如何执行的:
def execute(self):
"""Execute analysis.
@return: analyzer PID.
"""
global ERROR_MESSAGE
global CURRENT_STATUS
if not self.analyzer_path or not os.path.exists(self.analyzer_path):
return False
try:
proc = subprocess.Popen([sys.executable, self.analyzer_path],
cwd=os.path.dirname(self.analyzer_path))
self.analyzer_pid = proc.pid
except OSError as e:
ERROR_MESSAGE = str(e)
return False
如果在客人上执行,我可以在哪里存储收集到的信息以进一步提取到报告中?
请参阅我的另一个答案,信息始终由处理模块收集并添加到全局容器中。然后从那里您可以使用报告模块访问它。
你的分析包应该使用一些工具来获得你想要的结果或信息。然后在处理模块中,您拥有成员self.dropped_path
,您可以在那里查看文件,处理它并将信息添加到全局容器中。
我希望这可以帮助您更接近想要实现的目标。