ctf misc学习之旅week9

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}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值