Invoke-PSImage利用分析
0x00 前言
最近在github看見一個有趣的項目:Invoke-PSImage,在png文件的像素內插入powershell代碼作為payload(不影響原圖片的正常瀏覽),在命令行下僅通過一行powershell代碼就能夠執行像素內隱藏的payload
這是一種隱寫(Steganography)技術的應用,我在之前的文章對png的隱寫技術做了一些介紹,可供參考:
《隱寫技巧——PNG文件中的LSB隱寫》
《隱寫技巧——利用PNG文件格式隱藏Payload》
本文將結合自己的一些心得對Invoke-PSImage進行分析,介紹原理,解決測試中遇到的問題,學習腳本中的編程技巧,提出自己的優化思路
Invoke-PSImage地址:
https://github.com/peewpw/Invoke-PSImage
0x01 簡介
本文將要介紹以下內容:
·腳本分析
·隱寫原理
·實際測試
·編程技巧
·優化思路
0x02 腳本分析
1、參考說明文件
https://github.com/peewpw/Invoke-PSImage/blob/master/README.md
(1) 選取每個像素的兩個顏色中的4位用於保存payload
(2) 圖像質量將受到影響
(3) 輸出格式為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)n
說明:
$payload[$counter]/16表示$payload[$counter]/0x10
即取0x73/0x10,取商,等於0x07
所以,$paybyte1 = 0x07
代碼:
$paybyte2 = ($payload[$counter] -band 0x0f)n
說明:
即0x73 & 0x0f,結果為0x03
所以,$paybyte2 = 0x03
代碼:
$paybyte3 = ($randb[($counter+2)%109] -band 0x0f)n
說明:
作隨機數填充,$paybyte3可忽略
註:
原代碼會將payload的長度和圖片的像素長度進行比較,圖片多出來的像素會以同樣格式被填充成隨機數
(2) 向原像素賦值,添加payload
原像素為RGB(0x62,0x61,0x60)
代碼:
$rgbValues[($counter*3)] = ($rgbValues[($counter*3)] -band 0xf0) -bor $paybyte1n
說明:
即0x60 & 0xf0 | 0x07
所以,$rgbValues[0] = 0x67
代碼:
$rgbValues[($counter*3+1)] = ($rgbValues[($counter*3+1)] -band 0xf0) -bor $paybyte2n
說明:
即0x61 & 0xf0 | 0x03
所以,$rgbValues[1] = 0x63
代碼:
$rgbValues[($counter*3+2)] = ($rgbValues[($counter*3+2)] -band 0xf0) -bor $paybyte3n
說明:
隨機數填充,可忽略
綜上,新像素的修改過程為:
R: 高位不變,低4位填入隨機數
G: 高位不變,低4位填入payload的低4位
B: 高位不變,低4位填入payload的高4位
2、讀取RGB,還原出payload
對輸出做一個簡單的修改,讀取第一個像素中的payload並還原
取第0個像素的代碼如下:
sal a New-Object;nAdd-Type -AssemblyName "System.Drawing";n$g= a System.Drawing.Bitmap("C:1evil-kiwi.png");n$p=$g.GetPixel(0,0);n$p;n
還原payload,輸出payload的第一個字元,代碼如下:
$o = [math]::Floor(($p.B -band 15)*16) -bor ($p.G -band 15);n[math]::Floor(($p.B -band 15)*16) -bor ($p.G -band 15));n
0x04 實際測試
使用參數:
Invoke-PSImage -Script .test.ps1 -Image .kiwi.jpg -Out .evil-kiwi.pngn
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的代碼進行分析,介紹加解密原理,分析優缺點,提出優化思路,幫助大家更好的進行學習研究
本文為 3gstudent 原創稿件, 授權嘶吼獨家發布,如若轉載,請聯繫嘶吼編輯: http://www.4hou.com/technology/9472.html 更多內容請關注「嘶吼專業版」——Pro4hou
推薦閱讀:
※引入機器學習前需要先弄明白這三件事
※並非勒索軟體?Petya 的真實面目令人遐想
※Appleby 被黑,世界級財富大鱷財務信息泄露
※參加 DEF CON、Black Hat 這樣的大會是一種怎樣的體驗?
TAG:信息安全 |