这是一篇关于misc图片方面的博客,可以用作入门misc方向食用。
流程
查看图片特征 --> 查看图片表面信息 --> 利用010查看二进制信息 --> 利用format检测 --> 利用Stegdetect检测 --> 解密
图片16进制文件倒置脚本
整体字符反向输出
with open("n.png","rb") as f:
t = f.read()
for i in t[::-1]:
a = hex(i)[2:]
if len(a) == 1:
a = '0' + a
print(a,end="")
整体16进制前后倒置
Stegdetect
jpg图片隐写的大杀器,用于检测jpg图片的各种隐写。
以JphideLSB隐写为例
.\stegdetect.exe -tjopi -s 10.0 文件路径
如同可检测出jphide隐写。
zsteg
检测png图片的隐藏信息。
查询图片详细信息
exiftool
文件结构
在开始图片学习之前要先了解一些文件的文件结构。
查看文件16进制形式需要用到查看器,如010Editor。
文件头
文件头是指文件十六进制形式下的开头四个十六进制码。
即图中区域。
还需要了解一些常见的文件头。
每个文件类型都有自己的文件结构,具体问题具体分析。
附加字符串
可以看到在最后添加字符串时,图片并不会受到影响。
在读取时只需要用到010Editor或其他图片十六进制查看器查看即可。
文件载体
隐藏
使用copy指令可以将压缩包或文本或PDF等等添加到图片尾部。
可见两图片没有区别,用010Editor打开。
可以看到flagpk.png的最后存在隐藏的zip压缩文件。
提取
这里用到kali虚拟机。
1,binwalk分离
binwalk --run-as=root 文件路径 -e
2,foremost分离
foremost 文件路径 -T
宽高修改(文件结构)
在010中按ALT+4
可以唤起模板,找到宽高可以修改。
当我们修改值的时候图片会发生一点的变化。
举个例子
假如有一个图片
看着正常,但是一旦把宽度放大。
就会有隐藏的flag。
图片修复
对于题目中的一些损坏图片,可能得自己来修复。
有一个flag-是损坏的文件,用010打开。
通过结构的判断,我们发现这是张png图片。
但是缺少了文件头。
查阅发现png的文件为89 50 4E 47
添加上文件头。
文件-->新建-->新建十六进制文件-->先填入文件头,再将其余部分复制过来。
保存,并添加png后缀即可。
LSB隐写(基于PNG图片)
看操作
现在有一个LSB隐写的图片。
打开Stegsolve-->File-->Open,打开LSB隐写的图片。
Analyse-->Data Extract
Bit Planes一般会将Red,Green,Blue都选为0。
Order settings里的选项一般是慢慢的试出来的。
点击Preview即可查看隐写内容。
特殊一点的
LSB cloacked-pixel工具隐写
python2 lsb.py extract 图片 out.txt 密码
Jphide
用到Jphswin工具
用工具打开一个jpg文件
点击Hide可以隐藏数据,设置密码为123456,点击Save jpeg即可保存
点击Seek可以提取隐藏数据,同上输入密码即可。
或者在kali中使用
steghide extract -sf '/root/桌面/lianjie/4.jpg' -p 123456
outguess隐写
用到工具outguess。
在kali中使用。
加密:
outguess -k 密码 -d 密文 demo.jpg out.jpg
加密之后,demo.jpg会覆盖out.jpg,hidden.txt的内容是要隐藏的东西。
解密:
outguess -k 密码 -r 图片路径 密文路径
F5隐写
加密涉及不到,直接解密
java Extract 文件路径
java Extract 文件路径 -p 密码
输出在output.txt里。
像素隐写
在像素中可能有隐写信息。
提示:把图片缩小10倍
大概率为像素隐写
from PIL import Image
img = Image.open('arcaea.png')
w = img.width
h = img.height
img_obj = Image.new("RGB",(w//10,h//10))
for x in range(w//10):
for y in range(h//10):
(r,g,b)=img.getpixel((x*10,y*10))
img_obj.putpixel((x,y),(r,g,b))
img_obj.save('ok.png')
oursercet
适用于任何文件的加密,有Key
该隐写会在文件为添加数据,导致文件在放入010时报错。
特征
双图片隐写(盲水印双图片)
用到BlindWaterMark-master工具
python2 bmp.py decode 1png 2.png 生成.png
kali中使用。
盲水印单图片
用到WaterMark工具
二维码分析
二维码的拼接与修复
不同种类的二维码用到的解码器不同,找到对应的二维码后再找解码器解码即可。
条码/二维码有多少种(各行业条码应用情况) - 知乎 (zhihu.com)
二维码的绘制
0x00000000
0xff71fefe
0x83480082
0xbb4140ba
0xbb6848ba
0xbb4a80ba
0x83213082
0xff5556fe
0xff5556fe
0x00582e00
0x576fb9be
0x707ef09e
0xe74b41d6
0xa82c0f16
0x27a15690
0x8c643628
0xbfcbf976
0x4cd959aa
0x2f43d73a
0x5462300a
0x57290106
0xb02ace5a
0xef53f7fc
0xef53f7fc
0x00402e36
0xff01b6a8
0x83657e3a
0xbb3b27fa
0xbb5eaeac
0xbb1017a0
0x8362672c
0xff02a650
0x00000000
将16进制转为2进制
t = open("D://浏览器下载//新建 文本文档.txt","r")
tt = t.readlines()
for num in tt:
a = bin(eval(num))
a = a.replace("0b","")
if len(a) < 32:
a = "0"*(32 - len(a)) + a
print(a)
with open("D://浏览器下载//新建2.txt", "a+", encoding="utf-8") as file:
file.write(a + "\n")
00000000000000000000000000000000
11111111011100011111111011111110
10000011010010000000000010000010
10111011010000010100000010111010
10111011011010000100100010111010
10111011010010101000000010111010
10000011001000010011000010000010
11111111010101010101011011111110
11111111010101010101011011111110
00000000010110000010111000000000
01010111011011111011100110111110
01110000011111101111000010011110
11100111010010110100000111010110
10101000001011000000111100010110
00100111101000010101011010010000
10001100011001000011011000101000
10111111110010111111100101110110
01001100110110010101100110101010
00101111010000111101011100111010
01010100011000100011000000001010
01010111001010010000000100000110
10110000001010101100111001011010
11101111010100111111011111111100
11101111010100111111011111111100
00000000010000000010111000110110
11111111000000011011011010101000
10000011011001010111111000111010
10111011001110110010011111111010
10111011010111101010111010101100
10111011000100000001011110100000
10000011011000100110011100101100
11111111000000101010011001010000
00000000000000000000000000000000
将一设为点,零为空,画图。
from PIL import Image
import numpy as np
def hex2bin(hexmat):
binmattemp = [bin(m)[2:] for m in hexmat] # 全转成二进制
rowlen = max([len(m) for m in binmattemp]) # 取最宽的值
binmat = [[0] + [int(b) for b in row.zfill(rowlen)] for row in binmattemp] # 用0补齐
print rowlen + 1, 'x', len(binmat)
for i in xrange(len(binmat)):
print ''.join([str(b) for b in binmat[i]])
return binmat, rowlen + 1, len(binmat)
def rm_col(binmat, col): # 移除指定的列
return [row[:col] + row[col + 1:] for row in binmat]
def make_bw_img(binmat, w, h, outfilename, blackbit=0):
bwmat = [[0 if b == blackbit else 255 for b in row] for row in binmat] # 用255表示白,0表示黑
imagesize = (w, h)
img = Image.fromarray(np.uint8(np.array(bwmat)))
img.save(outfilename)
if __name__ == '__main__':
hexmat = [0x00000000,
0xff71fefe,
0x83480082,
0xbb4140ba,
0xbb6848ba,
0xbb4a80ba,
0x83213082,
0xff5556fe,
0x00582e00,
0x576fb9be,
0x707ef09e,
0xe74b41d6,
0xa82c0f16,
0x27a15690,
0x8c643628,
0xbfcbf976,
0x4cd959aa,
0x2f43d73a,
0x5462300a,
0x57290106,
0xb02ace5a,
0xef53f7fc,
0x00402e36,
0xff01b6a8,
0x83657e3a,
0xbb3b27fa,
0xbb5eaeac,
0xbb1017a0,
0x8362672c,
0xff02a650,
0x00000000]
binmat, w, h = hex2bin(hexmat)
binmat = rm_col(binmat, 22) # 发现第七行和第22行多余,故删除
binmat = rm_col(binmat, 7)
make_bw_img(binmat, w, h, 'matrix_rmcol.png', blackbit=1)
可得
QRcode二维码
QRcode二维码用一个特性,
如图黑色都是固定不变的
如图是损坏的二维码
在正常的二维码中,我画出的这一列和这一行是一黑一白交替的像素。如下图
例一 [XYCTF] 我的二维码为什么扫不出来
看到一个损坏的二维码和py脚本
from PIL import Image
import random
def reverse_color(x):
return 0 if x == 255 else 255
def reverse_row_colors(pixels, row, width, block_size=10):
for x_block in range(width // block_size):
x = x_block * block_size
y = row * block_size
for x_small in range(x, x + block_size):
for y_small in range(y, y + block_size):
pixel = pixels[x_small, y_small]
pixels[x_small, y_small] = reverse_color(pixel)
def reverse_col_colors(pixels, col, height, block_size=10):
for y_block in range(height // block_size):
x = col * block_size
y = y_block * block_size
for x_small in range(x, x + block_size):
for y_small in range(y, y + block_size):
pixel = pixels[x_small, y_small]
pixels[x_small, y_small] = reverse_color(pixel)
original_img = Image.open("flag.png")
new_img = original_img.copy()
width, height = new_img.size
pixels = new_img.load()
count = 0
while count < 7:
x = random.randint(0, 1)
if x == 0:
reverse_col_colors(pixels, random.randint(0, height // 10 - 1), height)
else:
reverse_row_colors(pixels, random.randint(0, width // 10 - 1), width)
count += 1
new_img.save("new.png")
分析脚本
reverse_row_colors()
函数是把一行颜色反转。
reverse_col_colors()
函数是把一列颜色反转。while count < 7: x = random.randint(0, 1) if x == 0: reverse_col_colors(pixels, random.randint(0, height // 10 - 1), height) else: reverse_row_colors(pixels, random.randint(0, width // 10 - 1), width) count += 1
这一段就是随机把一行或者一列颜色反转。
那么咱们就只能手工修复了。
reverse_row_colors(pixels, 1, width) #行
reverse_col_colors(pixels, 0, height) #列
reverse_col_colors(pixels, 2, height)
reverse_col_colors(pixels, 5, height)
先用以上段调出四个角
这是调了4次,还有3次要调。
由上面的QRcoed的特性来调。
reverse_row_colors(pixels, 12, width)
reverse_col_colors(pixels, 10, height)
reverse_col_colors(pixels, 11, height)
最后得出二维码
from PIL import Image
import random
def reverse_color(x):
return 0 if x == 255 else 255
def reverse_row_colors(pixels, row, width, block_size=10):
for x_block in range(width // block_size):
x = x_block * block_size
y = row * block_size
for x_small in range(x, x + block_size):
for y_small in range(y, y + block_size):
pixel = pixels[x_small, y_small]
pixels[x_small, y_small] = reverse_color(pixel)
def reverse_col_colors(pixels, col, height, block_size=10):
for y_block in range(height // block_size):
x = col * block_size
y = y_block * block_size
for x_small in range(x, x + block_size):
for y_small in range(y, y + block_size):
pixel = pixels[x_small, y_small]
pixels[x_small, y_small] = reverse_color(pixel)
original_img = Image.open("new.png")
new_img = original_img.copy()
width, height = new_img.size
print(width,height)
pixels = new_img.load()
reverse_row_colors(pixels, 1, width) #行
reverse_col_colors(pixels, 0, height) #列
reverse_col_colors(pixels, 2, height)
reverse_col_colors(pixels, 5, height)
reverse_row_colors(pixels, 12, width)
reverse_col_colors(pixels, 10, height)
reverse_col_colors(pixels, 11, height)
new_img.show()
GIF动图的分析
可以用Stegsolve工具来逐帧分析
打开jsp.gif文件
Analyse-->Frame Browser
即可得出。
Logistic混沌变换加密
图片的混沌加密是先把所有像素点平坦化了,按照一位数组处理的,然后再重组为图片
import cv2
import numpy as np
from PIL import Image
def logistic(Img, x, u,times):
M = Img.shape[0]
N = Img.shape[1]
for i in range(1, times):
x = u * x * (1 - x)
array = np.zeros(M * N)
array[1] = x
for i in range(1, M * N - 1):
array[i + 1] = u * array[i] * (1 - array[i])
array = np.array(array * 255, dtype='uint8')
code = np.reshape(array, (M, N))
xor = Img ^ code
v = xor
return v
x = 密码1
u = 密码2
times = 密码3
Img = cv2.imread('图片路径')
Img = Img[:, :, [2, 1, 0]]
(r, g, b) = cv2.split(Img)
R = logistic(r, x, u, times)
G = logistic(g, x, u, times)
B = logistic(b, x, u, times)
merged = np.ones(Img.shape, dtype=np.uint8)
merged[:, :, 2] = B
merged[:, :, 1] = G
merged[:, :, 0] = R
Img = Image.fromarray(merged)
Img.save('flag.png')
webp图片隐写
stegpy隐写
在kali中使用
stegpy 文件
转为其他文件
stego文件头
stego文件头的图片可以在linux中显示为图片。
通道低位隐写
当图片的位深度大于24位时,就有可能存在通道低位隐写
如下图片属性,这里注意到是48位的图片位深度
48位的图片,平均RBG位16,人眼是看不到低于8bit位的像素信息的。
# 提取低位
import cv2
import numpy as np
img = cv2.imread("turing.png", cv2.IMREAD_UNCHANGED)
img2 = img & 0xFF
img2 = img2.astype(np.uint8)
cv2.imwrite("turing1.png", img2)
humbnail隐写(缩略图隐写)
这里是缩略图隐写的方式,叫做thumbnail隐写
用Magic打开即可看到
ctfshow{dbf7d3f84b0125e833dfd3c80820a129}
未经作者允许,请勿转载!!!
标签:存在,reverse,img,col,图片,pixels,block,size From: https://www.cnblogs.com/xmiscx/p/18227886