XCTF whiper
题目给了png和压缩包,压缩包解压要密码
Stegsolve打开png看到
Hint1得到提示,但之后也没用上
在png末尾看到base64

Binwalk文件,dd提取5984之后的数据


将得到的文件解base64得到文件4,再次binwalkj分离

strings搜索password,得到密码

解压得到flag:ZCTF{Nightingale}
CTF 我萌吗
这是一个代码审计的题目

题目先给了一个py代码,运行后显示

根据提示hex打开文件得到js代码,直接给了加密逻辑

交给deepseek写出解密程序,得到
from PIL import Image
import base64
import sys
def decode(dest_path, key_path):
dest = Image.open(dest_path).convert('RGBA')
key = Image.open(key_path).convert('RGBA')
dw, dh = dest.size
kw, kh = key.size
base64_chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
base64_ords = [ord(c) for c in base64_chars]
candidates = {}
# 遍历key的每个像素
for ky in range(kh):
for kx in range(kw):
kr, kg, kb, ka = key.getpixel((kx, ky))
# 情况B:检查相同坐标dest(x,y)
if kx < dw and ky < dh:
dr, dg, db, da = dest.getpixel((kx, ky))
if dr == kr and db == 255 - kb:
idx = dg
ch = kg
if 0 <= idx < 256 and ch in base64_ords:
candidates.setdefault(idx, []).append(ch)
# 情况A:检查dest转置坐标(y,x)
if ky < dw and kx < dh:
dr, dg, db, da = dest.getpixel((ky, kx))
if dr == 255 - kr:
idx = kg
ch = kb
if 0 <= idx < 256 and ch in base64_ords:
candidates.setdefault(idx, []).append(ch)
# 去重
for idx in candidates:
candidates[idx] = list(set(candidates[idx]))
indices = sorted(candidates.keys())
print("Found indices:", indices)
if not indices:
print("No candidates found")
return
max_idx = max(indices)
missing = [i for i in range(max_idx + 1) if i not in candidates]
print("Missing indices:", missing)
# 构建候选列表,缺失的用None表示
cand_list = [candidates.get(i) for i in range(max_idx + 1)]
# 递归枚举所有组合
def backtrack(pos, current):
if pos == len(cand_list):
flag_base64 = ''.join(chr(c) for c in current)
try:
decoded = base64.b64decode(flag_base64)
text = decoded.decode('utf-8')
print("Found flag base64:", flag_base64)
print("Decoded flag:", text)
sys.exit(0)
except:
pass
return
if cand_list[pos] is not None:
for ch in cand_list[pos]:
backtrack(pos + 1, current + [ch])
else:
for ch in base64_ords:
backtrack(pos + 1, current + [ch])
backtrack(0, [])
print("No valid flag found")
if __name__ == "__main__":
decode("dest.png", "key.png")
取前面一部分b25seSBjYXQgd2lsbCBkZWNvZGUgdGhpczIzMzMzMzM=,得到 flag{b25seSBjYXQgd2lsbCBkZWNvZGUgdGhpczIzMzMzMzM=}
流量分析
题目给的流量包导出http看到

符合sql注入的特点,每次从32开始,记录每次的ascii值得到 102 108 97 103 123 99 50 98 98 102 57 99 101 99 100 97 102 54 53 54 99 102 53 50 52 100 48 49 52 99 53 98 102 48 52 54 99 125 转ascii得到flag{c2bbf9cecdaf656cf524d014c5bf046c}
湘湖杯 Hidden Write
题目给了个png图片,hex打开
在文件尾和后面看到


有3个IHDR,两个缺失文件头,分离补齐文件头,得到两张新图片


原图和新图相同,把原图和新图1,github上找的代码进行双图盲水印
#!/usr/bin/env python
# -*- coding: utf8 -*-
cmd = None
debug = False
seed = 20160930
oldseed = False
alpha = 3.0
if __name__ == '__main__':
import sys
if '-h' in sys.argv or '--help' in sys.argv or len(sys.argv) < 2:
print ('Usage: python bwm.py <cmd> [arg...] [opts...]')
print (' cmds:')
print (' encode <image> <watermark> <image(encoded)>')
print (' image + watermark -> image(encoded)')
print (' decode <image> <image(encoded)> <watermark>')
print (' image + image(encoded) -> watermark')
print (' opts:')
print (' --debug, Show debug')
print (' --seed <int>, Manual setting random seed (default is 20160930)')
print (' --oldseed Use python2 random algorithm.')
print (' --alpha <float>, Manual setting alpha (default is 3.0)')
sys.exit(1)
cmd = sys.argv[1]
if cmd != 'encode' and cmd != 'decode':
print ('Wrong cmd %s' % cmd)
sys.exit(1)
if '--debug' in sys.argv:
debug = True
del sys.argv[sys.argv.index('--debug')]
if '--seed' in sys.argv:
p = sys.argv.index('--seed')
if len(sys.argv) <= p+1:
print ('Missing <int> for --seed')
sys.exit(1)
seed = int(sys.argv[p+1])
del sys.argv[p+1]
del sys.argv[p]
if '--oldseed' in sys.argv:
oldseed = True
del sys.argv[sys.argv.index('--oldseed')]
if '--alpha' in sys.argv:
p = sys.argv.index('--alpha')
if len(sys.argv) <= p+1:
print ('Missing <float> for --alpha')
sys.exit(1)
alpha = float(sys.argv[p+1])
del sys.argv[p+1]
del sys.argv[p]
if len(sys.argv) < 5:
print ('Missing arg...')
sys.exit(1)
fn1 = sys.argv[2]
fn2 = sys.argv[3]
fn3 = sys.argv[4]
import random
import cv2 #opencv-python
# OpenCV是以(BGR)的顺序存储图像数据的
# 而Matplotlib是以(RGB)的顺序显示图像的
def bgr_to_rgb(img):
b, g, r = cv2.split(img)
return cv2.merge([r, g, b])
#random.shuffle的random关键字炸了喵
def old_shuffle(x):
for i in reversed(range(1, len(x))):
j = int( random.random() * (i + 1) )
x[i], x[j] = x[j], x[i]
import numpy as np
import matplotlib.pyplot as plt
if not debug:
import matplotlib
matplotlib.use('Agg')
if cmd == 'encode':
print ('image<%s> + watermark<%s> -> image(encoded)<%s>' % (fn1, fn2, fn3))
img = cv2.imread(fn1)
wm = cv2.imread(fn2)
if img is None: raise FileNotFoundError("can't find %s"%fn1)
if wm is None: raise FileNotFoundError("can't find %s"%fn2)
if debug:
plt.subplot(231), plt.imshow(bgr_to_rgb(img)), plt.title('image')
plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(bgr_to_rgb(wm)), plt.title('watermark')
plt.xticks([]), plt.yticks([])
# print img.shape # 高, 宽, 通道
h, w = img.shape[0], img.shape[1]
hwm = np.zeros((int(h * 0.5), w, img.shape[2]))
assert hwm.shape[0] > wm.shape[0]
assert hwm.shape[1] > wm.shape[1]
hwm2 = np.copy(hwm)
for i in range(wm.shape[0]):
for j in range(wm.shape[1]):
hwm2[i][j] = wm[i][j]
if oldseed: random.seed(seed,version=1)
else: random.seed(seed)
m, n = list(range(hwm.shape[0])), list(range(hwm.shape[1]))
if oldseed:
old_shuffle(m)
old_shuffle(n)
else:
random.shuffle(m)
random.shuffle(n)
for i in range(hwm.shape[0]):
for j in range(hwm.shape[1]):
hwm[i][j] = hwm2[m[i]][n[j]]
rwm = np.zeros(img.shape)
for i in range(hwm.shape[0]):
for j in range(hwm.shape[1]):
rwm[i][j] = hwm[i][j]
rwm[rwm.shape[0] - i - 1][rwm.shape[1] - j - 1] = hwm[i][j]
if debug:
plt.subplot(235), plt.imshow(bgr_to_rgb(rwm)), \
plt.title('encrypted(watermark)')
plt.xticks([]), plt.yticks([])
f1 = np.fft.fft2(img)
f2 = f1 + alpha * rwm
_img = np.fft.ifft2(f2)
if debug:
plt.subplot(232), plt.imshow(bgr_to_rgb(np.real(f1))), \
plt.title('fft(image)')
plt.xticks([]), plt.yticks([])
img_wm = np.real(_img)
assert cv2.imwrite(fn3, img_wm, [int(cv2.IMWRITE_JPEG_QUALITY), 100])
# 这里计算下保存前后的(溢出)误差
img_wm2 = cv2.imread(fn3)
sum = 0
for i in range(img_wm.shape[0]):
for j in range(img_wm.shape[1]):
for k in range(img_wm.shape[2]):
sum += np.power(img_wm[i][j][k] - img_wm2[i][j][k], 2)
miss = np.sqrt(sum) / (img_wm.shape[0] * img_wm.shape[1] * img_wm.shape[2]) * 100
print ('Miss %s%% in save' % miss)
if debug:
plt.subplot(233), plt.imshow(bgr_to_rgb(np.uint8(img_wm))), \
plt.title('image(encoded)')
plt.xticks([]), plt.yticks([])
f2 = np.fft.fft2(img_wm)
rwm = (f2 - f1) / alpha
rwm = np.real(rwm)
wm = np.zeros(rwm.shape)
for i in range(int(rwm.shape[0] * 0.5)):
for j in range(rwm.shape[1]):
wm[m[i]][n[j]] = np.uint8(rwm[i][j])
for i in range(int(rwm.shape[0] * 0.5)):
for j in range(rwm.shape[1]):
wm[rwm.shape[0] - i - 1][rwm.shape[1] - j - 1] = wm[i][j]
if debug:
assert cv2.imwrite('_bwm.debug.wm.jpg', wm)
plt.subplot(236), plt.imshow(bgr_to_rgb(wm)), plt.title(u'watermark')
plt.xticks([]), plt.yticks([])
if debug:
plt.show()
elif cmd == 'decode':
print ('image<%s> + image(encoded)<%s> -> watermark<%s>' % (fn1, fn2, fn3))
img = cv2.imread(fn1)
img_wm = cv2.imread(fn2)
if img is None: raise FileNotFoundError("can't find %s"%fn1)
if img_wm is None: raise FileNotFoundError("can't find %s"%fn2)
if debug:
plt.subplot(231), plt.imshow(bgr_to_rgb(img)), plt.title('image')
plt.xticks([]), plt.yticks([])
plt.subplot(234), plt.imshow(bgr_to_rgb(img_wm)), plt.title('image(encoded)')
plt.xticks([]), plt.yticks([])
if oldseed: random.seed(seed,version=1)
else: random.seed(seed)
m, n = list(range(int(img.shape[0] * 0.5))), list(range(img.shape[1]))
if oldseed:
old_shuffle(m)
old_shuffle(n)
else:
random.shuffle(m)
random.shuffle(n)
f1 = np.fft.fft2(img)
f2 = np.fft.fft2(img_wm)
if debug:
plt.subplot(232), plt.imshow(bgr_to_rgb(np.real(f1))), \
plt.title('fft(image)')
plt.xticks([]), plt.yticks([])
plt.subplot(235), plt.imshow(bgr_to_rgb(np.real(f1))), \
plt.title('fft(image(encoded))')
plt.xticks([]), plt.yticks([])
rwm = (f2 - f1) / alpha
rwm = np.real(rwm)
if debug:
plt.subplot(233), plt.imshow(bgr_to_rgb(rwm)), \
plt.title('encrypted(watermark)')
plt.xticks([]), plt.yticks([])
wm = np.zeros(rwm.shape)
for i in range(int(rwm.shape[0] * 0.5)):
for j in range(rwm.shape[1]):
wm[m[i]][n[j]] = np.uint8(rwm[i][j])
for i in range(int(rwm.shape[0] * 0.5)):
for j in range(rwm.shape[1]):
wm[rwm.shape[0] - i - 1][rwm.shape[1] - j - 1] = wm[i][j]
assert cv2.imwrite(fn3, wm)
if debug:
plt.subplot(236), plt.imshow(bgr_to_rgb(wm)), plt.title(u'watermark')
plt.xticks([]), plt.yticks([])
if debug:
plt.show()
得到后半部分flag

原图和新图2盲水印没什么东西,对新图2zsteg分析得到前半部分flag
把得到的拼接获得flag
hxb2018{490fe1033073e985ef4526a41ea903ef}


被折叠的 条评论
为什么被折叠?



