【病毒分析】phobos家族2700变种加密器分析报告

1.样本信息

⽂件名Fast.exe
SHA2563c95bd8e14f6aa92e94ec3318d23a8cc34192259
MD528c6c0b4f54912ec73c9bfeb3f2a8f07
运行平台Windows

2.感染迹象

2.1 文件结构分析

整体文件大小为200+k,把冗余数据去掉,发现仍然可以运行,大小变为56k。与phobos家族的标准一致。

图片

2.1.1 勒索信

图片

2.1.2 勒索壁纸

图片

2.1.3 密钥

加密aes256 key(此key用于加密文件)的rsa公钥为

[0xB7,0x0AA,0x5B,0x0CB,0x0EC,0x0B8,0x1C,0x0E8,0x0B0,0x0EE,0x5,0x0D9,0x8E,0x92,0x67,0x8F,0x0B0,0x11,0x0D9,0x0E0,0x42,0x50,0x0C,0x2A,0x0B1,0x65,0x30,0x23,0x8C,0x0D7,0x0E7,0x6F,0x60,0x0,0x0A4,0x0FA,0x77,0x0DE,0x0C6,0x11,0x6B,0x0DF,0x0E5,0x2D,0x94,0x0E4,0x67,0x0D8,0x1E,0x74,0x0A3,0x0F6,0x53,0x0AB,0x0FE,0x0AA,0x0E9,0x0CC,0x2A,0x0BF,0x5,0x4D,0x7E,0x2A,0x18,0x9F,0x34,0x87,0x9,0x99,0x0AB,0x46,0x7D,0x0D8,0x66,0x4D,0x9,0x55,0x2D,0x0C9,0x8E,0x6C,0x90,0x75,0x0B5,0x0ED,0x6C,0x46,0x77,0x55,0x48,0x38,0x70,0x0CC,0x0DC,0x0F3,0x12,0x1B,0x88,0x44,0x24,0x0C,0x0E9,0x6,0x0A0,0x0C0,0x68,0x33,0x0C,0x95,0x0DB,0x0D,0x5D,0x0EC,0x0D8,0x15,0x92,0x0D1,0x3D,0x0D4,0x44,0x0FA,0x2E,0x73,0x1A,0x49,0x0C1,0x0BD]

写入文件的配置中的iv(变化的)后面固定的16字

[0xD,0x0DB,0x95,0x0C,0x33,0x68,0x0C0,0x0A0,0x6,0x0E9,0x0C,0x24,0x44,0x88,0x1B,0x12]

加密字符串的aes128 key

[0xC3,0x70,0x0D7,0x0CC,0x94,0x27,0x77,0x70,0x0DF,0x2,0x0DF,0x0CE,0x0E2,0x0D5,0x32,0x14]

2.1.4 加密文件结构

文件被加密并重命名如下格式1.png.id[8E1EA49A-3524].[sqlback@memeware.net].2700

图片

图片

被加密的文件的后8 Byte为固定值。

2.1.5 加密文件样式

模拟客户中招后环境

加密后

图片

图片

解密后

图片

2.2 软件运行分析

2.2.1 函数sub_4054BF(内存初始化)

文件加密部分可以从sub_4054BF函数开始分析,此函数的关键部分如下

if ( ntfs_get_names(newfilename, 0x7FFFu, 2) )
{
  GenerateRandomBytes_SHA224_256Pad(16, key);
  v6 = *lpThreadParameter;
  if ( !sub_40868F() )
    break;
  sub_408EBE(lpMem, v3, key, newfilename, *(*v6 + 9));
}
BOOL __usercall sub_40868F@<eax>(int a1@<esi>)
{
  int v1; // eax
  v1 = CRC32_ProcessInteger(0, a1, 32);
  return *(a1 + 160) == CRC32_ProcessInteger(v1, (a1 + 32), 128);
}
  • 首先调用函数ntfs_get_names生成了新的文件名,存放在newfilename中;

  • 调用函数GenerateRandomBytes_SHA224_256Pad随机生成加密此文件的密钥,命名此数据为filekey;

  • 调用函数sub_40868F,通过计算CRC32值并比较,判断给定块中的数据是否与文件的第一个块相匹配,以此来确定该块是否是文件的开头;

  • 最后调用函数sub_408EBE进行加密的其他步骤,下文将函数sub_408EBE重命名为encode;

  • 函数ntfs_get_names仅实现了字符串拼接功能,ID的生成逻辑id[8E1EA49A-3354]不在此函数中,id是通过sub_4054BF的参数传递到此函数中。

2.2.2 ntfs_get_names函数(新文件名字)

ida反编译时参数缺失

mov     esi, [ebp+lpThreadParameter]
...
mov     eax, [esi]
mov     eax, [eax]
push    dword ptr [eax+8]
push    [esp+34h+lpMem]
push    2
push    7FFFh
push    [esp+40h+newfilename]
call    ntfs_get_names

其中push    dword ptr [eax+8]即为.id[8E1EA49A-3524].[sqlback@memeware.net].2700

此函数仅实现字符串拼接功能。

2.2.3 sub_408EBE函数(encode)

int __usercall sub_408EBE@<eax>(const WCHAR *a1@<edi>, _DWORD *a2, int a3, const WCHAR *lpFileName, char a5)
{
  int FileW; // ebx
  DWORD FileAttributesW; // eax
  int v7; // eax
  LARGE_INTEGER FileSize; // [esp+8h] [ebp-20h] BYREF
  LARGE_INTEGER v10; // [esp+10h] [ebp-18h]
  DWORD dwFileAttributes; // [esp+1Ch] [ebp-Ch]
  DWORD v12; // [esp+20h] [ebp-8h]
  int v13; // [esp+24h] [ebp-4h]

  v13 = 0;
  FileW = (int)CreateFileW(a1, 0x80000000, 7u, 0, 3u, 0, 0);
  if ( FileW == -1 )
    return v13;
  if ( !GetFileSizeEx((HANDLE)FileW, &FileSize) )
    goto LABEL_15;
  CloseHandle((HANDLE)FileW);
  FileW = -1;
  v10 = FileSize;
  if ( FileSize.QuadPart )
  {
    FileAttributesW = GetFileAttributesW(a1);
    dwFileAttributes = FileAttributesW;
    if ( FileAttributesW != -1 )
    {
      v12 = FileAttributesW & 1;
      if ( (FileAttributesW & 1) != 0 )
        SetFileAttributesW(a1, FileAttributesW & 0xFFFFFFFE);
      v7 = (a5 & 1) != 0 || v10.QuadPart < 0x180000ui64
         ? sub_408782(a2, a3, a1, lpFileName, a5)
         : sub_408C42(a3, a1, lpFileName, a5);
      v13 = v7;
      if ( v12 )
      {
        if ( v7 )
        {
          SetFileAttributesW(lpFileName, dwFileAttributes);
          return v13;
        }
        SetFileAttributesW(a1, dwFileAttributes);
LABEL_15:
        if ( FileW != -1 )
          CloseHandle((HANDLE)FileW);
      }
    }
  }
  return v13;
}

此函数大致逻辑为:

  • 函数尝试使用CreateFileW打开文件,并检查操作是否成功。如果不成功,则返回;

  • 然后使用GetFileSizeEx获取文件大小,若文件为空,则关闭句柄并返回;

  • 使用GetFileAttributesW检索文件属性,检查文件属性中的只读标志,如果文件是只读的,接下来的代码会使用SetFileAttributesW函数将只读标志清除;

  • 根据文件大小是否小于 0x180000,调用sub_408782或sub_408C42函数;

  • 此代码通过加密现有文件来创建一个新文件。该函数接受现有文件的文件名、密码和要创建的新文件的文件名称。该函数分块读取现有文件,对每个块进行加密,并将加密的块写入新文件。加密是通过使用密码和文件属性计算哈希值来完成的。哈希值用于对文件数据进行块加密。该函数还将新文件的文件属性设置为与现有文件匹配;

  • sub_408782与sub_408C42函数的区别为,一个为全加密,一个为部分加密。

2.2.4 sub_408782函数(全加密)

if ( hObject != (HANDLE)-1 && !sub_40669B(v16, a1->mainkey, a2) )
{
    while ( ReadFile(hFile, (LPVOID)a1->buffer, nNumberOfBytesToRead, &nNumberOfBytesToWrite, 0) )
    {
    if ( nNumberOfBytesToWrite < nNumberOfBytesToRead )
    {
        dwFlagsAndAttributes = 16 - (nNumberOfBytesToWrite & 0xF);
        sub_408FA9((char *)(nNumberOfBytesToWrite + a1->buffer), 0, dwFlagsAndAttributes);
        nNumberOfBytesToWrite += dwFlagsAndAttributes;
    }
    if ( !sub_406432((int)v16, a1->buffer, a1->buffer)
        || !WriteFile(hObject, (LPCVOID)a1->buffer, nNumberOfBytesToWrite, &NumberOfBytesWritten, 0)
        || NumberOfBytesWritten != nNumberOfBytesToWrite )
    {
        break;
    }
    if ( nNumberOfBytesToWrite < nNumberOfBytesToRead )
    {
        v15 = v18;
        *buffer = 0;
        v14 = v19;
        buffer[1] = 2;
        v13 = (int)v20;
        buffer[2] = -257466862;
        buffer[6] = 32;
        sub_408FD7(v13, v14, v15);
        sub_408FD7(v9, (int)a1->zero, 20);
        sub_408FD7(v9 + 20, a2, 16);
        sub_408FD7(v9 + 40, a1->mainkey + 32, 128);
        sub_408FD7(v9 + 172, (int)a1->ident, 6);
        v11 = v22;
        *(_DWORD *)(v9 + 36) = dwFlagsAndAttributes;
        *(_DWORD *)(v9 + 168) = v11 + 178;
        if ( !sub_40669B(v17, a1->mainkey, a2) )
        {
        if ( sub_406432((int)v17, a1->buffer, a1->buffer) )
        {
            sub_408FA9(v17, 0, 0x128u);
            if ( WriteFile(hObject, (LPCVOID)a1->buffer, *(_DWORD *)(v9 + 168), &NumberOfBytesWritten, 0) )
            {
            if ( NumberOfBytesWritten == *(_DWORD *)(v9 + 168) )
            {
                if ( (a5 & 4) != 0 )
                sub_4086B7(hFile);
                if ( (a5 & 2) != 0 )
                {
                FlushFileBuffers(hFile);
                FlushFileBuffers(hObject);
                }
                v23 = 1;
            }
            }
        }
        }
        break;
    }
    }
    sub_408FA9(v16, 0, 0x128u);
}

其中函数sub_406432为加密函数,v16与v17为加密时需要使用的数据,包括密钥与初始IV等,通过函数sub_40669B生成加密需要使用的数据,加密后的数据写入新文件,最后会删除原文件。

在函数sub_C6669B中的a1为重要结构体,包括加密缓冲区与加密需要的信息,分析结构如下:

struct a1{
    Byte* mainkey;//指向164 Byte的地址
    Byte zero[20];//暂未发现作用
    Byte ident[8];//存放机器的唯一标识
    Byte* buffer;//指向一块1114370h大小的内存,用作加密时的缓冲区
    int buffer_size=1114370;//缓冲区大小
}

图片

加密完文件内容后会加密文件的基础信息,包括文件名等信息,其中,a2也会被加密后放入文件末尾(a2为之前生成的filekey)。

在此处下断点:

图片

图片

被加密的数据如下

0348F020  00 00 00 00 02 00 00 00  12 5E A7 F0 79 6F A5 46  .........^.....F
0348F030  37 80 23 35 7A 83 51 3B  20 00 00 00 9E 3F 4F 64  7.#5z.Q; ....?Od
0348F040  43 00 55 00 41 00 73 00  73 00 69 00 73 00 74 00  C.U.A.s.s.i.s.t.
0348F050  61 00 6E 00 74 00 54 00  61 00 73 00 6B 00 2E 00  a.n.t.T.a.s.k...
0348F060  78 00 6D 00 6C 00 00 00  F8 FC 14 D4 F7 93 92 4A  x.m.l..........J

其中包括当前文件的文件名CUAssistantTask.xml

查看此函数sub_C6669B的其余变量可得到被加密的文件路径为C:\Program Files\CUAssistant\CUAssistantTask.xml。

函数sub_408C42的加密流程与函数sub_408782一致,区别是sub_408C42是部分加密,2个函数都会调用同一个加密核心函数sub_406432。

2.2.5 sub_406432函数(加密核心函数)

int aes_crypt_cbc( aes_context *ctx,
                    int mode,
                    const unsigned char iv[16],
                    const unsigned char *input,
                    unsigned char *output,
                    unsigned int length )
{
    int i;
    unsigned char temp[16];
    if( length % 16 )
        return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH );
    if( mode == AES_DECRYPT )
    {
        while( length > 0 )
        {
            memcpy( temp, input, 16 );
            aes_crypt_ecb( ctx, AES_DECRYPT, input, output );
            for( i = 0; i < 16; i++ )
                output[i] = (unsigned char)( output[i] ^ iv[i] );
            memcpy( iv, temp, 16 );
            input  += 16;
            output += 16;
            length -= 16;
        }
    }
    else
    {
        while( length > 0 )
        {
            for( i = 0; i < 16; i++ )
                output[i] = (unsigned char)( input[i] ^ iv[i] );
            aes_crypt_ecb( ctx, AES_ENCRYPT, output, output );
            memcpy( iv, output, 16 );
            input  += 16;
            output += 16;
            length -= 16;
        }
    }
    return( 0 );
}

2.2.6  killsystemprocesses函数(杀死不利进程)

图片

图片

2.2.7 eternal_blue函数(永恒之蓝)

使用永恒之蓝漏洞,通过445端口横向感染内网其他主机,达到利用的目的:

图片

图片

尝试连接其他主机的445端口:

图片

复制令牌:

图片

2.2.8 self_copy函数(自我复制)

自我复制并隐藏.目录如下

C:\Users\Administrator\AppData\Roaming\Microsoft\Windows\StartMenu\Programs\Startup
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup
C:\Users\Administrator\AppData\Local

写入注册表启动项

Software\Microsoft\Windows\CurrentVersion\Run

图片

图片

2.2.9 write_black_page函数(线程执行函数)

写入黑页.通过执行cmd,将所有用户桌面改为全黑色,并生成勒索页面和勒索信息,地址等等。

图片

图片

3.病毒分析概览

根据对样本的深入逆向工程分析,得出该勒索病毒分析结果概览:

主要功能

自我复制、提升权限、开机自启、利用永恒之蓝漏洞进行传播、文件加密、生成勒索提示页(黑页)、创建任务完成监视线程

安全特征

CRC32校验:用于自校验

字符串混淆

采用6347模式,输入49作为ID号解密字符串

AES ECB加密

使用明确指定的Key

子进程操作

创建子进程关闭防火墙

系统操作

修改注册表、添加自启动项目、获取硬盘信息,并进行SHA-256尝试发送HTTP POST请求(未指定参数)

网络与传播

内网扫描,寻找开放445端口的主机利用永恒之蓝漏洞进行攻击,创建攻击线程

进程操作

枚举并终止特定进程,如一些系统应用、数据库服务等

4.安全建议

4.1 风险消减措施

资产梳理排查目标:根据实际情况,对内外网资产进行分时期排查

服务方式:调研访谈、现场勘查、工具扫描

服务关键内容:流量威胁监测系统排查、互联网暴露面扫描服务、技术加固服务、集权系统排查

图片

4.2 安全设备调优

目标

通过对安全现状的梳理和分析,识别安全策略上的不足,结合目标防御、权限最小化、缩小攻击面等一系列参考原则,对设备的相关配置策略进行改进调优,一方面,减低无效或低效规则的出现频次;另一方面,对缺失或遗漏的规则进行补充,实现将安全设备防护能力最优化。

图片

主要目标设备

网络安全防护设备、系统防护软件、日志审计与分析设备、安全监测与入侵识别设备。

4.3 全员安全意识增强调优

目标:

通过网络安全意识宣贯、培训提升全方位安全能力

形式:

培训及宣贯

图片

线下培训课表

若无法组织线下的集体培训,考虑两种方式:

1.提供相关的安全意识培训材料,由上而下分发学习

2.组织相关人员线上开会学习。线上培训模式。

图片

线上学习平台

5.团队介绍

团队坚持自主研发及创新,在攻防演练平台、网络安全竞赛平台、网络安全学习平台方面加大研发投入,目前已获得十几项专利及知识产权。团队也先后通过了ISO9001质量管理体系、ISO14000环境管理体系、ISO45001职业安全健康管理体系 、ITSS(信息技术服务运行维护标准四级)等认证,已构建了网络安全行业合格的资质体系;

6.我们的数据恢复服务流程

多年的数据恢复处理经验,在不断对客户服务优化的过程中搭建了"免费售前+安心保障+专业恢复+安全防御"一体化的专业服务流程。

① 免费咨询/数据诊断分析

       专业的售前技术顾问服务,免费在线咨询,可第一时间获取数据中毒后的正确处理措施,防范勒索病毒在内网进一步扩散或二次执行,避免错误操作导致数据无法恢复。

       售前技术顾问沟通了解客户的机器中毒相关信息,结合团队数据恢复案例库的相同案例进行分析评估,初步诊断分析中毒数据的加密/损坏情况。

② 评估报价/数据恢复方案

       您获取售前顾问的初步诊断评估信息后,若同意进行进一步深入的数据恢复诊断,我们将立即安排专业病毒分析工程师及数据恢复工程师进行病毒逆向分析及数据恢复检测分析。

       专业数据恢复工程师根据数据检测分析结果,定制数据恢复方案(恢复价格/恢复率/恢复工期),并为您解答数据恢复方案的相关疑问。

③ 确认下单/签订合同

       您清楚了解数据恢复方案后,您可自主选择以下下单方式:

双方签署对公合同:根据中毒数据分析情况,量身定制输出数据恢复合同,合同内明确客户的数据恢复内容、数据恢复率、恢复工期及双方权责条款,双方合同签订,正式进入数据恢复专业施工阶段,数据恢复后进行验证确认,数据验证无误,交易完成。

④ 开始数据恢复专业施工

      安排专业数据恢复工程师团队全程服务,告知客户数据恢复过程注意事项及相关方案措施,并可根据客户需求及数据情况,可选择上门恢复/远程恢复。

      数据恢复过程中,团队随时向您报告数据恢复每一个节点工作进展(数据扫描 → 数据检测 → 数据确认 → 恢复工具定制 → 执行数据恢复 → 数据完整性确认)。

⑤ 数据验收/安全防御方案

      完成数据恢复后,我司将安排数据分析工程师进行二次检查确认数据恢复完整性,充分保障客户的数据恢复权益,二次检测确认后,通知客户进行数据验证。

      客户对数据进行数据验证完成后,我司将指导后续相关注意事项及安全防范措施,并可提供专业的企业安全防范建设方案及安全顾问服务,抵御勒索病毒再次入侵。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值