深度分析Netwalker勒索软件 – 作者:深信服千里目安全实验室

样本简介

Netwalker勒索,也被称为Mailto勒索,Mailto是基于加密文件名格式的勒索软件的名称,Netwalker是基于勒索软件的勒索信内容给出的名称,目前针对的目标是企业和政府机构,近期开始活跃。

该家族发展历程如下,2019 年 9 月左右发现了一个新变种的勒索病毒,该勒索病毒根据被加密文件的扩展名被命名为 Mailto。针对企业的Mailto勒索病毒在 2020 年 1 月 31 日针对性攻击澳洲货运与物流公司 Toll Group 的公司网络,加密了连接至公司网络的所有 Windows 设备,高达 1000 台主机被感染,导致该公司关闭许多 IT 系统。2020 年 2 月初澳洲 Australian Signals Directorate 的 Australian Cyber Security Centre (ACSC)发布了此勒索病毒的警报通知。

深信服安全团队近期捕获了该勒索软件家族的新变种,经分析该变种采用了PowerShell加载执行dll的方式来执行核心勒索,此样本的核心勒索为一个32位dll文件,提取后查找到实际文件名为Netwalker_dll.dll,经后续分析该勒索会采用多种技巧来规避杀软查杀。

这款勒索病毒与Sodinokibi勒索病毒的相似点如下:

1、与Sodinokibi一样,都会在内存中生成一个比较详细的配置文件信息。

2、它的所有函数都被加密处理了,杀毒软件一般很难检测,同时使用dll做为载体直接在内存中加载执行,可以逃避大部分杀毒软件,这个勒索一定是一个技术比较成熟的黑客组织开发的。

3、生成的勒索提示信息,与Sodinokibi的名字类似,[随机加密后缀]-Readme.txt,有可能是仿造Sodinokibi。

加密演示

手工执行核心勒索过程,如下。

1599478134.png!small

加密完成后,进程退出前最后会弹出勒索信,勒索提示信息文件[加密后缀]-Readme.txt,内容如下。

1599478179.png!small

勒索病毒加密后的文件后缀名为随机字符串,如下。

1599478201.png!small

勒索病毒解密网站,如下。

1599478217.png!small

最后经多次实际本地测试,该变种由于没有删除卷影副本,如果之前有过设置系统保护的话可通过设置的还原点进行相应文件恢复。

1599478235.png!small

样本分析

恶意文件是一个混淆加密的PowerShell脚本,先对PowerShell脚本进行解混淆,如下。

1599478456.png!small

解混淆后的内容,如下,字节序列中的0x4d、0x5a明显可以看出是一个PE文件标志头。

1599478477.png!small

1599478493.png!small

手工提取十六进制字节序列,之后生成二进制文件。

1599478624.png!small

最终得到一个会进行进程注入的dll文件,文件名为Netwalker_dll.dll,很奇怪,没有导入表,存在一个导出函数Do,编译时间为2020年4月13日。

1599478641.png!small

1599478647.png!small

即使没有任何导入表的痕迹,但是提取的字符串会存在相应的dll名称,猜测后续会阻止静态分析,进行动态导入。

1599478664.png!small

ida载入后,来到Do函数入口。

1599478681.png!small

先获取ntdll_1.dll的地址,之后加载所需的API函数。

1599478699.png!small

1599478704.png!small

申请一段内存,将所有动态获取的API函数地址存入该区域,后续通过首地址加偏移进行调用。

1599478820.png!small

第二次加载Kernel32.dll,之后加载所需的API函数,存入之前申请的内存空间里。

1599478836.png!small

通过ntdll_1获取到所需的API函数后,会接着判断后续需要导入的其余dll是否可以直接导入,如果当前没有导入,直接调用ldrLoadDll进行导入,然后后续进行加载该dll所需的API函数。

1599478852.png!small

经统计,最终导入了156个API函数。

ntdll_12.RtlAllocateHeap

ntdll_12.RtlFreeHeap

ntdll_12.RtlReAllocateHeap

ntdll_12.memset

ntdll_12.memcpy

ntdll_12.memcmp

ntdll_12.sprintf

ntdll_12.strchr

ntdll_12.strtol

ntdll_12.strcpy

ntdll_12.strcat

ntdll_12.wcscpy

ntdll_12.wcscat

ntdll_12.strstr

ntdll_12.wcsstr

ntdll_12.wcscmp

ntdll_12.wcsncmp

ntdll_12.RtlRandomEx

ntdll_12.RtlRandom

ntdll_12.RtlInitAnsiString

ntdll_12.RtlInitUnicodeString

ntdll_12.RtlAnsiStringToUnicodeString

ntdll_12.RtlUnicodeStringToAnsiString

ntdll_12.RtlFreeUnicodeString

ntdll_12.RtlFreeUnicodeString

ntdll_12.LdrLoadDll

ntdll_12.RtlAdjustPrivilege

ntdll_12.ZwQuerySystemInformation

ntdll_12.ZwOpenProcess

ntdll_12.ZwTerminateProcess

ntdll_12.ZwAllocateVirtualMemory

ntdll_12.ZwFreeVirtualMemory

ntdll_12.ZwWriteVirtualMemory

ntdll_12.ZwReadVirtualMemory

ntdll_12.ZwQueryVirtualMemory

ntdll_12.ZwMapViewOfSection

ntdll_12.ZwUnmapViewOfSection

ntdll_12.ZwSetContextThread

ntdll_12.ZwResumeThread

ntdll_12.ZwSuspendThread

ntdll_12.ZwQueueApcThread

ntdll_12.ZwClose

ntdll_12.ZwSetInformationFile

ntdll_12.ZwQueryInformationFile

ntdll_12.ZwDuplicateObject

ntdll_12.ZwQueryObject

ntdll_12.ZwOpenFile

ntdll_12.RtlDosPathNameToNtPathName_U

ntdll_12.RtlComputeCrc32

ntdll_12.RtlGetVersion

kernel32.CreateFileW

kernel32.WriteFile

kernel32.ReadFile

kernel32.GetFileSize

kernel32.GetFileSizeEx

kernel32.SetFilePointerEx

kernel32.SetEndOfFile

kernel32.GetLogicalDriveStringsW

kernel32.GetDriveTypeW

kernel32.CloseHandle

kernel32.GetTickCount

kernel32.GetTempPathW

kernel32.GetTempFileNameW

kernel32.CopyFileW

kernel32.MoveFileW

kernel32.DeleteFileW

kernel32.CreateProcessW

kernel32.ExitProcess

kernel32.CreateDirectoryW

kernel32.RemoveDirectoryW

kernel32.GetWindowsDirectoryW

kernel32.GetSystemDirectoryW

kernel32.GetComputerNameExW

kernel32.GetVersion

kernel32.GetModuleFileNameW

kernel32.FindResourceA

kernel32.LoadResource

kernel32.LockResource

kernel32.SizeofResource

kernel32.FindFirstFileW

kernel32.FindNextFileW

kernel32.FindClose

kernel32.WaitForMultipleObjects

kernel32.CreateThread

kernel32.IsWow64Process

kernel32.Wow64DisableWow64FsRedirection

kernel32.Wow64RevertWow64FsRedirection

kernel32.Sleep

kernel32.GetFileAttributesW

kernel32.SetFileAttributesW

kernel32.WaitForDebugEvent

kernel32.ContinueDebugEvent

kernel32.DebugActiveProcessStop

kernel32.GetLastError

kernel32.GetCurrentProcessId

kernel32.SetErrorMode

kernel32.LocalFree

ntdll_12.RtlInitializeCriticalSection

ntdll_12.RtlEnterCriticalSection

ntdll_12.RtlLeaveCriticalSection

kernel32.WaitForSingleObject

kernel32.FlushFileBuffers

kernel32.GetCurrentThreadId

kernel32.QueryDosDeviceW

kernel32.QueryFullProcessImageNameW

kernel32.GetModuleHandleW

kernel32.CreateEventW

kernel32.OpenEventW

kernel32.SetEvent

kernel32.CreateMutexW

kernel32.OpenMutexW

kernel32.ReleaseMutex

advapi32.GetCurrentHwProfileW

advapi32.OpenSCManagerW

advapi32.EnumServicesStatusW

advapi32.OpenServiceW

advapi32.EnumDependentServicesW

advapi32.ControlService

advapi32.CloseServiceHandle

advapi32.QueryServiceStatusEx

advapi32.RegOpenKeyExW

advapi32.RegCreateKeyExW

advapi32.RegSetValueExW

advapi32.RegQueryValueExW

advapi32.RegDeleteKeyExW

advapi32.RegDeleteKeyW

advapi32.RegDeleteValueW

advapi32.RegFlushKey

advapi32.RegCloseKey

advapi32.LookupPrivilegeValueW

advapi32.AdjustTokenPrivileges

advapi32.DuplicateTokenEx

advapi32.CreateProcessAsUserW

advapi32.RevertToSelf

advapi32.ImpersonateLoggedOnUser

advapi32.GetTokenInformation

advapi32.ConvertSidToStringSidW

advapi32.IsWellKnownSid

user3 2.GetKeyboardLayoutList

mpr.WNetOpenEnumW

mpr.WNetEnumResourceW

mpr.WNetUseConnectionW

mpr.WNetAddConnection2W

mpr.WNetGetUniversalNameW

mpr.WNetCloseEnum

shell32.SHGetFolderPathW

shell32.ShellExecuteW

srvcli.NetShareEnum

netutils.NetApiBufferFree

ole32.CoInitializeEx

ole32.CoUninitialize

ole32.CoCreateInstance

ole32.CoInitializeSecurity

oleaut32.SysAllocString

oleaut32.SysFreeString

psapi.GetModuleFileNameExW

此勒索软件的函数全部被加密存放在内存中,在执行的时候解密调用,主要是为了阻止安全研究人员对样本进行静态分析。样本首次被发现,只有一款杀毒引擎检测出来恶意的,如下所示。

1599478878.png!small

一周过去了,也只有15款杀毒引擎能检测,其中只有微软提取了相应的病毒特征名,识别为NetWalker勒索病毒,如下。

1599478896.png!small

之所以检测不出来,主要是由于第一样本使用了PowerShell脚本进行无文件加载payload,同时payload样本的导入表被全被加密,没有了导入表,导致样本无法检测。

针对于这种API全部采用动态导入的方式加载,IDA中可以自建结构体进行优化分析结果,如下。

1599478929.png!small

1599478933.png!small

接着发现没有调用诸如GetModuleHandle的API函数来获取当前程序加载地址,而是对其地址每次减去0x800后比较是否存在PE标记头“MZ”,从而来获取当前PE文件实际内存加载地址(基址),此处避免了敏感API函数调用。

1599478962.png!small

后续会寻找资源,资源大小为0x149C(5726)个字节。

1599478987.png!small

1599478991.png!small

1599478995.png!small

资源开头前4个字节为密钥的长度,后四个字节为密钥,经分析后续采用RC 4算法解密资源,密钥为”]ZRW”。

1599479105.png!small

1599479115.png!small

最终内存解密出的勒索配置信息,如下。

{

"mpk": "JgQzhhhjdTmwJuFlSWQ99dolV6sNRQWfNdqTbxulxCc=",

"mode": 0,

"spsz": 15360,

"thr": 1500,

"namesz": 8,

"idsz": 6,

"pers": true,

"onion1": "pb36hu4spl6cyjdfhing7h3pw6dhpk32ifemawkujj4gp33ejzdq3did.onion",

"onion2": "rnfdsgm6wb6j6su5txkekw4u4y47kp2eatvu7d6xhyn5cs4lt4pdrqqd.onion",

"lfile": "{id}-Readme.txt",

"lend": "SGkhDQpZb3VyIGZpbGVzIGFyZSBlbmNyeXB0ZWQgYnkgTmV0d2Fsa2VyLg0KQWxsIGVuY3J5cHRlZCBmaWxlcyBmb3IgdGhpcyBjb21wdXRlciBoYXMgZXh0ZW5zaW9uOiAue2lkfQ0KDQotLQ0KSWYgZm 9yIHNvbWUgcmVhc29uIHlvdSByZWFkIHRoaXMgdGV4dCBiZWZvcmUgdGhlIGVuY3J5cHRpb24gZW5kZWQsDQp0aGlzIGNhbiBiZSB1bmRlcnN0b29kIGJ5IHRoZSBmYWN0IHRoYXQgdGhlIGNvbXB1dGVyIHNsb3dzIGRvd24sDQphbmQgeW91ciBoZWFydCByYXRlIGhhcyBpbmNyZWFzZWQgZHVlIHRvIHRoZSBhYmlsaXR5IHRvIHR1cm4gaXQgb2ZmLA0KdGhlbiB3ZSByZWNvbW1lbmQgdGhhdCB5b3UgbW92ZSBhd2F5IGZyb20gdGhlIGNvbXB1dGVyIGFuZCBhY2NlcHQgdGhhdCB5b3UgaGF2ZSBiZWVuIGNvbXByb21pc2VkLg0KUmVib290aW5nL3NodXRkb3duIHdpbGwgY2F1c2UgeW91IHRvIGxvc2UgZmlsZXMgd2l0aG91dCB0aGUgcG9zc2liaWxpdHkgb2YgcmVjb3ZlcnkuDQoNCi0tDQpPdXIgIGVuY3J5cHRpb24gYWxnb3JpdGhtcyBhcmUgdmVyeSBzdHJvbmcgYW5kIHlvdXIgZmlsZXMgYXJlIHZlcnkgd2VsbCBwcm 90ZWN0ZWQsDQp0aGUgb25seSB3YXkgdG8gZ2V0IHlvdXIgZmlsZXMgYmFjayBpcyB0byBjb29wZXJhdGUgd2l0aCB1cyBhbmQgZ2V0IHRoZSBkZWNyeXB0ZXIgcHJvZ3JhbS4NCg0KRG8gbm 90IHRyeSB0byByZWNvdmVyIHlvdXIgZmlsZXMgd2l0aG91dCBhIGRlY3J5cHRlciBwcm 9ncmFtLCB5b3UgbWF5IGRhbWFnZSB0aGVtIGFuZCB0aGVuIHRoZXkgd2lsbCBiZSBpbXBvc3NpYmxlIHRvIHJlY292ZXIuDQoNCkZvciB1cyB0aGlzIGlzIGp1c3QgYnVzaW5lc3MgYW5kIHRvIHByb3ZlIHRvIHlvdSBvdXIgc2VyaW91c25lc3MsIHdlIHdpbGwgZGVjcnlwdCB5b3Ugb25lIGZpbGUgZm 9yIGZyZWUuDQpKdXN0IG9wZW4gb3VyIHdlYnNpdGUsIHVwbG9hZCB0aGUgZW5jcnlwdGVkIGZpbGUgYW5kIGdldCB0aGUgZGVjcnlwdGVkIGZpbGUgZm 9yIGZyZWUuDQoNCi0tDQoNClN0ZXBzIHRvIGdldCBhY2Nlc3Mgb24gb3VyIHdlYnNpdGU6DQoNCjEuRG93bmxvYWQgYW5kIGluc3RhbGwgdG9yLWJyb3dzZXI6IGh0dHBzOi8vdG9ycHJvamVjdC5vcmcvDQoNCjIuT3BlbiBvdXIgd2Vic2l0ZToge29uaW9uMX0NCklmIHRoZSB3ZWJzaXRlIGlzIG5vdCBhdmFpbGFibGUsIG9wZW4gYW5vdGhlciBvbmU6IHtvbmlvbjJ9DQoNCjMuUHV0IHlvdXIgcGVyc29uYWwgY29kZSBpbiB0aGUgaW5wdXQgZm 9ybToNCg0Ke2NvZGV9",

"white": {

"path": ["*system volume information", "*windows.old", "*:users**temp", "*msocache", "*:winnt", "*$windows.~ws", "*perflogs", "*boot", "*:windows", "*:program file*vmware", "\*users**temp", "\*winnt", "\*windows", "*program file*vmware", "*appdata*microsoft", "*appdata*packages", "*microsoftprovisioning", "*dvd maker", "*Internet Explorer", "*Mozilla", "*Mozilla*", "*Old Firefox data", "*program file*windows media*", "*program file*windows portable*", "*windows defender", "*program file*windows nt", "*program file*windowsphoto*", "*program file*windows side*", "*program file*windowsPowerShell", "*program file*cuass*", "*program file*microsoft games", "*program file*common filessystem", "*program file*common files*shared", "*program file*common filesreference ass*", "*windowscache*", "*temporary internet*", "*media player", "*:users*appdata*microsoft", "\*users*appdata*microsoft", "*Program File*Cisco"],

"file": ["ntuser.dat*", "iconcache.db", "gdipfont*.dat", "ntuser.ini", "usrclass.dat", "usrclass.dat*", "boot.ini", "bootmgr", "bootnxt", "desktop.ini", "ntuser.dat", "autorun.inf", "ntldr", "thumbs.db", "bootsect.bak", "bootfont.bin"],

"ext": ["msp", "exe", "sys", "msc", "mod", "clb", "mui", "regtrans-ms", "theme", "hta", "shs", "nomedia", "diagpkg", "cab", "ics", "msstyles", "cur", "drv", "icns", "diagcfg", "dll", "ocx", "lnk", "ico", "idx", "ps1", "mpa", "cpl", "icl", "msu", "msi", "nls", "scr", "adv", "386", "com", "hlp", "rom", "lock", "386", "wpx", "ani", "prf", "rtp", "ldf", "key", "diagcab", "cmd", "spl", "deskthemepack", "bat", "themepack"]

},

"kill": {

"use": true,

"prc": ["nslsvice.exe", "pg*", "nservice.exe", "cbvscserv*", "ntrtscan.exe", "cbservi*", "hMailServer*", "IBM*", "bes10*", "black*", "apach*", "bd2*", "db*", "ba*", "be*", "QB*", "oracle*", "wbengine*", "vee*", "postg*", "sage*", "sap*", "b1*", "fdlaunch*", "msmdsrv*", "report*", "msdtssr*", "coldfus*", "cfdot*", "swag*", "swstrtr*", "jetty.exe", "wrsa.exe", "team*", "agent*", "store.exe", "sql*", "sqbcoreservice.exe", "thunderbird.exe", "ocssd.exe", "encsvc.exe", "excel.exe", "synctime.exe", "mspub.exe", "ocautoupds.exe", "thebat.exe", "dbeng50.exe", "*sql*", "mydesktopservice.exe", "onenote.exe", "outlook.exe", "powerpnt.exe", "msaccess.exe", "tbirdconfig.exe", "wordpad.exe", "ocomm.exe", "dbsnmp.exe", "thebat64.exe", "winword.exe", "oracle.exe", "xfssvccon.exe", "firefoxconfig.exe", "visio.exe", "mydesktopqos.exe", "infopath.exe", "agntsvc.exe"],

"svc": ["Lotus*", "veeam*", "cbvscserv*", "hMailServer", "backup*", "*backup*", "apach*", "firebird*", "ibmiasrw", "IBM Domino*", "Simply Accounting Database Connection Manager", "IASJet", "QB*", "*sql*", "sql*", "QuickBooksDB*", "IISADMIN", "omsad", "dc*32", "server Administrator", "wbengine", "mr2kserv", "MSExchange*", "ShadowProtectSvc", "SP*4", "teamviewer", "MMS", "AcronisAgent", "ARSM", "AcrSch2Svc", "vsnapvss", "SPXService", "StorageCraft ImageManager", "wrsvc", "stc_endpt_svc", "acrsch2svc*"],

"svcwait": 0,

"task": ["reboot", "restart", "shutdown", "logoff", "back"]

},

"net": {

"use": true,

"ignore": {

"use": true,

"disk": true,

"share": ["ipc$", "admin$"]

}

},

"unlocker": {

"use": true,

"ignore": {

"use": true,

"pspath": ["*:windows*", "*:winnt*", "*:program file*vmwar*", "*Program File*Fortinet", "*Program File*Cisco"],

"prc": ["psexec.exe", "system", "forti*.exe", "fmon.exe", "fcaptmon.exe", "FCHelper64.exe"]

}

}

}




经过解密后得到的配置内容,后续会进行使用,达到最终加密目的。从解密得到的配置信息来看,我们可以发现mpk很有可能为公钥(public key),如下是存在不加密的白名单列表。




路径有:["*system volume information", "*windows.old", "*:users**temp", "*msocache", "*:winnt", "*$windows.~ws", "*perflogs", "*boot", "*:windows", "*:program file*vmware", "\*users**temp", "\*winnt", "\*windows", "*program file*vmware", "*appdata*microsoft", "*appdata*packages", "*microsoftprovisioning", "*dvd maker", "*Internet Explorer", "*Mozilla", "*Mozilla*", "*Old Firefox data", "*program file*windows media*", "*program file*windows portable*", "*windows defender", "*program file*windows nt", "*program file*windowsphoto*", "*program file*windows side*", "*program file*windowsPowerShell", "*program file*cuass*", "*program file*microsoft games", "*program file*common filessystem", "*program file*common files*shared", "*program file*common filesreference ass*", "*windowscache*", "*temporary internet*", "*media player", "*:users*appdata*microsoft", "\*users*appdata*microsoft", "*Program File*Cisco"]




文件有:["ntuser.dat*", "iconcache.db", "gdipfont*.dat", "ntuser.ini", "usrclass.dat", "usrclass.dat*", "boot.ini", "bootmgr", "bootnxt", "desktop.ini", "ntuser.dat", "autorun.inf", "ntldr", "thumbs.db", "bootsect.bak", "bootfont.bin"]




扩展名有:["msp", "exe", "sys", "msc", "mod", "clb", "mui", "regtrans-ms", "theme", "hta", "shs", "nomedia", "diagpkg", "cab", "ics", "msstyles", "cur", "drv", "icns", "diagcfg", "dll", "ocx", "lnk", "ico", "idx", "ps1", "mpa", "cpl", "icl", "msu", "msi", "nls", "scr", "adv", "386", "com", "hlp", "rom", "lock", "386", "wpx", "ani", "prf", "rtp", "ldf", "key", "diagcab", "cmd", "spl", "deskthemepack", "bat", "themepack"]

具体的内容不再描述,每个配置项的目的很明确,可自行查看配置内容。

经分析发现后续会对 “mpk”: “JgQzhhhjdTmwJuFlSWQ99dolV6sNRQWfNdqTbxulxCc=” 值base64解码后进行crc32计算得到crc32值进行校验,校验通过后经base64解码之后会使用SHA256对其计算得到hash值。

1599479141.png!small

lend字段值,经base64解码后得到勒索信模板,如下。

1599479157.png!small

经过一段uuid数据(实质为本地获取的SIP安全标识符)与mpk解码后的数据拼接,再进行SHA256输出得到hash。转换为十六进制字符后得到”a219b2b56bd53d644b6fa610f0db829243bf8cc3234fc67769f2e276e58b7018″,后续会使用该段内容。

1599479178.png!small

后续加密密钥的产生过程会调用RtlRandomEx,前期的话这里使用的是ZwQuerySystemTime来得到当前系统时间作为种子从而来迭代产生随机数拼接成32个字节长度的数据。查询后发现ZwQuerySystemTime函数返回的是自1601年1月1日以来,每100纳秒间隔的数量。

由于RtlRandomEx为伪随机数生成函数,所以固定的种子会产生固定的随机值,由于存在一定的缺陷,假如后续核心勒索使用的是同一个密钥加密全部文件,那么我们可以利用这个缺陷来反推得到密钥,但是经后续分析,发现并不是。不过,我们依然可以反推出该处密钥产生过程的流程,自行模拟编写得到的demo源码如下。

#include<windows.h>
#include<cstdio>
typedef NTSYSAPI ULONG RtlRandomEx(
       PULONG Seed
       );
typedef NTSTATUS ZwQuerySystemTime
(
       LARGE_INTEGER* time
       );
int main()
{
       LARGE_INTEGER now;
       RtlRandomEx* rand = (RtlRandomEx*)GetProcAddress(GetModuleHandle(L"ntdll"), "RtlRandomEx");
       ZwQuerySystemTime* MyQuerySystemTime = (ZwQuerySystemTime*)GetProcAddress(GetModuleHandle(L"ntdll"), "ZwQuerySystemTime");
       MyQuerySystemTime(&now);
       ULONG seed_now = now.LowPart;
       printf("0x%Xn", now);
       printf("0x%Xn", seed_now);
       ULONG rand_value = rand(&seed_now);
       printf("%X", (rand_value % 256));
       for (int i = 0; i < 31; i++)
       {
              ULONG new_seed_now = rand_value;
              ULONG rand_value = rand(&new_seed_now);
              printf("%X", (rand_value % 256));
       }
       return 0;
}

1599479305.png!small

1599479344.png!small

后续还会继续产生32个字节长度的随机数据,同样也会继续调用RtlRandomEx,使用ZwQuerySystemTime得到当前系统时间作为种子产生随机数拼接成32个字节长度的数据。

1599479361.png!small

1599479372.png!small

在对加密密钥进行加密的流程里,经分析黑客采用的是curve25519加密,如图选中区域。经查询发现curve25519 是目前最高水平的 Diffie-Hellman函数,在密码学中,Curve25519是一个椭圆曲线提供128位安全性,设计用于椭圆曲线Diffie-Hellman(ECDH)密钥协商方案。它是最快的ECC曲线之一,并未被任何已知专利所涵盖。这里猜测黑客为了防止RSA加密方案的后续不安全性,进而采用了ECC椭圆曲线的加密算法来对加密密钥进行加密保护。同样,我们可以从解密的勒索配置内容中得到原始的未被后续处理的公钥mpk,但由于没有黑客的私钥,所以理论上我们无法进行解密。

1599479396.png!small

公钥为mpk字段值内容,如下是实际加密流程。

1599479465.png!small

经后续分析加密文件采用的是salsa20 32字节(256位)密钥长度进行加密,该处salsa20算法的密钥key为之前上面被加密的数据经sha256后进一步处理得到的值。

1599479486.png!small

之前经过salsa20与sha256以及curve25519加密后得到的相关数据会被拼接产生一个数据块,大小为108个字节,如下。

1599479502.png!small

数据块再次被处理后,会创建注册表项直接写入。

1599479537.png!small

1599479542.png!small

1599479546.png!small

当下次再次运行时,被加密文件的扩展名的前6个字符会依然为a219b2,保存的是之前组合拼接并被加密的数据块。

1599479565.png!small

1599479574.png!small

勒索信的文件名生成格式,id值来源于之前随机产生的32个字节长度的十六进制内容的前6个字符。

1599479594.png!small

之后产生勒索信中的用户代码内容,以及勒索信内容。

F/E74FlVhO8UTlvHhfqrWTdDUsUieV9ORLkBrnWdttIzRhtZmCxWKGOg0+tNDaeAKt9iwvUY1CzN5u9LgHvUR9sA2lBu4kFO65Yyi7ZisEeA2L8Wpm3EWjXibuA9jsb6Zah5x/wsSy6umv9PopmCuEofskuhPkpQ5Oc5DCYHpDCIvAxyh4qCYrtsvcMF5RzOUWsoibwnubiZctWKNIS7EbWdkaDTrpAInkUH689lquDzoxjhP+tbRRRo2jov4ZYSHMRM6GL08AqTM//rIvPX+aqZoG8CMkpcg==

1599479614.png!small

最后会进入文件加密流程,在进程注入阶段前会采用SeImpersonatePrivilege与SetPrivilege来进行权限提升。

1599479636.png!small

由于文件所属的用户权限存在差异,为了最大限度加密文件成功,会模拟其余用户token认证登录。

1599479653.png!small

第一次遍历进程,通过计算crc32值进行比较得到需要注入的进程名,接着开始注入,会注入到explorer.exe进程。

1599479683.png!small

1599479687.png!small

1599479691.png!small

1599479694.png!small

1599479698.png!small

1599479701.png!small

利用token模拟技术来提升权限,便于后续进行一些需要特定权限的操作。

1599479715.png!small

注入完后,恢复线程,实质分析环境下,注入是失败的,估计是一个功能未完善的勒索。

1599479729.png!small

之后通过API函数获取磁盘类型,找到可用盘符,为之后的文件遍历做准备,如下。

1599479745.png!small

设置完线程所需的临界区后,经分析后发现会存在3个主线程,如下。

1599479839.png!small

开启第一个主线程1000A560,此时针对是C盘符,之后每个盘符都相应开启一个线程,每个文件与文件夹都开启同样的线程,从设计上该勒索的加密效率很高。

1599479932.png!small

1599479946.png!small

1599479951.png!small

进入sub_1000A560线程内部后,加密流程开始,首先遍历文件,搜索文件。1599528273.png!small

文件加密流程如下,递归创建加密线程。

1599528301.png!small

1599528305.png!small

针对未加密完成的文件,核心勒索再次运行时会进行文件内容核查,检查文件末尾的最后4个字节来判断是否需要再次加密。

1599528329.png!small

1599528333.png!small

1599528336.png!small

主线程遍历完找到所需的文件后,开始打开文件。

1599528355.png!small

加密前的文件内容,如下。

1599528372.png!small

加密后的文件内容,如下。

1599528383.png!small

实际文件加密流程如下,会采用salsa20算法加密。

1599528395.png!small

文件末尾会再次写入108个字节数据,实质包含被curve25519加密过的salsa20的加密密钥。

1599528411.png!small

之后产生的新的文件名后缀,进行改名。

1599528431.png!small

后续经分析,该勒索针对每一个文件都采用不同的加密密钥进行加密。

1599528440.png!small

1599528455.png!small

1599528458.png!small

1599528462.png!small

产生不同的加密密钥来源于之前调用过的RtlRandomEx,这里会使用NtQuerySystemTime得到当前系统时间作为种子来迭代产生随机数拼接成32个字节长度的数据,由于每个文件都是不同的加密密钥,即使使用了存在一定缺陷的随机数来产生密钥,但是整体上来看解密复杂度提升了很多。

1599528479.png!small由于采用了递归形式的多线程结构,运行时开启的线程数会达到上千数量。

1599528521.png!small

在每个文件夹下都会释放xxxxxx-ReadMe.txt的勒索信

1599528528.png!small

由于针对每个文件的加密密钥不同, 所以文件末尾附加的数据也是不同的。

1599528536.png!small

1599528540.png!small

流程图

1599528556.png!small

勒索追踪

经上面的分析可知由于在进程注入流程中采用的payload为x86架构,所以对于目前大多数为64位系统来说注入是会失败的,在适配方面存在不足,所以可以判定该勒索目前还处于积极开发阶段,之后经追踪发现,该勒索已经更新并增加了x64模块,对于新出现的PowerShell脚本对比之前的脚本发现,整体执行流程没有改变,对其去混淆后,发现在恶意文件数据区域存在了针对x64环境的payload,提取后分析发现同样无任何导入表,经本地运行后可成功加密文件,目前该勒索已经适配成功。

1599528588.png!small

1599528591.png!small

1599528595.png!small

1599528598.png!small

1599528602.png!small

威胁情报

HASH

8336572266de59a362177d39dfd212be

1b6a2bfa39bcc335b1aff8217fe9e05f

0e81df6fb8c 469afed2208cee0f6ec8c

9fb87ac9c00ea780bad678cb5bde676c

809a76a64875aeede09f7db28a2333a9

解决方案

深信服下一代防火墙AF、终端检测响应平台EDR、安全感知平台SIP等安全产品均能有效检测防御此恶意软件,已经部署相关产品的用户可以进行安全扫描,检测清除此恶意软件,如图所示:

1599528621.png!small

来源:freebuf.com 2020-09-08 09:37:24 by: 深信服千里目安全实验室

© 版权声明
THE END
喜欢就支持一下吧
点赞0
分享
评论 抢沙发

请登录后发表评论