YARA是一个工具,旨在(但不限于)帮助恶意软件研究人员识别和分类恶意软件样本
。通过YARA,你可以根据文本或二进制模式创建恶意软件特征(或任何你想描述的)的描述。每个描述,又称规则,由一组字符串和一个布尔表达式组成,决定其逻辑。
有史以来第一次,在 YARA 3.0中,您可以扩展其特性以表达更复杂和精细的条件。YARA 3.0通过使用模块来实现这一点,您可以使用这些模块来定义数据结构和函数,以后可以在规则中使用这些模块。您可以在使用模块一节中看到一些模块可以做什么的示例。
下面的代码就演示下如何解析Hello world
写一个hello world 模块
模块是用 C 编写的,并作为编译过程的一部分内置到 YARA 中。为了创建自己的模块,您必须熟悉 C 编程语言以及如何从源代码配置和构建 YARA。您不需要了解 YARA 是如何做到这一点的;
YARA 为模块提供了一个简单的 API,这就是您需要了解的全部内容。
模块的源代码必须位于源代码的 libyara/module 目录中。建议使用模块名作为源文件的文件名,如果模块名为 foo,则源文件应为 foo.c。
在 libyara/module 目录中,你会找到一个 demo.c 文件作为我们的起点,该文件如下所示:
include <yara/modules.h>
#define MODULE_NAME demo
begin_declarations;
declare_string("greeting");
end_declarations;
int module_initialize(
YR_MODULE* module)
{
return ERROR_SUCCESS;
}
int module_finalize(
YR_MODULE* module)
{
return ERROR_SUCCESS;
}
int module_load(
YR_SCAN_CONTEXT* context,
YR_OBJECT* module_object,
void* module_data,
size_t module_data_size)
{
set_string("Hello World!", module_object, "greeting");
return ERROR_SUCCESS;
}
int module_unload(
YR_OBJECT* module_object)
{
return ERROR_SUCCESS;
}
#undef MODULE_NAME
#include <yara/modules.h>
头文件是 YARA 模块 API 的定义所在的地方,因此在所有模块中都需要这个头文件。
#define MODULE_NAME demo
这是定义模块名称的方式,也是必需的。每个模块都必须在源代码的开头定义其名称。在构建到 YARA 中的模块中,模块名称必须是唯一的
。
begin_declarations;
declare_string("greeting");
end_declarations;
在这里,模块声明了可用于 YARA 规则的函数和数据结构
。在这种情况下,我们只是声明了一个字符串变量,命名为问候语。
Module_initialize 函数在 YARA 的初始化过程中被调用,而其对应的 module_finalize 函数在 YARA 的终止过程中被调用。这些函数允许您初始化和终止模块中可能需要使用的任何全局数据结构。
对于每个扫描的文件,只调用此函数一次,但只有在通过某个规则和 import 指令导入模块时才调用此函数。Module_load 函数是您的模块有机会检查被扫描的文件、按照首选的方式解析或分析它,然后填充在声明部分中定义的数据结构的地方。
在本例中,module_load 函数根本不检查文件内容,它只是分配字符串“ Hello World!”前面声明的变量问候语。
对于 module_load 的每个调用,都有一个对应的 module_unload 调用。这个函数允许您的模块释放 module_load 期间分配的任何资源。在这种情况下没有什么可以释放,所以函数只返回 ERROR_SUCCESS。Module_load 和 module_unload 都应返回 ERROR_SUCCESS,以表明一切正常。如果返回不同的值,则扫描将中止,并向用户报告错误。
编译
模块并不是仅仅通过将它们的源代码放入 libyara/module 目录就神奇地内置到 YARA 中的,您必须遵循两个进一步的步骤才能使它们工作。第一步是将您的模块添加到 module_list 文件
,该文件也可以在 libyara/module 目录中找到。
MODULE(tests)
MODULE(pe)
#ifdef CUCKOO_MODULE
MODULE(cuckoo)
#endif
MODULE(demo)
最后一行MODULE(demo)
不能少,代表是demo模块。
第二步是修改 Makefile.am
,告诉 make 程序必须编译模块的源代码并链接到 YARA。在 libyara/Makefile.am 的开头,你会发现:
MODULES = modules/tests/tests.c
MODULES += modules/pe/pe.c
if CUCKOO_MODULE
MODULES += modules/cuckoo/cuckoo.c
endif
MODULES += modules/demo/demo.c
最后一行不能少。
到现在已经准备一个模块了,准备编译吧。切到工作目录执行如下编译命令。
make && make install
创建一个rule文件:
import "demo"
rule HelloWorld
{
condition:
demo.greeting == "Hello World!"
}
使用此规则扫描的任何文件都将与 HelloWord 匹配,因为 demo.looking==“ Hello World!”始终为 true。
声明
声明部分是您声明变量、结构和函数的地方,这些变量、结构和函数将可用于您的 YARA 规则。每个模块都必须包含如下声明部分。
基础类型
在声明部分中,可以分别使用 Declaration_string (< variable name >)、 Declaration_whole (< variable name >)和 Declaration_float (< variable name >)来声明 string、 int 或 float 变量。比如说
begin_declarations;
declare_integer("foo");
declare_string("bar");
declare_float("baz");
end_declarations;
变量名不能包含字母、数字和下划线以外的字符
。这些变量可以在以后的规则中任何需要整数或字符串的地方使用。假设您的模块名称是“ mymodule”,它们可以这样使用:
其他
结构体、数组、字典、函数
在本例中,我们使用 start_struct (< structname >)和 end_struct (< structname >)来划分两个结构,它们分别名为 some_struct 和 another_struct。在结构分隔符中,您可以放置任何其他需要的声明,包括另一个结构声明。还要注意,不同结构的成员可以具有相同的名称,但同一结构中的成员必须具有唯一的名称。
Read more
https://yara.readthedocs.io/en/stable/writingmodules.html#the-hello-world-module
微信公众号:cdtfug, 欢迎关注一起吹牛逼,也可以加微信号「xiaorik」朋友圈围观。