Invoke-PSImage 利用分析

发布于 2025-02-10 06:44:40 字数 4284 浏览 8 评论 0

0x00 前言

最近在 github 看见一个有趣的项目: Invoke-PSImage ,在 png 文件的像素内插入 powershell 代码作为 payload(不影响原图片的正常浏览),在命令行下仅通过一行 powershell 代码就能够执行像素内隐藏的 payload。

本文将结合自己的一些心得对 Invoke-PSImage 进行分析,介绍原理,解决测试中遇到的问题,学习脚本中的编程技巧,提出自己的优化思路

Invoke-PSImage 地址:https://github.com/peewpw/Invoke-PSImage

0x01 简介

本文将要介绍以下内容:

  • 脚本分析
  • 隐写原理
  • 实际测试
  • 编程技巧
  • 优化思路

0x02 脚本分析

1、参考说明文件

https://github.com/peewpw/Invoke-PSImage/blob/master/README.md

  • 选取每个像素的两个颜色中的 4 位用于保存 payload
  • 图像质量将受到影响
  • 输出格式为 png

2、参考源代码对上述说明进行分析

(1) 像素使用的为 RGB 模式,分别选取颜色分量中的 G 和 B 的低 4 位(共 8 位) 保存 payload

(2) 由于同时替换了 G 和 B 的低 4 位,故图片质量会受影响

补充:

LSB 隐写是替换 RGB 三个分量的最低 1 位,人眼不会注意到前后变化,每个像素可以存储 3 位的信息

猜测 Invoke-PSImage 选择每个像素存储 8 位是为了方便实现(8 位=1 字节),所以选择牺牲了图片质量

(3) 输出格式为 png,需要无损

png 图片为无损压缩(bmp 图片也是无损压缩),jpg 图片为有损压缩。所以在实际测试过程,输入 jpg 图片,输出 png 图片,会发现 png 图片远远大于 jpg 图片的大小

(4) 需要注意 payload 长度,每个像素保存一个字节,像素个数需要大于 payload 的长度

0x03 隐写原理

参照源代码进行举例说明(跳过读取原图片的部分)

1、修改像素的 RGB 值,替换为 payload

代码起始位置:https://github.com/peewpw/Invoke-PSImage/blob/master/Invoke-PSImage.ps1#L110

对 for 循环做一个简单的修改,假定需要读取 0x73 ,将其写入第一个像素 RGB(0x67,0x66,0x65)

(1) 读取 payload

代码:

$paybyte1 = [math]::Floor($payload[$counter]/16)

说明:

$payload[$counter]/16 表示 $payload[$counter]/0x10

即取 0x73/0x10,取商,等于 0x07

所以,$paybyte1 = 0x07

代码:

$paybyte2 = ($payload[$counter] -band 0x0f)

说明:

即 0x73 & 0x0f,结果为 0x03

所以,$paybyte2 = 0x03

代码:

$paybyte3 = ($randb[($counter+2)%109] -band 0x0f)

说明:

作随机数填充,$paybyte3 可忽略

注:

原代码会将 payload 的长度和图片的像素长度进行比较,图片多出来的像素会以同样格式被填充成随机数

(2) 向原像素赋值,添加 payload

原像素为 RGB(0x62,0x61,0x60)

代码:

$rgbValues[($counter*3)] = ($rgbValues[($counter*3)] -band 0xf0) -bor $paybyte1

说明:即 0x60 & 0xf0 | 0x07,所以,$rgbValues[0] = 0x67

代码:

$rgbValues[($counter*3+1)] = ($rgbValues[($counter*3+1)] -band 0xf0) -bor $paybyte2

说明:即 0x61 & 0xf0 | 0x03,所以,$rgbValues[1] = 0x63

代码:

$rgbValues[($counter*3+2)] = ($rgbValues[($counter*3+2)] -band 0xf0) -bor $paybyte3

说明:随机数填充,可忽略

综上,新像素的修改过程为:

R: 高位不变,低 4 位填入随机数 G: 高位不变,低 4 位填入 payload 的低 4 位 B: 高位不变,低 4 位填入 payload 的高 4 位

2、读取 RGB,还原出 payload

对输出做一个简单的修改,读取第一个像素中的 payload 并还原

取第 0 个像素的代码如下:

sal a New-Object;
Add-Type -AssemblyName "System.Drawing";
$g= a System.Drawing.Bitmap("C:\1\evil-kiwi.png");
$p=$g.GetPixel(0,0);
$p;

还原 payload,输出 payload 的第一个字符,代码如下:

$o = [math]::Floor(($p.B -band 15)*16) -bor ($p.G -band 15);
[math]::Floor(($p.B -band 15)*16) -bor ($p.G -band 15));

0x04 实际测试

使用参数:

Invoke-PSImage -Script .\test.ps1 -Image .\kiwi.jpg -Out .\evil-kiwi.png

test.ps1: 包含 payload,例如"start calc.exe"

kiwi.jpg: 输入图片,像素数量需要大于 payload 长度

evil-kiwi.png: 输出图片路径

脚本执行后会输出读取 图片解密 payload 并执行的代码

实际演示略

0x05 优化思路

结合前面的分析,选择替换 RGB 中两个分量的低 4 位保存 payload,会在一定程序上影响图片质量,可参照 LSB 隐写的原理只替换三个分量的最低位,达到人眼无法区别的效果。

当然,该方法仅是隐写技术的一个应用,无法绕过 Win10 的 AMSI 拦截,在 Win10 系统上测试还需要考虑对 AMSI 的绕过。

0x06 小结

本文对 Invoke-PSImage 的代码进行分析,介绍加解密原理,分析优缺点,提出优化思路,帮助大家更好的进行学习研究。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

玩套路吗

暂无简介

文章
评论
28 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文