反调试手段检测——基于yara规则引擎

发布时间 2023-03-22 21:13:25作者: Hanpto

在软件开发中,反调试技术是一种保护软件免受恶意用户攻击的重要手段。它可以帮助开发人员防止黑客、逆向工程师和其他恶意用户试图使用调试工具来修改软件或者窃取敏感信息。但当反调试技术被一些恶意程序,如病毒木马所使用时,这就会增大安全人员分析其的难度。

Yara规则引擎是一个基于Yara语言的软件工具,可以用来识别和分类恶意软件和其他威胁。其工作方式是通过预定义的规则对文件和进程进行扫描,并对匹配规则的文件和进程进行标记和分类。这些规则通常基于文件的内容、特定的字符串、文件名、进程行为等。

研究一个软件存在哪些反调试手段时,传统的方式是使用调试器如Ollydbg、x64dbg对软件进行单步调试,检查出现异常的指令及其附近的指令,根据特征分析是使用了什么反调试手段。这种逐步尝试软件存在哪些反调试手段的方式,是一项体力活,比较耗时耗力。为了解决这一问题,我们可以将各种反调试手段的一些独有特征制定成yara规则,再配合上yara规则引擎去实现自动化检测软件存在的反调试手段。

这里首先说明如何将yara引擎接入到自己的项目中来:
1.在github上将yara项目下拉到本地(GitHub - VirusTotal/yara: The pattern matching swiss knife)
2.使用Visual Studio打开yara项目
3.检查libyara项目的配置类型是否为静态库,若是则生成libyara项目得到libyara.lib静态库文件
image
4.将刚才生成的libyara.lib及libyara/include目录下的yara.h及yara目录一同拷贝到自己项目的目录处
image
5.在自己项目的VC++目录中配置包含目录(yara.h及yara目录所在的目录)及库目录(libyara.lib所在的目录)
image
6.在自己项目的链接器输入中配置附加依赖库(添加yara库的静态库名字 libyara.lib)
image
7.写测试代码进行接入是否成功
测试代码如下(yara版本为4.2.3):

点击查看代码
#include <iostream>
#include "yara.h"

using namespace std;
#pragma comment(lib,"ws2_32.lib")//yara会使用到这网络库和加密库,所以需要加载上
#pragma comment(lib,"crypt32.lib")


int callback(YR_SCAN_CONTEXT* context,//scanner的规则回调函数
    int message,
    void* message_data,
    void* user_data)
{
    if (message == CALLBACK_MSG_RULE_MATCHING) {
        //匹配该特征规则,打印匹配信息后
        printf("filename:%s\nfind antidebug:%s !!!\n\n", (char*)(user_data), ((YR_RULE*)message_data)->identifier);
        g_antiDebugKinds++;
        return CALLBACK_CONTINUE;
    }

    if (message == CALLBACK_MSG_SCAN_FINISHED) {
        //扫描完成,没有匹配任何特征规则
        printf("filename:%s\nscan finished !!!\n\n", (char*)(user_data));
    }

    //没有匹配该特征规则,继续匹配下一条特征规则
    return CALLBACK_CONTINUE;
}


int main(int argc, char* argv[])
{
    YR_RULES* rules = NULL;
    YR_COMPILER* compiler = NULL;
    YR_SCAN_CONTEXT* scan_context = NULL;
    const char* rule_string = "rule CheckRemoteDebuggerPresent { strings: $a = \"CheckRemoteDebuggerPresent\" condition: $a }";
    const char* file_path = "E:\\yaratest.exe";

    // 初始化Yara库
    yr_initialize();

    // 创建编译器对象
    yr_compiler_create(&compiler);

    // 编译规则字符串
    yr_compiler_add_string(compiler, rule_string, NULL);//添加匹配的规则
    yr_compiler_get_rules(compiler, &rules);//获取编译好的规则二进制文件

    // 扫描文件
    yr_scanner_create(rules, &scan_context);
    yr_scanner_set_callback(scan_context, (YR_CALLBACK_FUNC)callback, (void*)file_path);
    yr_scanner_scan_file(scan_context, file_path);

    // 释放资源
    yr_scanner_destroy(scan_context);
    yr_compiler_destroy(compiler);
    yr_finalize();

    return 0;
}

接下来我们来写一个示例程序yaratest.exe测试一下效果:
未使用反调试时:
image
反调试检测结果:
image

使用反调试时:
image
反调试检测结果:
image

注:
1.在以上测试代码中,虽然我们检测是静态的可执行文件,但是yara规则引擎也可以检测运行中的程序,只需要将接口由yr_scanner_scan_file替换为yr_scanner_scan_proc即可。
2.当规则过多或为了能随时替换规则而不改动程序时时,我们可以将规则存储在(.yar)文件中,同时将接口由yr_compiler_add_string替换为yr_compiler_add_file即可。