目录
EZ_v1deo
视频的lsb隐写,直接让gpt写脚本,修改几次就差不多了
import cv2
import numpy as np
# 读取原始视频
input_filename = 'flag.avi'
cap = cv2.VideoCapture(input_filename)
fps = int(cap.get(cv2.CAP_PROP_FPS))
frame_size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)), int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
# 准备写入新视频
output_filename = 'decrypted_flag.avi'
fourcc = cv2.VideoWriter_fourcc(*'XVID')
out = cv2.VideoWriter(output_filename, fourcc, fps, frame_size)
# 解密LSB隐写并写入新视频
while cap.isOpened():
ret, frame = cap.read()
if not ret:
break
# 解密LSB隐写
decrypted_frame = frame & 1
decrypted_frame = decrypted_frame*(255,255,255)
out.write(decrypted_frame.astype(np.uint8))
cap.release()
out.release()
cv2.destroyAllWindows()
看视频拿到flag
Mondy left me Broken
看到视频猜测是猫脸变换,提取一帧出来,爆破一下参数
ffmpeg -i final.mkv -vframes 1 output.png
import numpy as np
from PIL import Image
import cv2
im = Image.open('output.png')
im = np.array(im)
def dearnold(img):
r,c,t = img.shape
p = np.zeros((r,c,t),dtype=np.uint8)
for a in range(1, 11):
for b in range(1, 11):
for i in range(r):
for j in range(c):
for k in range(t):
x = ((a*b+1)*i - b*j)%r
y = (-a*i + j)%r
p[x,y,k] = img[i,j,k]
filename = f'new/dearnold{a}_{b}.png'
cv2.imwrite(filename, p)
print('dearnold{}_{}'.format(a, b))
return p
dearnold(im)
爆破出来图片参数a和b都是5的时候,图片正常
ffmpeg -i final.mkv -c:v libx264 -c:a aac output.mp4
恢复视频
import numpy as np
import cv2
from PIL import Image
import tqdm
def dearnold(img):
r,c,t = img.shape
p = np.zeros((r,c,t),dtype=np.uint8)
a = 5
b = 5
for i in range(r):
for j in range(c):
for k in range(t):
x = ((a*b+1)*i - b*j)%r
y = (-a*i + j)%r
p[x,y,k] = img[i,j,k]
return p
video = "output.mp4"
cap = cv2.VideoCapture(video)
fps = cap.get(cv2.CAP_PROP_FPS)
size = (int(cap.get(cv2.CAP_PROP_FRAME_WIDTH)),
int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT)))
fourcc = cv2.VideoWriter_fourcc(*'mp4v')
out = cv2.VideoWriter('flag.mp4', fourcc, fps, size)
pbar = tqdm.tqdm(total=int(cap.get(cv2.CAP_PROP_FRAME_COUNT)))
ret, frame = cap.read()
while ret:
ret, frame = cap.read()
if ret:
frame = dearnold(frame)
out.write(frame) # 将处理后的帧写⼊新的视频⽂件
pbar.update(1)
else:
break
cap.release()
out.release()
第三秒左右应该是有一半flag的,但这里看不清,题目后面直接给了
_I_CAN_GOT_both}
还发现了水印的参数(题目hint给了说是dct音频隐写)
这里dct
水印提取需要原视频,所以要下载原视频
https://www.bilibili.com/video/BV1Fh4y1M79t/?spm_id_from=333.337.search-card.all.click
提取音频
ffmpeg -i final.mkv -vn -acodec pcm_s16le flag.wav
ffmpeg -i origin2.mp4 -vn -acodec pcm_s16le origin.wav
import numpy as np
from scipy.io import wavfile
from scipy.fftpack import fft, fftfreq
import matplotlib.pyplot as plt
# 读取音频文件
rate, data = wavfile.read('flag.wav')
rate2, data2 = wavfile.read('origin2.wav')
# 将双声道音频合并成单声道
if len(data.shape) > 1 and data.shape[1] == 2:
data = data.mean(axis=1)
if len(data2.shape) > 1 and data2.shape[1] == 2:
data2 = data2.mean(axis=1)
# 计算音频差异
data3 = data2 - data
# 计算频谱
fft_size = 4096
plt.specgram(data3, fft_size, rate, window=None, noverlap=30, scale='dB')
plt.savefig("1.png")
plt.show()
稍微拉伸一下就可以直接扫了
WMCTF{Video_Audio
那么flag为
WMCTF{Video_Audio_I_CAN_GOT_both}
perfect two-way foil
这里可以看到是希伯特曲线和flag.png
很像
⼤⼩为512*512,同时题⽬中要求是⼆向化的⿊盒⼦,结合图像中有很多的⿊⾊要素和图⽚为RGBA,可以基础猜测需要将 ⼆维图像希尔伯特取点后重新组合回三维物体,之后有⼀部分彩⾊要素应该就是flag需要的东⻄,最后的三维物体 我们再对其z轴进⾏切⽚我们就可以到三维物体的⼤致概况,由此编写脚本:
import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
from PIL import Image
def _hilbert_3d(order):
def gen_3d(order, x, y, z, xi, xj, xk, yi, yj, yk, zi, zj, zk, array):
if order == 0 :
xx = x + (xi + yi + zi)/3
yy = y + (xj + yj + zj)/3
zz = z + (xk + yk + zk)/3
array.append((xx, yy, zz))
else:
gen_3d(order-1, x, y, z, yi/2, yj/2, yk/2, zi/2, zj/2, zk/2, xi/2, xj/2,xk/2, array)
gen_3d(order-1, x + xi/2, y + xj/2, z + xk/2, zi/2, zj/2, zk/2, xi/2, xj/2,xk/2, yi/2, yj/2, yk/2, array)
gen_3d(order-1, x + xi/2 + yi/2, y + xj/2 + yj/2, z + xk/2 + yk/2, zi/2,zj/2, zk/2, xi/2, xj/2, xk/2, yi/2, yj/2, yk/2, array)
gen_3d(order-1, x + xi/2 + yi, y + xj/2 + yj, z + xk/2 + yk, -xi/2, -xj/2, -xk/2, -yi/2, -yj/2, -yk/2, zi/2, zj/2, zk/2, array)
gen_3d(order-1, x + xi/2 + yi + zi/2, y + xj/2 + yj + zj/2, z + xk/2 + yk + zk/2, -xi/2, -xj/2, -xk/2, -yi/2, -yj/2, -yk/2, zi/2, zj/2, zk/2, array)
gen_3d(order-1, x + xi/2 + yi + zi, y + xj/2 + yj + zj, z + xk/2 + yk + zk,-zi/2, -zj/2, -zk/2, xi/2, xj/2, xk/2, -yi/2, -yj/2, -yk/2, array)
gen_3d(order-1, x + xi/2 + yi/2 + zi, y + xj/2 + yj/2 + zj , z + xk/2 + yk/2+ zk, -zi/2, -zj/2, -zk/2, xi/2, xj/2, xk/2, -yi/2, -yj/2, -yk/2, array)
gen_3d(order-1, x + xi/2 + zi, y + xj/2 + zj, z + xk/2 + zk, yi/2, yj/2,yk/2, -zi/2, -zj/2, -zk/2, -xi/2, -xj/2, -xk/2, array)
n = pow(2, order)
hilbert_curve = []
gen_3d(order, 0, 0, 0, n, 0, 0, 0, n, 0, 0, 0, n, hilbert_curve)
return np.array(hilbert_curve).astype('int')
def _hilbert_2d(order):
def gen_2d(order, x, y, xi, xj, yi, yj, array):
if order == 0:
xx = x + (xi + yi)/2
yy = y + (xj + yj)/2
array.append((xx, yy))
else:
gen_2d(order-1, x, y, yi/2, yj/2, xi/2, xj/2, array)
gen_2d(order-1, x + xi/2, y + xj/2, xi/2, xj/2, yi/2, yj/2, array)
gen_2d(order-1, x + xi/2 + yi/2, y + xj/2 + yj/2, xi/2, xj/2, yi/2, yj/2,array)
gen_2d(order-1, x + xi/2 + yi, y + xj/2 + yj, -yi/2, -yj/2, -xi/2, -xj/2,array)
n = pow(2, order)
hilbert_curve = []
gen_2d(order, 0, 0, n, 0, 0, n, hilbert_curve)
return np.array(hilbert_curve).astype('int')
# Generate 3D Hilbert curve for order 3
curve = _hilbert_3d(6)
curve_2 = _hilbert_2d(9)
p = np.array(Image.open('flag.png').convert('RGBA'))
line = []
for i in curve_2:
line.append(p[i[0], i[1]])
line = np.array(line)
remake_3d = np.zeros((64,64,64,4), dtype=np.uint8)
for i in range(len(curve)):
remake_3d[curve[i][0], curve[i][1], curve[i][2], :] = line[i]
for i in range(64):
pic = Image.fromarray(remake_3d[:,:,i,:])
pic.save('res/' + str(i) + '.png')
WMCTF{6532f556-2dc5-45f6-847f-797f235d7bb1}
StegLab-PointAttack 1& 2
直接看雪殇的,师傅们乱秀集锦