跳转至

Solar 应急响应赛 5 月 Writeup

  • 时间:5 月 31 日 10:00~18:00
  • 附件大小:15 GB 压缩的 OVF 格式虚拟机,完全导入后约 30 GB

附件分类

  • 应急响应:Windows Server 2016 虚拟机

简单总结

题目短小精悍,同时也不是太难,冲榜很大程度上靠手速(因此也是很惊险刺激hh)。

解题过程

开源项目 - 逆向

核心算法并不难,重点在于还原多重编码的代码并推断出其大概作用。

所给附件是一个 C++ 项目,主文件是对所给字符串做异或,解出 flag{this_is_fake_flag},并不正确。

转而分析项目文件,在 ConsoleApplication2/ConsoleApplication2.vcxproj 中发现了内嵌代码。在构建项目本身前,Visual Studio 会先执行 PreBuildEvent 中的任务,这个任务生成了一个批处理脚本到临时文件,随后生成 VB 脚本如下:

小提示

Windows 批处理中的 %random% 是为随机数保留的变量。

Function Base64Encode(bytes^)
  Dim xmlDoc, node
  Set xmlDoc = CreateObject("MSXML2.DOMDocument.3.0"^)
  Set node = xmlDoc.createElement("b64"^)

  node.DataType = "bin.base64"
  node.NodeTypedValue = bytes

  Base64Encode = Replace(Replace(node.Text, vbCr, ""^), vbLf, ""^)
End Function

Function Base64Decode(strBase64^)
  Dim xmlDoc, node
  Set xmlDoc = CreateObject("MSXML2.DOMDocument.3.0"^)
  Set node = xmlDoc.createElement("b64"^)

  node.DataType = "bin.base64"
  node.Text = Replace(Replace(strBase64, vbCr, ""^), vbLf, ""^)

  Base64Decode = node.NodeTypedValue
End Function

Function EncodeForPowerShell(plaintext^)
  Dim stream
  Set stream = CreateObject("ADODB.Stream"^)
  With stream
       .Type = 2
       .Charset = "utf-16le"
       .Open
       .WriteText plaintext
       .Position = 0
       .Type = 1
       .Position = 2
    EncodeForPowerShell = .Read
  End With

  stream.Close
End Function

Dim base64Code, decodedBytes, psCommand, encodedCommand

base64Code = "<Ignored>"

On Error Resume Next

decodedBytes = Base64Decode(base64Code^)

If Err.Number <> 0 Then
  WScript.Quit 1
End If

Dim stream : Set stream = CreateObject("ADODB.Stream"^)

With stream
     .Type = 1
     .Open
     .Write decodedBytes
     .Position = 0
     .Type = 2
     .Charset = "utf-8"
  psCommand = .ReadText
End With

encodedCommand = Base64Encode(EncodeForPowerShell(psCommand^)^)

Dim shell : Set shell = CreateObject("WScript.Shell"^)
shell.Run "powershell.exe -EncodedCommand " ^& encodedCommand,0

这段代码的细节无需过多关注,只需知道它生成的是 PowerShell 脚本即可。base64Code 编码的也是一段代码(由于太长在上面省略了),解码后做一点点整理工作:

$target = "LHDh1x1zdIiVS+a5qYJrBPb0ixqHTxd+uJ/3tckUdOqG+mn113E=";
$k = "FixedKey123!";

$d = [System.Text.Encoding]::UTF8.GetBytes((Read-Host "输入字符串"));
$s = 0..255;
$j = 0;

0..255 | ForEach-Object {
  $j = ($j + $s[$_] + [byte]$k[$_ % $k.Length]) % 256;
  $s[$_], $s[$j] = $s[$j], $s[$_];
};

$i = $j = 0;
$r = @();

$d | ForEach-Object {
  $i = ($i + 1) % 256;
  $j = ($j + $s[$i]) % 256;
  $s[$i], $s[$j] = $s[$j], $s[$i];
  $r += $_ -bxor $s[($s[$i] + $s[$j]) % 256];
};

[System.Convert]::ToBase64String($r) -eq $target;

发现是典型的 RC4 算法,直接解密即可获得 Flag(在此之前还需要先进行 Base64 解密):

RC4 解密后的 Flag

应急响应

比较简短的五连问...

挖矿后台

查看任务计划,有可疑的任务 sql backing up 存在,指向一个 VBS 脚本文件,对应导致系统卡顿的配置名称(去除空格为答案)。

恶意的任务计划

跟踪其调用的 sqlwpr.exe 是一个恶意挖矿程序,b.oracleservice.top 为矿池服务器,是所要的恶意链接。

进一步溯源,在网上搜索这个链接,可以找到 ThreatFox 的 IOC 报告,对应的团队为 8220Gang

服务器后门

管理员桌面有 CrushFTP 与 O2Server 两个服务的目录。

对于 CrushFTP 浏览其日志文件 CrushFTP.log,注意到攻击者从匿名用户身份使用非常规方式提权到 crushadmin 账户,在修改 user1 密码后使用其将配置文件导出。提权部分的日志如下:

CrushFTP 的提权攻击日志

搜索对应的漏洞应为 CVE-2025-31161


攻击者的 C2 服务器 IP 字面上有点不清楚,首先会想到恶意程序。做这道题的时候因为语义不完整,会比较搞心态...其实顺着常规的恶意攻击分析思路进行就好。

使用取证程序可以在 Users/Public 目录找到 update.exe,但恢复出来是乱码,其原始功能无法直接确定。 但在查看事件时可以注意到,Windows Powershell 中有异常的脚本下载操作。

PowerShell 日志中的异常命令

注意

此处 192.168.60.220 是提供脚本的跳板,并非真正的 C2 服务器,需要注意。

由于脚本文件没有直接保存(downloadstring 函数的结果会存储在内存而非文件系统),转而猜测该脚本可能负责控制防火墙、维持后门等。毕竟这些操作一定涉及网络,会经由系统的防火墙并记录日志,于是去查看对应时间段前后的安全日志(登录/网络请求)。

结合发起程序、时间等进一步筛选,最终定位到下图:

安全审查事件中显示的访问 IP

得到 C2 服务器地址为 156.238.230.57

评论