CuckooSandbox自定义规则 - self.mark_call,self.mark, self.has_mark函数正确使用方法

刚接触Cuckoo这款沙箱,在编写自定义规则时遇到很多困难,很多模板里面用的函数官网文档上没有太详细的说明。
只好自己写规则demo,和测试样本demo,再根据沙箱报告的结果去猜这个函数应该怎么正确使用.

在观摩github社区里面其他人共享的Signature模板时,发现别人使用了很多函数,不明白是干什么,常见的模板框架里至少有下面这两个函数

  • on_call(self, call, process)
  • on_complete(self)

这两个函数官网文档里有描述是干嘛用的,第一个on_call在特定api被调用的时候,把API调用时的环境传给这个on_call函数。

on_call函数有3个签名,分别是:

  • self 用来获取当前签名类的成员信息,比如我们需要在on_call函数中,根据是否命中不同的函数,来修改当前签名的描述信息
  • call 这个参数与当前被调用的API相关,可以获取API名称以及调用API时传入的具体参数值等信息
  • process 这个参数包含的信息是,当前是哪个进程在调用这个API

默认on_call是匹配所有API调用的,所以在写Signature的时候,一定要加一些过滤,来提高性能!
我们写的规则签名文件,都是继承自abstracts.py文件中的Signautre类,在这个类中可以找到一些Cuckoo预设的字段

其中的三个字段主要用来设置on_call的调用频率

  • filter_processnames = set()
  • filter_apinames = set()
  • filter_categories = set()
  • filter_analysistypes = set()

我们可以在写自定义签名的时候,重写父类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,进程,句柄等。

上面例子中,我做了两个判断:

  • 当打开文件名是1.txt的时候
  • 有文件写入的时候,我要看写入了什么内容

上面两个需求都可以在条件里面调用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()

我写了一个测试程序,提交到沙箱来验证这三条规则,测试程序的功能是创建两个文件,分别是

  • 创建1.txt写入内容为 my name is wdy
  • 创建2.txt写入内容 my name is wdy2

程序的源码


#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调用则被忽略

CuckooSandbox自定义规则 - self.mark_call,self.mark, self.has_mark函数正确使用方法_第1张图片

第二个例子验证结果:在on_call里面我没有写任何判断条件,我只调用了self.mark_call(),所以任何调用我指定api的时候,都会把当前调用的详细信息输出到沙箱报告

CuckooSandbox自定义规则 - self.mark_call,self.mark, self.has_mark函数正确使用方法_第2张图片

第三个例子验证结果:由于没有在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你随便自定义,最终都会显示在沙箱报告的被命中的这条规则签名下面,只不过显示的格式是你自定义的

你可能感兴趣的:(CuckooSanbox)