刚接触Cuckoo这款沙箱,在编写自定义规则时遇到很多困难,很多模板里面用的函数官网文档上没有太详细的说明。
只好自己写规则demo,和测试样本demo,再根据沙箱报告的结果去猜这个函数应该怎么正确使用.
在观摩github社区里面其他人共享的Signature模板时,发现别人使用了很多函数,不明白是干什么,常见的模板框架里至少有下面这两个函数
这两个函数官网文档里有描述是干嘛用的,第一个on_call在特定api被调用的时候,把API调用时的环境传给这个on_call函数。
on_call函数有3个签名,分别是:
默认on_call是匹配所有API调用的,所以在写Signature的时候,一定要加一些过滤,来提高性能!
我们写的规则签名文件,都是继承自abstracts.py文件中的Signautre类,在这个类中可以找到一些Cuckoo预设的字段
其中的三个字段主要用来设置on_call的调用频率
我们可以在写自定义签名的时候,重写父类Signature的几个属性,来达到过滤,提高性能的效果。
举个例子:
我想监控写入文件的API,当写入的文件名是1.txt的时候,我要把api,进程名,写入的参数等信息显示在沙箱报告中!
先看看正常版本
from lib.cuckoo.common.abstracts import Signature
class TestWriteFile(Signature):
name = "test_write_file"
description = "test file api calls"
severity = 3
categories = ["test"]
authors = ["Danyang.Wang"]
minimum = "2.0"
filter_apinames = set(["NtWriteFile","NtOpenFile","NtCreateFile"])
def on_call(self, call, process):
if call["api"] in ["NtOpenFile","NtCreateFile"] and call["status"]:
if "1.txt" in call["arguments"]["filepath"]:
self.mark_call()
elif call["api"] == "NtWriteFile" and call["status"]:
self.mark_call()
def on_complete(self):
return self.has_marks()
第一步:通过filter_apinames 指定我要哪些API走我的on_call方法。
第二步:在on_call方法中判断当我指定的API被调用时,我该怎样判断,是否本次API调用含有违规行为。
如果有违规行为我就调用self.mark_call(),这个函数的功能是在沙箱报告中显示详细的函数调用信息,参数,api,进程,句柄等。
上面例子中,我做了两个判断:
上面两个需求都可以在条件里面调用self.mark_call()来实现,最后说一下on_complete这个函数在API调用完成后触发,一般用来判断根据API被调用后对系统产生的影响,来动态修改,description、或者规则评分,最后返回self.has_marks()
self.has_marks()函数会检查本次API调用是否有命中,有是把匹配到的东西否输出到沙箱报告中。
本次API调用有没有命中,取决于在on_call或者on_complete中有没有根据你的判断条件去调用self.mark、self.mark_ioc或self.mark_call其中任意一个函数
我分别写了三个demo来测试拦截写文件的api,刚刚上面的是第一个例子,正常版。
第二个例子:
我没有在on_call里面做任何判断,这里例子的呈现结果是会打印所有我指定的api调用的信息到沙箱报告中
filter_apinames = set(["NtWriteFile","NtOpenFile","NtCreateFile"])
def on_call(self, call, process):
self.mark_call()
def on_complete(self):
return self.has_marks()
第三个例子:
我没有写on_complete函数,也没有返回self.has_marks(),结果就是沙箱报告没有输出任何跟这个签名的信息
filter_apinames = set(["NtWriteFile","NtOpenFile","NtCreateFile"])
def on_call(self, call, process):
if call["api"] in ["NtOpenFile","NtCreateFile"] and call["status"]:
if "1.txt" in call["arguments"]["filepath"]:
self.mark_call()
elif call["api"] == "NtWriteFile" and call["status"]:
self.mark_call()
我写了一个测试程序,提交到沙箱来验证这三条规则,测试程序的功能是创建两个文件,分别是
程序的源码
#include "stdafx.h"
#include
#include
int _tmain(int argc, _TCHAR* argv[])
{
HANDLE hFile = NULL;
hFile = CreateFile(L"1.txt", GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL,NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Create file handle failed\n");
return 0;
}
DWORD dwWritten = 0;
char name[20] = "my name is wdy";
WriteFile(hFile, name, strlen(name), &dwWritten, NULL);
CloseHandle(hFile);
hFile = CreateFile(L"2.txt", GENERIC_ALL, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
printf("Create file handle failed\n");
return 0;
}
char name2[20] = "my name is wdy2";
WriteFile(hFile, name2, strlen(name2), &dwWritten, NULL);
CloseHandle(hFile);
system("pause");
return 0;
}
第一个例子验证结果:打印出了我想要的创建1.txt,和两次写入文件api调用信息,创建2.txt的api调用则被忽略
第二个例子验证结果:在on_call里面我没有写任何判断条件,我只调用了self.mark_call(),所以任何调用我指定api的时候,都会把当前调用的详细信息输出到沙箱报告
第三个例子验证结果:由于没有在on_complete指定self.has_marks(),所以即使你在on_call里匹配到了,沙箱报告中也不会显示这条规则被匹配到
self.mark这个函数用于自定义显示数据,比如你某个函数调用命中的时候,我想自定义数据显示在沙箱报告中,看例子:
def on_call(self, call ,process):
if re.match(self.indicator, call["arguments"]["regkey"], re.I):
self.mark(name=process["process_name"],regKey=call["arguments"]["regkey"],xxx=vvv)
xxx和xxx你随便自定义,最终都会显示在沙箱报告的被命中的这条规则签名下面,只不过显示的格式是你自定义的