作者: Yenn_
原文链接: Wei's Blog
Turla,也被称为Venomous Bear、Waterbug和Uroboros,是迄今为止最为高级的威胁组织之一,并被认为隶属于俄罗斯政府(该组织成员均说俄语)。虽然该组织被认为至少在2007年就已经成立,但直到2014年它才被卡巴斯基实验室发现。
File Name | File Size | File Type | MD5 |
---|---|---|---|
DebugView.exe | 137,728 Byte | BackDoor | 277f2d8e682f7ffc071560f44af4ab41 |
样本似乎伪造为Windows下的SysInternal套件
样本内的类和函数命名都是由两位字符组成
设置样本中的异常处理,将异常发送到ThreadException
通过字符串“”gGYJ\YwJ1sggs1YBg31GjGg14\dd0d}w}ds4””解密出一串GUID
“169739e7-2112-9514-6a61-d300c0fef02d”
根据Gethostid返回的值与13取余,根据余数来决定在哪个文件夹释放创建新文件夹释放文件,在这里取到的路径为“C:\Users\sam\AppData\Local\Microsoft\Network\3DDC94D8”,得到路径后创建文件夹
获取计算机信息、解密加载出后续操作使用的内容,并通过前面解密出的”169739e7-2112-9514-6a61-d300c0fef02d”创建一个新GUID
创建互斥量,互斥量都是由Username+固定字符串解密内容,根据UserName不同,生成的互斥量也不同,格式为Global\+生成的与GUID同一格式的内容
在文件夹“C:\Users\sam\AppData\Local\Microsoft\Network\3DDC94D8\3F515151”创建文件,写入程序运行的日志,写入的日志由Rijndael加密,KEY值由当前时间计算得出,通过KEY与文件的内容可以解密出样本的日志文件
加密:
判断样本运行状态,进行不同的操作,主入口点有4种不同的路径:
调试过程中进入了流程3,样本先提权到SeDebugPrivilege权限
为Shell_TrayWnd窗口设置WindowsHook,注入DLL到explorer.exe中
注入后的explorer.exe
在explorer.exe中注入的DLL实际是一个CLR RUNTIME LOADER,负责加载执行先前样本中的内容
类似样本中CLR Runtime Loader的源码,加载CLR Runtime到Target中执行
__declspec(dllexport) HRESULT LoadDNA(_In_ LPCTSTR lpCommand) {
HRESULT hr;
ICLRMetaHost * pMetaHost = NULL;
ICLRRuntimeInfo * pRuntimeInfo = NULL;
ICLRRuntimeHost * pClrRuntimeHost = NULL;
// Load .NET Runtime
hr = CLRCreateInstance(CLSID_CLRMetaHost, IID_PPV_ARGS( & pMetaHost));
hr = pMetaHost - >GetRuntime(L "v4.0.30319", IID_PPV_ARGS( & pRuntimeInfo));
hr = pRuntimeInfo - >GetInterface(CLSID_CLRRuntimeHost, IID_PPV_ARGS( & pClrRuntimeHost));
// Start Runtime
hr = pClrRuntimeHost - >Start();
// Parse Arguments
ClrLoaderArgs args(lpCommand);
// Execute Loaded .NET Code
DWORD pReturnValue;
hr = pClrRuntimeHost - >ExecuteInDefaultAppDomain(
args.pwzAssemblyPath.c_str(),
args.pwzTypeName.c_str(),
args.pwzMethodName.c_str(),
args.pwzArgument.c_str(),
&pReturnValue);
// Release and Free Resources
pMetaHost - >Release();
pRuntimeInfo - >Release();
pClrRuntimeHost - >Release();
// Return .NET Code Result
return hr;
}
加载完成后执行流程又回到了DbgView.exe中,调用了dbgview中的W.s()方法
设置异常处理
查询当前的进程名是否为被注入的进程,可以看出程序会注入的程序包含“iexplore”,”firefox”,”browser”,”outlook”,”chrome”,”nlnotes”,”notes2”,”opera”,”msimn”
根据查询的结果会创建不同的线程
当注入的不是上述进程时:
与样本最开始相同会查询系统信息,然后尝试持久化操作,但在调试过程中创建自启动没有成功,返回字符串“DISABLE”,尝试的注册表路径
或尝试添加自启动.lnk到启动目录
创建了一个IPC远程通道
“ipc://5728912222233c6860fe9a5a2ae45a7e/d22f298e18a16a3175ea1a78b5419c91”
从样本向日志中写入的内容来看,样本将C2下发的命令操作称为”Task”
功能还带有注入到其他进程中的功能
当当前进程为“iexplore”,”firefox”,”browser”,”outlook”,”chrome”,”nlnotes”,”notes2”,”opera”,”msimn”时
尝试与C2链接,C2的地址由
“C:\Users\sam\AppData\Local\Microsoft\Network"下文件取出,当文件不存在时,样本还存在default server
解密出的两个Default Server:
“https://www.bombheros.com/wp-content/languages/index.php" “https://www.simplifiedhomesales.com/wp-includes/images/index.php"
与C2通信支持的协议类型包含”http”.”https”,”ftp”,”ftps”
查询窗口,检测抓包软件,包括
“megadumper”,”smartsniff”,”snoopypro”,”wireshark”,”ethereal”,”tcpview”,”tcpdump”,”windump”,”portmon”,”dsniff”,
向C2发送HTTP请求,cookie字段为GUID的base64编码,用于标识被感染主机
Action ID | Commands | Description |
---|---|---|
1 | log | Logs a specified debug message |
2 | get | Upload files from a specified directory. It appears the actor can specify which files to upload based on their modified, accessed and created timestamps as well. |
3 | put | Writes provided data (referred to as ‘payload’) to a specified file on the system. |
4 | cmd | Executes a specified command and writes the output to a temporary file. The temporary file is uploaded to the C2 server |
5 | sleep | Trojan sleeps for a specified time |
6 | upgrade | Upgrades the Trojan by changing the current executable’s file extension to “.old” and writing a newly provided executable in its place |
7 | scrshot | Takes a screenshot of the entire visible screen. The screenshot is saved to a specified filename or using a filename with the following format: [year]-[month]-[day]-[hour]-[minute]-[second]-[milisecond].jpg. The file is uploaded to the C2 server |
8 | camshot | Creates a Window called “WebCapt” to capture an image from an attached webcam, which it copies to the clipboard and writes to a specified file or a file following the same format from the “scrshot” command. The file is uploaded to the C2 server |
9 | uuid | Sets the unique agent identifier by providing a specific GUID |
10 | interval | Sets the transport intervals, specifically the minimum and maximum time intervals between C2 communications. |
11 | server | Sets the C2 servers by providing a list of URLs |
12 | transport | Sets the transport processes by providing a list of processes that Kazuar will inject its code and execute within. |
13 | autorun | Sets the autorun type as discussed earlier in this blog. Kazuar will accept the following strings for this command: DISABLED, WINLOGON, POLICIES, HKCURUN, RUNONCE, LOADKEY, STARTUP |
14 | remote | Sets a remote type. We are only aware of one remote type that instructs Kazuar to act as an HTTP server and allow the threat actor to interact with the compromised system via inbound HTTP requests. |
15 | info | Gathers system information, specifically information referred to as: Agent information, System information, User information, Local groups and members, Installed software, Special folders, Environment variables, Network adapters, Active network connections, Logical drives, Running processes and Opened windows |
16 | copy | Copies a specified file to a specified location. Also allows the C2 to supply a flag to overwrite the destination file if it already exists. |
17 | move | Moves a specified file to a specified location. Also allows the C2 to supply a flag to delete the destination file if it exists. |
18 | remove | Deletes a specified file. Allows the C2 to supply a flag to securely delete a file by overwriting the file with random data before deleting the file. |
19 | finddir | Find a specified directory and list its files, including the created and modified timestamps, the size and file path for each of the files within the directory. |
20 | kill | Kills a process by name or by process identifier (PID) |
21 | tasklisk | List running processes. Uses a WMI query of “select * from Win32_Process” for a Windows system, but can also running “ps -eo comm,pid,ppid,user,start,tty,args” to obtain running processes from a Unix system. |
22 | suicide | We believe this command is meant to uninstall the Trojan, but it is not currently implemented in the known samples. |
23 | plugin | Installing plugin by loading a provided Assembly, saving it to a file whose name is the MD5 hash of the Assembly’s name and calling a method called “Start”. |
24 | plugout | Removes a plugin based on the Assembly’s name. |
25 | pluglist | Gets a list of plugins and if they are “working” or “stopped” |
26 | run | Runs a specified executable with supplied arguments and saves its output to a temporary file. The temporary file is up loaded to the C2 server. |
“https://www.bombheros.com/wp-content/languages/index.php" “https://www.simplifiedhomesales.com/wp-includes/images/index.php"
参考链接:
2.https://unit42.paloaltonetworks.com/unit42-kazuar-multiplatform-espionage-backdoor-api-access/
3.https://www.epicturla.com/blog/sysinturla
伪造为Windows下Sysinternas组件中的DebugView
流程与前面Kazuar backdoor - e888b93f4d5f28699b29271a95ccad55ca937977d442228637ad9a7c037d3a6a4相同,不过这次样本使用了ConfuserEX混淆字符串,通过工具可以直接解出明文,而前面样本中使用了自定义的加密方法,在使用字符串时通过解密。
通过工具反混淆后可直接查看明文字符串:
同样通过在”Shell_TrayWnd”设置HOOK
释放一个DLL文件在%appdata%..\Local\随机名目录下,释放的DLL同样是一个CLR Runtime Loader
在explorer.exe的进程中可以看见.NET Assemblies中CLR下的样本进程
释放出的DLL的混淆代码部分,干扰IDA的F5
在Explorer.exe中加载MainClass中的EntryPoint
判断是否注入在当前进程下:
创建IPC通道
监听HTTP请求
同样的命令执行,26条指令与前面相同
样本与Kazuar backdoor -e888b93f4d5f28699b29271a95ccad55ca937977d442228637ad9a7c037d3a6a4手法一致,在混淆中使用了ConfuserEX,反混淆后可以直接显示明文字符串,在样本e888b93f4d5f28699b29271a95ccad55ca937977d442228637ad9a7c037d3a6a4中则使用了自定义的加密方法,将字符串隐藏。在C2链接过程中,样本并没有设置自己的Default Server
样本执行流程相同,不使用ConfuserEX混淆字符串,使用自定义的算法混淆,没有C2时使用样本自带的Default C2 Server
https://afci-newsoft.fr/wp-content/stmoptimize/optimize.php
https://aviatnetworks.com/wp-includes/images/index.php
https://www.citiquartz.com/wp-includes/fonts/icons/
97022ee2f998b4a94f0fc2
File Name | File Size | File Type | MD5 |
---|---|---|---|
611,328 Byte | Dropper | a6efd027b121347201a3de769389e6dd |
样本伪造为Windows系统文件,原始文件名为ESCEBIN.EXE,但是实际上确实一个DLL文件
通过调用RegOpenKey对
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Windows的访问来查询当前是否为管理员权限,当不是管理员的时候会格式化一串字符串“Why the fu*k not?”,然后退出进程
尝试遍历%Systemroot%\inf文件夹下所有.inf文件,查询键名“DestinationDirs”
判断Windows系统版本
格式化字符串
遍历C:\Program Files下所有文件,尝试遍历“windowsapps”文件夹,当不存在时会生成一个随机数,从C:\Program Files下随机取一个文件夹,然后进行创建文件的测试
读取资源中类型为“BINRARY“,资源名称为“#203”的资源,解密后写入到前面进行写文件测试的文件夹
修改写入文件的时间为前面获取的explorer的Last Write Time
重复上面的操作,从资源中解密出3个DLL文件
创建一个名为“Alerter”的自启动服务
查询注册表
“HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Svchost下值“netsvcs”的数据,并用查询到的内容来对比创建的服务“Alerter”是否在其中
创建注册表“HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Alerter\Parameters”,并添加三项注册表值,将ServiceDLL修改为%System32%下的alrsvc.dll,alrsvc.dll从资源“#161”中解密释放
修改了注册表HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Alerter\Parameters的ServiceDLL的值为alrsvc.dll,所以在下次服务启动时,会加载起来释放出的alrsvc.dll
注册函数“Service”处理控制请求,创建新线程遍历”C:\Windows\INF\“下所有.inf文件
将前面Carbon Installer 释放的文件移动到文件夹”C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\RedistList”
利用当前alrsvc.dll加载其中的sacril.dll,调用函数”OnDemandStart”
释放出的四个文件,应该为Carbon主体、两个通讯模块DLL、一个配置文件。Carbon运行中从配置文件解密出配置信息,包括C2地址也在配置文件中。
sacril.dll为Carbon的主体文件
创建了大量的互斥体
MUTEX | |
---|---|
Global\StopDeskIntel | Global\StickLowDrop |
Global\Open.Locked.Session.MBP | Global\NE_full_block_clone |
Global{5279C310-CA22-EAA1-FE49-C3A6A22AFC82} | Global\Central.Orchestrator.E |
Global\ViHyperCPrompt |
在前阶段Drop文件的目录“C:\Program Files\Reference Assemblies\Microsoft\Framework\v3.0\RedistList”下拼接出大量的路径
在新建的文件夹\1033下创建一个dbr4as.lte文件,在其中写入日志文件,写入后立马对日志文件进行加密
加密前:
加密后:
在样本执行过程中会将配置文件解密,样本执行的操作都来自于配置文件estdlawf.fes。
Carbon解密后的的配置文件:
[NAME]
object_id=APCA1lABkYnaL4eoNL07VAAlmu
iproc = iexplore.exe,outlook.exe,msimn.exe,firefox.exe,opera.exe,chrome.exe,browser.exe,nlnotes.exe,notes2.exe,spotify.exe,adobeupdater.exe,adobearm.exe,jusched.exe,thunderbird.exe
ex = #,netscape.exe,mozilla.exe,adobeupdater.exe,chrome.exe
[TIME]
user_winmin = 2400000
user_winmax = 3600000
sys_winmin = 3600000
sys_winmax = 3700000
task_min = 20000
task_max = 30000
checkmin = 60000
checkmax = 70000
logmin = 60000
logmax = 120000
lastconnect=111
timestop=
active_con = 900000
time2task=3600000
[CW_LOCAL]
quantity = 0
[CW_INET]
quantity = 2
address1 = www.berlinguas.com:443:/wp-content/languages/index.php
address2 = www.balletmaniacs.com:443:/wp-includes/fonts/icons/
[TRANSPORT]
system_pipe = suplexrpc
spstatus = yes
adaptable = no
[RENDEZVOUS_POINT]
quantity = 1
address1 = pastebin.com:443:/raw/5qXBPmAZ
[DHCP]
server = 135
[LOG]
logperiod = 7200
[WORKDATA]
run_task=
run_task_system=
其中可以清晰的发现PIPE名”suplexrpc”与三个地址
www.berlinguas.com:443:/wp-content/languages/index.php
www.balletmaniacs.com:443:/wp-includes/fonts/icons/
pastebin.com:443:/raw/5qXBPmAZ
Carbon还包含一个日志文件,日志的格式为日期|时间|受害者id|源|消息
[LOG]
start=1
20/02/17|12:48:24|8hTdJtUBB57ieReZAOSgUYacts|s|OPER|New object ID generated '8hTdJtUBB57ieReZAOSgUYacts'|
20/02/17|12:48:24|8hTdJtUBB57ieReZAOSgUYacts|s|ST|3/81|0|
20/02/17|12:48:24|8hTdJtUBB57ieReZAOSgUYacts|s|START OK
Carabon可以与网络中其他计算机进行通信,下发任务。使用了几种类型的传输协议
TCP、b2m、np、frag、m2b
Carbon还为样本提供了持续更新的功能
尝试将同时释放出的另两个DLL文件注入到配置文件中的iproc配置项中
在目标进程中创建远线程调用LoadLibrary将DLL加载到目标进程中
解密Carbon文件:(来自ESET)
#!/usr/bin/env python2
from Crypto.Cipher import CAST
import sys
import argparse
def main():
parser = argparse.ArgumentParser(formatter_class=argparse.RawTextHelpFormatter)
parser.add_argument("-e", "--encrypt", help="encrypt carbon file", required=False)
parser.add_argument("-d", "--decrypt", help="decrypt carbon file", required=False)
try:
args = parser.parse_args()
except IOError as e:
parser.error(e)
return 0
if len(sys.argv) != 3:
parser.print_help()
return 0
key = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0\xFE\xFC\xBA\x98\x76\x54\x32\x10"
iv = "\x12\x34\x56\x78\x9A\xBC\xDE\xF0"
cipher = CAST.new(key, CAST.MODE_OFB, iv)
if args.encrypt:
plaintext = open(args.encrypt, "rb").read()
while len(plaintext) % 8 != 0:
plaintext += "\x00"
data = cipher.encrypt(plaintext)
open(args.encrypt + "_encrypted", "wb").write(data)
else:
ciphertext = open(args.decrypt, "rb").read()
while len(ciphertext) % 8 != 0:
ciphertext += "\x00"
data = cipher.decrypt(ciphertext)
open(args.decrypt + "_decrypted", "wb").write(data)
if __name__ == "__main__":
main()
本文由 Seebug Paper 发布,如需转载请注明来源。本文地址:https://paper.seebug.org/1516/