0.前言
LIVE勒索病毒家族最早被曝光是在23年12月份,360的论坛发布了该家族的被加密样本,其加密特征为文件名后直接添加LIVE后缀,这时候还是该家族勒索病毒的1.0版本
https://bbs.360.cn/thread-16111372-1-1.html
https://mp.weixin.qq.com/s/XV0x10YV-Wrs1ZI6tNHjLA
随后的24年1月份,奇安信的威胁情报中心揭秘了该团队利用国内某防泄密软件的漏洞进行渗透并且投放勒索病毒的案例,这时候的LIVE家族已经进化到了2.0版本,因为此时的加密特征为把原文件名修改为一串数字,再添加LIVE后缀
再在今年的2月8日,火绒安全也发布了一篇该家族利用某某通电子文档安全管理系统的文件上传漏洞进行入侵并且投放LIVE2.0勒索病毒的案例,并且附上了解密的demo代码。
而我们团队在去年接触到LIVE家族至今,总共捕获到了该家族的三个版本加密器,根据其加密后文件特征我们命令为1.0、1.5、2.0版本,由于其加密器三个版本本身都存在一些bug,导致其家族自己提供的解密器也无法坐到全部完整的恢复文件,因此我们也根据其加密流程和bug特征,自己制作了能完整恢复的解密补丁工具,在接下来对LIVE家族的分析文章中也都会一一发布。
通过对该LIVE勒索病毒家族的详细分析,无论是其入侵行为还是加密工具的溯源,我们可以清晰地认识到,这是一支新兴的勒索团队。尽管他们拥有国内的攻防经验,但在勒索领域尚显稚嫩。与我们过去所了解的成熟勒索病毒组织相比,他们展现出了不同的攻击模式:
- 技术手段方面,与依赖弱口令爆破手段的Phobos、Mallox等老牌勒索病毒家族不同,LIVE团队借助国内最新的1day漏洞,甚至在某次攻击中,利用了一家安全厂商的安全管控平台漏洞,直接下发加密器对设备进行加密,令原本用于防护的安全设备变成了勒索的利器。
- 勒索软件制作方面,相较于老牌的Phobos家族,LIVE团队的制作手法较为粗糙,其加密的文件连自己的解密器都无法解开。然而,他们展现出的努力值得关注,短短三个月内就迭代更新了三个版本,预示着下一版可能将更难以破解。
- 勒索金额方面,LIVE团队所要求的赎金金额远高于常见的勒索病毒家族。已知的几例支付赎金的受害者,平均赎金约为10万人民币,这一高额赎金的背后是他们深入渗透、加密核心业务服务器的结果,且他们主要针对医疗、能源和大型集团企业等行业。
LIVE勒索病毒组织的出现预示着国内网络安全面临新的挑战,标志着国内勒索病毒攻击的进化进入了2.0时代。与以往主要依赖弱口令爆破和1day漏洞入侵的1.0版本相比,这一新时代的攻击采用了更为复杂的技术手段,如高级持续性威胁(APT)攻击、社会工程学以及零日漏洞利用,展现了更精细化的目标选择和攻击策略,专门针对高价值企业和组织。
本篇文章深入分析了LIVE1.0勒索病毒,我们将继续发布关于LIVE1.5和LIVE2.0勒索病毒的深度分析,并分享相应的解密工具。我们的团队专注于应急响应与勒索病毒研究。如果您或您的客户不幸成为勒索病毒的攻击目标,请随时与我们联系并提交受影响的勒索病毒样本,让我们携手合作,共同维护网络安全防线。
1.背景
近期收到大量客户反馈遭到LIVE勒索病毒攻击,该病毒于2023年12月左右开始传播,并且存在多个版本。该中招客户为某医疗单位,团队工程师通过远程连接进行分析后提取到了勒索病毒的源头。
2.溯源分析
以下为模拟客户系统的部分内网环境遭受该LIVE家族攻击的部分环境:
2.1 排查文件
发现服务器上的文件在2024/2/27 15:06被加密,排查该时段有哪些新增文件。
最终发现在该时段新建了名为systime.exe的文件。
2.2 排查日志
排查相关日志,存在大量smb爆破行为并最终在2024/2/27 15:03:54成功爆破。
并在2024/2/27 15:04:05 登录远程桌面。
实际情况攻击者是使用IP-Guard漏洞进行入侵,上述环境为模拟横向攻击的溯源。
LIVE勒索病毒利用IP-Guard漏洞进行攻击的相关文章:https://mp.weixin.qq.com/s/XV0x10YV-Wrs1ZI6tNHjLA
3.恶意文件基础信息
3.1 加密器基本信息
文件名 |
admin.exe |
编译器 |
Microsoft Visual C/C++(19.33.31630)[C++] |
大小 |
3.08MB |
操作系统 |
Windows |
架构 |
386 |
模式 |
32 位 |
类型 |
EXEC |
字节序 |
LE |
MD5 |
a4b6148a76d8190e47679242c033f598 |
SHA1 |
f20f794b0066bf4868256ac428eeac8ba2d4d837 |
SHA256 |
16d581d781495d16058c43a1e517c0ab7ca3ea8638c9124a4abde72822f8b40f |
3.2 程序配置信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | MinDate: int64 1672531200
MaxDate: int64 1707955200
AppendedExtension: 'LIVE'
NoteFilename: 'FILE RECOVERY_ID_170605242653.txt'
DeleteSystemRestorePoints: false
StopServices: true
ServicesToStop: [ 'MSSQLFDLauncher' , 'MSSQLSERVER' , 'SQLSERVERAGENT' , 'SQLBrowser' , 'SQLTELEMETRY' , 'SQLWriter' , 'MSSQL' , 'SQLAgent' , 'MSSQLServerOLAPService' ]
StopProcesses: true
ProcessesToStop: [ 'postgresql' , 'sqlbrowser' , 'sqlwriter' , 'sqlservr' , 'sqlceip' , 'SQLAGENT' , 'sqlservr' , 'pg_ctl' , 'postgres' ]
DropNoteInSpecificDirectories: true
DirectoriesToDropNoteIn: [ 'C:\Users\Public\Documents' , 'C:\Users\Public\Desktop' ]
IncludeFiles: false
FileSet: [ 'C:\bootmgr' , 'FILE RECOVERY_ID_170605242653.txt' ]
IncludeDirectories: false
DirectorySet: [ 'C:\Program Files' , 'C:\Program Files (x86)' , 'C:\ProgramData' , 'C:\Windows' , 'C:\msys64' , 'C:\Users\All Users' ]
IncludeExtensions: false
NoneSet: [ 'exe' , 'dll' , 'ink' , 'ini' , 'lnk' , 'ico' , 'sys' , 'desktop' , 'mui' , 'live' ]
FastSet: @as []
IntermittentSet: @as []
FullSet: [ 'txt' , 'log' , 'doc' , 'docx' , 'msg' , 'rtf' , 'dat' , 'ppt' , 'pptx' , 'xml' , 'csv' , 'xls' , 'xlsx' ]
EncryptHiddenFiles: true
EncryptHiddenDirectories: false
BufferSize: 8192
Percent: 0.10000000000000001
Segmentation: 512.0
ChangeWallpaper: true
WallpaperName: '170605242653.jpg'
|
3.3 勒索信
Hello....Your file has been encrypted and cannot be used..When you see this letter, your privacy data has been backed up by us. If you do not handle it, we will publish your privacy data after the 7th.....Don't try to change or restore the file yourself, which will destroy them..If necessary, you can decrypt a test file for free. Free test decryption is only available for files less than 3MB in size.....To restore files, you need a decryption tool. Please contact us by email...Please add the file name of this document to the email and send it to me. ..¡¾FILE RECOVERY_ID xxxxxx¡¿..I will tell you the amount you need to pay. After the payment is completed, we will make the decryption tool and send it to you.....Customer service mailbox:..locked@onionmail.org..Spare mailbox: (use this mailbox after no reply in 24 hours)..liveteam@onionmail.org....You can also contact us through intermediary agencies (such as data recovery companies)....If you refuse to pay, you will be attacked constantly. Your privacy -sensitive data will also be announced on Internet.....!! We are a team that pays attention to credibility, so you can pay safely and restore data.
3.4 其他
勒索壁纸
密钥
4.加密后文件分析
4.1 加密文件结构
4.2 加密文件样式
加密文件名特征:文件名+.LIVE
加密文件目录样式:
勒索信+加密文件
解密后:
5.软件运行分析
初步来看加密器并未使用保护措施,并且也没有移除符号表,入口点为main。
5.1 加密器简要运行逻辑框图
5.2 加密器逆向分析
5.2.1 Main函数
从Main函数中可知主要逻辑在progarm_main中。
5.2.2 Progarm_main函数
首先程序会获取运行中的命令行,并且根据其参数内容进行其他功能的使用。
5.2.3 program_print_help函数(打印使用说明)
具体实现在函数program_print_help函数中有所说明,比如:指定加密的目录、删除系统还原点、停止服务等,使用方法是--参数 true/false
。
Progarm_main函数逻辑分析,最开始仅仅只检测cmd命令行的第一个参数是否为--self,如果需要将第二个参数即程序本身路径作为cmdline的第一个参数,以防止后续读取自身文件时,使用第一个参数不是文件本身路径而是--self参数,导致后续读取密钥与程序配置内容失败。
接下来进行读取系统时间,以用作后续的日期判断,来对程序状态进行设置。
再往下是初始化,初始化主要分为两部分:密钥初始化和程序初始化。这里就再次说一下文件的结构组成:
5.2.4 encryption_Initialize函数(密钥初始化)
密钥初始化核心为两部分,一个是从程序文件本身读取KEY,另一个是从将硬编码的IV赋值。
读取KEY:
赋值IV:
整体的密钥初始化就结束了。
5.2.5 program_Initialize函数(程序初始化)
其功能是读取勒索信前面的那部分程序配置信息,并且将其转换为key:value的形式,以便于后续功能的使用。
读取配置项:
转化为key:value形式:
文件内配置信息:
progarm_main函数的余下分析,接下来是一个死循环,主要针对于文件本身的第一个参数以后的其他参数进行遍历,并且判断其功能是否开启等操作,具体功能介绍可见program_print_help函数。
参数遍历完毕后,继续针对时间的比较,从文件配置信息中可以得到一个最大与最小的日期信息,是个Unix的时间戳,转换后可以得到具体时间,作用是来判断软件是否在2023-01-01 08:00:00 ~ 2024-02-15 08:00:00 之间,不在的话就不能够运行。
Mindate: 2023-01-01 08:00:00
Maxdate: 2024-02-15 08:00:00
逻辑实现:
从配置文件中读取勒索信的文件名称,并且从文件名中以‘_’字符进行分割包含的ID,给到progarms_id变量以便后续的使用,最后获取更换壁纸功能的状态,如果是true就会进入到progarm_ChangeWallpaper函数进行勒索壁纸的更换。
配置中的变量内容:
'NoteFilename': <'FILE RECOVERY_ID_170605242653.txt'> //勒索信文件名称
'ChangeWallpaper': <true> //壁纸更换功能状态
'WallpaperName': <'170605242653.jpg'> //勒索壁纸文件名称
代码实现:
5.2.6 progarm_ChangeWallpaper函数(更改壁纸)
和初始化一样,先移动FILE指针到程序文件中的勒索壁纸开头,然后读入到临时变量中。
获取程序文件的目录,进行勒索壁纸的保存。
最后写入一个更换壁纸的Powershell脚本wallpaper.ps1,并且使用system函数执行,完成更换壁纸的操作。
更换壁纸powershell脚本wallpaper.ps1内容:
Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public class Wallpaper {
[DllImport("user32.dll", CharSet = CharSet.Auto)]
public static extern int SystemParametersInfo(int uAction, int uParam, string lpvParam, int fuWinIni);
}
"@; $wallpaperPath = "C:\新建文件夹\170605242653.jpg";
$SPI_SETDESKWALLPAPER = 0x0014;
$UpdateIniFile = 0x01;
$SendChange = 0x02;
[Wallpaper]::SystemParametersInfo($SPI_SETDESKWALLPAPER, 0, $wallpaperPath, $UpdateIniFile -bor $SendChange)"@;
$wallpaperPath = "C:\新建文件夹\170605242653.jpg";
$SPI_SETDESKWALLPAPER
勒索壁纸:
获取勒索信的内容,其逻辑跟初始化和获取壁纸图片方法一样,将勒索信内容赋值到info_context变量中,以便后续的使用。
对IncludeExtensions配置项的状态进行获取,来判断是否启动包含扩展的功能,这里软件中默认是False,所以他将获取NoneSet的配置项内容,即不加密的文件后缀。
IncludeExtensions配置项的状态也决定程序使用那个加密函数,这里加密函数有两个:一个是___lambda4__program_encrypt;另外一个是___lambda5__program_encrypt,这里的使用___lambda5__program_encrypt加密函数。
程序为了保证写入勒索信和对文件进行加密顺利,将利用system函数来执行cmd命令对系统进行恢复选项的禁用并且对操作系统的引导状态策略设置为忽略所有故障。
之后就是对程序指定的服务和进程的停止操作。
进程
服务
在对指定的服务和进程进行关闭后,将开始最为关键的对文件操作的流程了。
首先是写入勒索信
因为DropNoteInSpecificDirectories配置项开启的缘故,所以勒索信会在DirectoriesToDropNoteIn配置项内容下的两个目录中写入名为NoteFilename配置项内容的勒索信文件。
DropNoteInSpecificDirectories内容为:
'DropNoteInSpecificDirectories': <true>
DirectoriesToDropNoteIn内容为:
‘DirectoriesToDropNoteIn': <['C:\\Users\\Public\\Documents', 'C:\\Users\\Public\\Desktop']>
NoteFilename内容为:
'NoteFilename': <'FILE RECOVERY_ID_170605242653.txt'>
勒索信写入完毕后,开始对磁盘文件的遍历与加密。
首先程序作者考虑到了文件数量庞大,需要采用多线程的方式来进行加密比较有效率,甚至于在加密算法上也做了处理。
先是获取处理器数量,开启线程池,创建多线程对象,并且对其错误进行处理,其中启动函数为___lambda6__gfunc函数。
这里判断如果没有错误发生的情况,会再次获取IncludeDirectories配置项内容,再次确认是否包含指定目录功能是否开启。
这里程序因为并未开启该功能,所以直接跳到对所有磁盘遍历操作。
首先是对A-Z字符做了拷贝,以供后续作为磁盘的盘符。
接着对其进行遍历路径的拼接,然后是不断的迭代,类似树的DFS,具体由progarm_Iterate函数实现。
5.2.7 progarm_Iterate函数(遍历文件路径,过滤文件,加密文件)
其参数有五个,分别为:(文件路径,配置信息,勒索信内容,勒索信长度,多线程对象)
首先该函数会打开文件路径下的目录,并且获得该目录下的所有文件的同时进行路径拼接,之后对其路径所指文件或目录进行判断是文件还是目录。
打开目录:
获取该目录下的文件并做判断:
如果是普通文件的话,先对其中的隐藏文件进行判断,然后根据EncryptHiddenFiles配置项来决定是否加密隐藏文件,EncryptHiddenFiles内容为true,所以对隐藏文件也进行加密。
这里考虑到存在NAS的缘故,所有判断了‘.‘开头的文件。
当满足了上述条件后,将最后做一次文件过滤,判断其加密文件后缀是否在Noset配置项内容中,所有过程过程由program_Filter函数实现。
5.2.7.1 program_Filter函数(文件过滤)
其参数有七个,分别为(文件名称,IncludeFiles配置项内容,FileSet配置项内容,FileSet配置项内容长度,IncludeExtension配置项内容,IncludeExtension配置项内容长度)
首先是获取文件的后缀,并且转换为小写。
之后是判断该文件后缀是否在Noset配置项内容中,Noset配置项内容:['exe', 'dll', 'ink', 'ini', 'lnk', 'ico', 'sys', 'desktop', 'mui', 'live'],若是不在则通过,若是在则不通过。
最后会多加一个判断,判断其文件是否是勒索信文件。
接着progarms_Iterate函数的内容进行分析。
在完成了文件过滤后,如果该文件符合上述所有条件,那么就需要将其丢入到线程池中,进行最后的加密了,然后还会将勒索信文件可写标志设置成true。
勒索信标志设置:
若该文件不是普通文件,而是目录,则会进入到判断路径是否是一个目录。
若该文件路径是一个目录则进行过滤,看看是否在DirectorySet配置项内容中的目录。
DirectorySet配置项内容:['C:\Program Files', 'C:\Program Files (x86)', 'C:\ProgramData', 'C:\Windows', 'C:\msys64', 'C:\Users\All Users']。
如果不在的话,就继续向下遍历,如果在,则停止遍历。
最后将判断勒索信可写标识是否为true,若可以写将判断该目录下是否已存在勒索信文件,若不存在则写入。
所有的文件遍历过程就全部分析完毕,接下来将最后分析加密流程。
因为之前提到过线程池的创建,所采用的执行函数是___lambda6__gfunc函数。
5.2.8 ___lambda6__gfunc函数(线程执行函数)
该函数的主要作用是对文件进行加密和重命名。
一切的实现则由task_data_encrypt_and_rename函数实现。
5.2.9 task_data_encrypt_and_rename函数(文件的加密和重命名)
该函数a1是一个结构体,这里暂时只恢复了两条一个是file_path加密文件路径和config配置信息,而加密则是进入到progarm_encrypt函数中进行。
5.2.10 progarm_encrypt函数(文件加密)
前文说过文件加密的progarm_encrypt函数的实现在程序中有两个:
- ___lambda4__program_encrypt函数
- ___lambda5__program_encrypt函数(此程序选择该函数作为加密函数)
5.2.10.1 ___lambda4__program_encrypt函数(文件加密)
该函数有三个参数,分别为:(文件路径,配置信息,程序加密错误信息)
大致的流程:
- 获取加密的文件后缀;
- 获取FastSet配置项,是个空字符数组,并且判断文件后缀是否在当中,若是不在则通过;
- 获取IntermittentSet配置项,是个空字符数组,并且判断文件后缀是否在当中,若在则通过,并且获取BufferSize配置项的大小,文件采用部分加密的方式;
- 若是不在IntermittentSet配置项的数组中,则采用全加密;
- 最后加密结束,返回到task_data_encrypt_and_rename函数进行重命名操作。
5.2.10.2 ___lambda5__program_encrypt函数(文件加密)
该函数有三个参数,分别为:(文件路径,配置信息,程序加密错误信息)
大致的流程:
- 获取加密的文件后缀;
- 获取IntermittentSet配置项,是个空字符数组,并且判断文件后缀是否在当中,若是不在则通过;
- 获取FullSet配置项,为文件扩展数组(FullSet配置项内容为:['txt', 'log', 'doc', 'docx', 'msg', 'rtf', 'dat', 'ppt', 'pptx', 'xml', 'csv', 'xls', 'xlsx']),然后判断文件后缀是否在其中,若在则通过,文件加密采用全加密,由函数encryption_Full实现;
- 若不在FullSet配置项中,则采用部分加密的方式,而加密部分的大小则由配置项BufferSize决定,半加密函数则由encryption_Fast函数实现;
- 最后加密结束,返回到task_data_encrypt_and_rename函数进行重命名操作。
5.2.10.3 encryption_Full函数(全加密)
该函数整体主要做用作文件的分快读写操作,加密部分主要是由encryption_OFB128实现。
- 采用读写的模式打开文件流;
- 采用分块加密,一次加密0x1000大小的数据,直到加密完所有数据为止;
- 采用AES_OFB128的加密方式,由函数encryption_OFB128实现;
- 最后依次将其加密数据写入到原文件中。
5.2.10.4 encryption_Fast函数(部分加密)
该函数整体主要做用作文件的读写操作,加密部分主要是由encryption_OFB128实现。
- 采用读写的模式打开文件流;
- 采用一次性读取0x2000大小数据进行加密;
- 加密算法采用了AES_OFB128的加密方式,由函数encryption_OFB128实现;
- 最后将加密数据写入到原文件中。
5.2.10.5 encryption_OFB128函数(核心加密函数)****:
该函数核心是一个异或加密,首先程序会通过encryption_Treyfer128函数处理iv。
5.2.10.6 encryption_Treyfer128函数(IV处理)
整体的处理呢大致分为四步:
- 将key和iv的值作为sbox的索引加到iv本身,但是需要注意sbox的长度;
- 将对应得到的iv的*2给到v4_Lobyte;
- 再将iv>>7后给到v4;
- 最后将v4和v4_Lobyte做按位或|操作后的值给到iv;
当全部文件加密结束后,回到task_data_encrypt_and_rename函数,将progarm_id写入到文件末尾,做文件重命名操作,以下为基本流程:
- 将progarm_id这8个字节的数据写入到文件末尾;
- 读取AppendedExtension配置项,AppendedExtension内容为LIVE;
- 在其文件名尾部进行拼接;
- 重命名该文件。
最后,在所有磁盘中的文件加密完成后将执行:
- 清空应用程序日志、安全日志和系统日志;
- 获取当前的UTC时间;
- 计算当前时间和另一个时间(v401)之间的差值,并将结果输出为字符串;
- 释放内存并清理变量。
此程序的分析到此结束,下面会发现磁盘中存在以下信息:
6.加密文件乱象的问题及解决方案
这个LIVE1.0的勒索病毒加密存在一定的bug,程序所存在的BUG原因:
因为多线程没有加锁的缘故,导致线程与线程之间出现死锁和自动销毁的现象,有的文件虽然加密过,但是文件名未被修改,多次加密后,因异或加密的特性,会出现自动解密的情况,这就会产生一些文件乱象问题,按照正常的程序流程,正常加密文件的特征是:
- 尾缀存在8字节的progarm_id
- 文件名字带.LIVE
由于这个问题会导致出现一些错误,文件无法用脚本去区分到底是加密的还是解密,比如:
- 尾缀存在8字节特征一次 -> 未加密情况
- 尾缀存在16字节特征两次 -> 加密的情况
因此我们给出的方案就是总共靠两个解密程序恢复,A程序为黑客自己制作的解密器(通过一位已缴纳赎金的受害者获取),我们将其patch之后,可以作为通用的其他受害者解密器使用;B程序为我们制作的补丁程序,若出现某文件用A程序恢复之后无法使用,证明其解密器判断出错,因此运行我们的B程序进行解密,解密之后会释放出两个文件,人工判断选择恢复正确的文件进行保留,错误的文件删除。此外由于LIVE1.0勒索病毒大部分加密的为使用了IP-Guard的系统,IP-Guard自带有文件保护,在文件解密之前,需要批量去除文件的可读权限,因此我们也制作了相关权限解除工具。最终通过这三个程序,我们可以实现百分百还原所有被LIVE1.0勒索病毒加密的文件。
受文章篇幅限制影响,我们将这一部分破解工具的制作使用教程以及相关源码放在我们的工具栏目讲解。