前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >使用yara防御恶意软件

使用yara防御恶意软件

作者头像
鸿鹄实验室
发布2021-03-31 11:02:49
发布2021-03-31 11:02:49
96200
代码可运行
举报
文章被收录于专栏:鸿鹄实验室鸿鹄实验室
运行总次数:0
代码可运行

本文将分享本人在学习yara时的一些心得,并在后面给出使用yara来防御CobaltStrike的方法。

yara简介

yara是一个基于规则的恶意样本分析工具,旨在帮助蓝队或安全研究员防御和分析恶意软件,其官网地址为https://virustotal.github.io/yara/。你可以使用yara基于文本或二进制来标记恶意软件家族来达到各种目的。

yara的安装也是十分的简单,如win下已有独立文件,下载使用即可。

下面是一个简单的yara规则的demo:

代码语言:javascript
代码运行次数:0
运行
复制
rule silent_banker : banker 
{     
     meta:              
          description = "This is just an example"             
          threat_level = 3                       
          in_the_wild = true          
    strings:                       
          $a = {6A 40 68 00 30 00 00 6A 14 8D 91}                       
          $b = {8D 4D B0 2B C1 83 C0 27 99 6A 4E 59 F7 F9}            
          $c = "UVODFRYSIHLNWPEJXQZAKCBGMT"          
    condition:                        
          $a or $b or $c 
}

yara规则不需要太多知识要求,规则本身十分简单, 真正的技巧和细节都在分析部分

yara规则

yara的规则跟许多语言的语法颇为类似,学习起来也没有那么的困难。下面就是一个基础的yara规则框架:

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{         
    meta:         
    strings:             
    condition: 
}

然后将其保存为yara文件即可。当然该规则没有进行任何操作。一般一个yara文件分为上述的三个部分,meta、strings、condition,并以rule包裹。rule后跟rule名字。关于rule名字有以下要求:

  • 英文或字母组成的字符串
  • 可以使用下划线
  • 第一个字符禁止为数字
  • 大小写敏感
  • 不可以大于128个字符长度

meta部分:主要为该规则的基础信息,如作者信息、创建时间、样本内容等

strings部分:主要用来定义字符串支持正则表达式,用来配合下面的部分使得规则生效。

condition部分:主要来编写表达式来处理strings部分的字符串。

yara关键词

在yara中有一些词不可作为标识符,因为在yara中有特殊用途。

all、and、or、at、int32、wide、not....

具体的可以去查找yara文档,这里不再赘述。

字符串

在yara中字符串的表示主要由十六进制与文本字符串组成。

十六进制字符串:

在十六进制字符串中可以使用通配符表示,通配符为“?”.demo如下:

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{         
    meta:             
        author = "lengyi"         
    strings:              
        $hex1 = { EF 44 ?? D8 A? FB}           
    condition:             
        $hex1 
 }

则它可以匹配以下字符串:

EF 44 01 D8AA FB

不定长字符串可以用[4-6]这类形式表示,而无限长的字符串可以用[-]表示

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{         
    meta:             
        author = "lengyi"         
    strings:             
        $hex1 = { EF 44 [-] D8 A2 FB}              
        $hex2 = { EF 44 [4-6] D8 A2 FB}             
    condition:             
        $hex1 or $hex2  
}

文本字符串:

这个就没啥好说的了,利用文本来匹配字符串,比如mimikatz的logonpasswords等

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{         
    meta:             
        author = "lengyi"         
    strings:              
        $hex1 = "honghe"            
    condition:             
        $hex1 
}

注:转义字符依旧适用。

修饰符

yara提供了丰富的修饰符来方便匹配,如不区分大小写的nocase:

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{     
    meta:         
        author = "lengyi"     
    strings:          
        $hex1 = "honghe"  nocase      
    condition:         
        $hex1 
}

宽字符的wide:

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{         
    meta:             
        author = "lengyi"         
    strings:              
        $hex1 = "honghe" wide         
    condition:             
        $hex1 
}

匹配base64的base64:

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{     
    meta:         
        author = "lengyi"     
    strings:          
        $hex1 = "honghe" base64     
    condition:         
        $hex1 
}

它将会匹配下面的字符串:

aG9uZ2hl

全词匹配的fullword:

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{         
    meta:             
        author = "lengyi"         
    strings:              
        $hex1 = "facebook" fullword         
    condition:             
        $hex1 
}

将匹配:

代码语言:javascript
代码运行次数:0
运行
复制
www.facebook.com www.xor.facebook.com https://www.facebook.com/

正则表达式

这个就不再多说了,唯一要注意的就是使用//来包裹正则表达式,类似于perl语法。

条件

布尔运算

使用and or not等关键字来使字符串充当布尔变量

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{         
    meta:             
        author = "lengyi"         
    strings:              
        $hex1 = "facebook"             
        $hex2 = "book"             
        $hex3 = "face"         
    condition:                 
        ($hex1 and $hex2) or $hex3 
}

文件大小

yara使用filesize来进行文件大小的匹配,大小以字节为单位

代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{         
    meta:             
        author = "lengyi"         
    condition:             
        filesize > 200KB 
}

可执行程序入口点

假如你扫描的文件是一个pe文件或者是一个elf文件时,你可以使用entry_point来进行表示程序的入口点。新版本中已将它归入了PE模块当中,不再单独使用。

访问指定位置的数据

如果你想从特定偏移位置读取数据, 并将其存为一个变量. 那么你可以使用以下任何一个方式:

代码语言:javascript
代码运行次数:0
运行
复制
int8(<offset or virtual address>) 
int16(<offset or virtual address>) 
int32(<offset or virtual address>)   
uint8(<offset or virtual address>) 
uint16(<offset or virtual address>) 
uint32(<offset or virtual address>)   
int8be(<offset or virtual address>) 
int16be(<offset or virtual address>) 
int32be(<offset or virtual address>)  
uint8be(<offset or virtual address>) 
uint16be(<offset or virtual address>) 
uint32be(<offset or virtual address>)
代码语言:javascript
代码运行次数:0
运行
复制
rule RuleName 
{        
    meta:             
        author = "lengyi"         
    condition:                 
        unint16(0) and unit32(unit32(0x3c)) == 0x00004550 
}

以上就是基本的yara规则的语法了,而在正式的编写中呢,可能并不需要这么负责的内容,比如我们以某rat的规则为例:

就是简单的三条url地址,然后使用or进行匹配,而这些url地址也可以使用pestudio来查看:

并不需要太多的逆向知识,除此之外vt也有相关的功能:

唯一的难点就是需要大量的样本来确定,该家族的样本都是使用的该url。

更简单的可能就像下面这样

代码语言:javascript
代码运行次数:0
运行
复制
rule hacktool_windows_mimikatz_copywrite 
{     
    meta:         
         description = "Mimikatz credential dump tool: Author copywrite"
         reference = "https://github.com/gentilkiwi/mimikatz" 
         author = "@fusionrace"         
         md5_1 = "0c87c0ca04f0ab626b5137409dded15ac66c058be6df09e22a636cc2bcb021b8"         
         md5_2 = "0c91f4ca25aedf306d68edaea63b84efec0385321eacf25419a3050f2394ee3b"         
         md5_3 = "0fee62bae204cf89d954d2cbf82a76b771744b981aef4c651caab43436b5a143"         
         md5_4 = "004c07dcd04b4e81f73aacd99c7351337f894e4dac6c91dcfaadb4a1510a967c"        
         md5_5 = "09c542ff784bf98b2c4899900d4e699c5b2e2619a4c5eff68f6add14c74444ca"         
         md5_6 = "09054be3cc568f57321be32e769ae3ccaf21653e5d1e3db85b5af4421c200669"     
    strings:        
         $s1 = "Kiwi en C" fullword ascii wide        
         $s2 = "Benjamin DELPY `gentilkiwi`" fullword ascii wide         
         $s3 = "http://blog.gentilkiwi.com/mimikatz" fullword ascii wide         
         $s4 = "Build with love for POC only" fullword ascii wide        
         $s5 = "gentilkiwi (Benjamin DELPY)" fullword wide        
         $s6 = "KiwiSSP" fullword wide       
         $s7 = "Kiwi Security Support Provider" fullword wide        
         $s8 = "kiwi flavor !" fullword wide     
     condition:         
         any of them 
        }

但对于mimikatz来说,的确简单有效

yara编写

我们以CobaltStrike为例,从分析开始一步步的编写一个yara规则出来。

首先就是文件大小,CobaltStrike生成的马一般都很小,所以我们第一条规则便可以针对马的大小来做限制:

代码语言:javascript
代码运行次数:0
运行
复制
rule CobaltStrike4_1:beacon 
{    
    meta:        
        description = "This rule is used to detect CobaltStrike4.1 Trojan"         
        author = "lengyi"     
    condition:        
        filesize > 10KB and filesize < 24KB 
  }

然后便是分析阶段,将cs的马子放入cutter进行分析,发现入口点基本一样:

将其转换为汇编代码,发现入口点的main的结构相同

继续跟进,发现入口点为0x004014b0 ,然后减去0xc,那么入口点基本就是14B0的位置:

在这里也可以印证我们的猜想

之前说过可以使用pe模块来标识文件的入口点,不过不是使用我们这里的地址,而是需要文件偏移:

即000008B0也就是0x8b0

代码语言:javascript
代码运行次数:0
运行
复制
import"pe" rule CobaltStrike4_1:beacon 
{    
    meta:         
        description ="This rule is used to detect CobaltStrike4.1 Trojan"  
        author = "lengyi"    
   condition:       
        pe.entry_point ==0x8b0 and filesize >10KB and filesize < 24KB 
}

那么这样简单的规则就算写完了,我们继续编写,在查看PE的过程中,我发现其中有一些奇奇怪怪的字符串:

看起来像是一些通信协议,我们回到cutter,查看main函数;

跳到401840,在该地址中可以看到我们的字符串,以及使用CreateThread来新建线程

这里CreateThread的地址为406148,在401648中可以看到正在使用CreateNamedPipeA进行管道通信:

通过附加多个线程,发现均存在该字符串,则在规则中匹配即可:

代码语言:javascript
代码运行次数:0
运行
复制
import "pe" rule CobaltStrike4_1:beacon 
{     
    meta:         
        description = "This rule is used to detect CobaltStrike4.1 Trojan"  
        author = "lengyi"     
    strings:          
        $name = "%c%c%c%c%c%c%c%c%cMSSE-%d-server"     
    condition:       
        pe.entry_point ==0x8b0 and filesize > 10KB and filesize < 24KB and $name 
}

最后使用uint16来判断一下是否为pe文件即可,最后的yara规则如下:

代码语言:javascript
代码运行次数:0
运行
复制
import "pe" rule CobaltStrike4_1:beacon 
{     
    meta:         
        description = "This rule is used to detect CobaltStrike4.1 Trojan"   
        author = "lengyi"    
    strings:         
        $name = "%c%c%c%c%c%c%c%c%cMSSE-%d-server"     
    condition:          
        uint16(0) == 0x5A4D and pe.entry_point ==0x8b0 and filesize > 10KB and filesize < 24KB and $name 
}

然后在一些威胁情报网站随便下了几个样本,三个检出了两个:

还是很不错的。

参考文章:

https://yara.readthedocs.io/en/stable/writingrules.html#more-about-rules

https://www.youtube.com/watch?v=35Exd9GrR5I&ab_channel=HackerSploit

https://www.anquanke.com/post/id/211501#h3-8

声明: 文章初衷仅为攻防研究学习交流之用,严禁利用相关技术去从事一切未经合法授权的入侵攻击破坏活动,因此所产生的一切不良后果与本文作者及该公众号无任何关联。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2020-09-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 鸿鹄实验室 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • yara简介
  • yara规则
    • yara关键词
  • yara编写
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档