日期:2024.06.24 作者:nothing 介绍:学习如何从 Invoke-PSImage
取证免杀图片中提取隐藏脚本。
0x00 前言
之前公众号发过一篇文章,是利用隐写技术进行木马免杀的,采用的方式就是Invoke-PSImage
,但之前只讲过如何进行隐藏,如果我们在真实环境中遇到了这种方式的免杀木马,如何进行病毒提取呢?下面就一起学习如何进行Invoke-PSImage
技术的免杀木马提取。
0x01 Invoke-PSImage
1.1 隐写原理
https://github.com/peewpw/Invoke-PSImage
前面的文章对Invoke-PSImage
的隐写方式做过简单的叙述。
其本质上使用的是图片隐写技术中相对简单的最低有效位隐写(LSB)的方式进行数据隐藏,采用嵌入的方式,将有效的shellcode隐藏到每个像素点中的两个颜色通道中的四个低位中去。
正常的LSB
隐写是替换RGB
三个颜色分量的最低一位,每个像素存储3
位的信息,但Invoke-PSImage
却针对2
个颜色分量各替换4
位,每个像素可以存储8
位的信息,这样存储的信息量大了,但是图片质量也下去了,可以看出前后的区别,如果能知道原有图片的样子,其实能一眼看出经过Invoke-PSImage
处理过的图片的区别。而且被Invoke-PSImage
处理过的图片大小,是原本文件大小的几倍之多,例如原本6M
的图片,处理完成后大小可以达到40-50M
,图片文件变得非常大。
1.2 脚本分析
上面简述了下技术原理,下面我们从脚本中的具体代码来看下Invoke-PSImage
是如何进行隐写的:
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
}
1、首先取三个颜色通道的数据,正常来讲,读取数据的时候,按照RGB
顺序读取;写入数据的时候,写入的顺序是按照BGR
顺序进行写入的。
2、这里我们假设有写入的第一个数据为0x53
,那么$paybyte1=0x53/0x10=0x05
,取商。
3、同理,$paybyte2=0x53&0x0f=0x03
。
4、$paybyte3
使用随机数填充,如果我们写入的payload
的长度比图片像素的长度小,那么图片多出来的像素会用相同格式进行填充为随机数。
5、之后开始对原像素进行填充payload
,假定这里原像素为(0x52,0x51,0x50)
,那么:$rgbValues[0]=0x52 & 0xf0 | 0x05=0x55
。
6、同理进行计算得到,$rgbValues[1]=0x51 & 0xf0 | 0x03=0x53
。
7、$paybyte3
全部为随机数,不做讨论。
这里可以看出,只有bg
通道写入了payload
数据,而R
通道则全部填充随机数。
0x02 实例分析
使用CobalStrike
生成了一段powershell
上线代码,写入到文件当中去,写入成功后,查看图片的RGB
最低的4
位通道,可以看到,全部呈雪花状,这也是Invoke-PSImage
写入木马后,图片的一个显著特征。
如果查看的话,也只能查看到一些杂乱的数据,并无明显特征,所以数据的提取就无法使用隐写工具完成,使用脚本进行BG
通道最低4
位数据的提取。
from PIL import Image
def solove_png(image_path):
img = Image.open(image_path)
width, height = img.size
extract_data = bytearray()
for y in range(height):
for x in range(width):
pixels = img.getpixel((x, y))
extract_byte = (pixels[1] & 0x0F) | ((pixels[2] & 0x0F) << 4)
extract_data.append(extract_byte)
return extract_data
image_path = "flag.png"
data = solove_png(image_path)
with open('1.bin', 'wb') as f:
f.write(data)
0x03 总结
通过上述内容可以得出,使用Invoke-PSImage
写入的图片有两个显著特征:
1、png
图片文件非常大。
2、图片RGB的通道的最低四位通道,全部呈雪花状,说明被写入了大量数据。
若在真实环境中遇到使用此种方式进行免杀的木马,也可以根据这两个特征,快速定位木马文件位置,进而使用脚本进行提取。
参考:
https://xz.aliyun.com/t/13159?time__1311=mqmxnDBDcD20w405DIYqCqT1x9AreH3Y4D
免责声明:本文仅供安全研究与讨论之用,严禁用于非法用途,违者后果自负。
点此亲启
原文始发于微信公众号(宸极实验室):『杂项』Invoke-PSImage取证
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论