题1


题目均为复现

simpleness

题目描述:

1
压缩包密码是个弱口令呢!

下载附件

根据提示压缩包密码是弱口令,按解题顺序的压缩包应该是hint–key–flag

先爆破hint.zip压缩包密码

解压压缩包得到

先看图片吧

binwalk提取试试

得到一张二维码图片,扫描二维码得到

到这边暂时没什么发现了,查看hint.rar,伪加密破解

根据hint:

1
key.zip的密码范围是qsnctf大小写哦,解出来的密码可以多次使用

爆破key.zip压缩包密码

干爆破太慢,所以需要生成一个qsnctf大小写组合的字典进行爆破

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def generate_case_combinations(s):
# 初始化一个空列表来存储所有组合
combinations = []

# 遍历字符串的每个字符,生成所有可能的组合
# 使用二进制表示每个字符的大小写状态(0表示小写,1表示大写)
for i in range(2**len(s)):
# 将二进制数转换为字符串形式,并去掉'0b'前缀
binary_rep = bin(i)[2:].zfill(len(s))
# 根据二进制表示生成对应的大小写组合
case_combination = ''.join(
char.upper() if bit == '1' else char.lower()
for char, bit in zip(s, binary_rep)
)
# 将生成的组合添加到列表中
combinations.append(case_combination)

return combinations

# 调用函数并打印结果
combinations = generate_case_combinations("qsnctf")
for combo in combinations:
print(combo)

运行得到

保存为文本,进行字典爆破

解压压缩包得到

根据hint:

1
提示一:需要这个版本的工具解码SilentEye0.3.1,这个版本不一样解不出来,没考虑到版本问题,对不起大家

静默之眼3.0

想到上面的qsnctf大小写组合的密码可以多次使用,考虑密码是QsNcTf

选择AES128模式解密

保存并查看1.txt

零宽解密

密码是

1
The password is Hello World

解压flag.zip得到

查看key.txt

snow隐写

根据hint:

1
flag压缩包的密码是中文

中文电码解码

flag.zip压缩包密码为

1
这是密码吗

解压压缩包得到

图片不显示,010查看

发现文件字节不仅逆序而且还奇偶分离

奇偶分离脚本

1
2
3
4
5
6
7
8
9
10
11
12
# 打开并读取名为flag.jpg的文件内容到变量s中
with open("E:\\脚本合集\\misc\\buuctf misc\\奇偶分离\\flag.jpg", "rb") as f:
s = f.read()

# 以二进制写模式打开一个新的文件flag1.jpg,准备写入处理后的数据
with open("E:\\脚本合集\\misc\\buuctf misc\\奇偶分离\\flag1.jpg", "wb") as a:
# 遍历s中的每个4字节块
for i in range(0, len(s), 4):
# 对每个4字节块进行反转操作
s1 = s[i:i+4][::-1]
# 将处理后的4字节块写入新文件
a.write(s1)

运行生成一张图片,010查看

发现文件就光逆序了,直接b神工具一把梭

查看图片

一眼图片宽高有问题,还是b神工具一把梭得到flag

可乐加冰

下载附件

binwallk分离

查看2AE96文件

提取数

1
83 46 36 36 36 95 43 83 46 36 95 95 36 43 83 46 95 95 95 43 83 46 95 95 36 43 83 46 36 36 36 36 43 83 46 36 36 36 95 43 83 46 36 95 95 36 43 83 46 95 95 36 43 34 45 34 43 83 46 36 95 36 36 43 83 46 36 95 36 95 43 83 46 36 36 95 36 43 83 46 36 36 95 43 34 45 34 43 83 46 36 95 95 43 83 46 36 95 36 95 43 83 46 36 36 36 36 43 83 46 36 36 36 43 34 45 34 43 83 46 36 95 95 36 43 83 46 36 95 95 36 43 83 46 36 36 95 43 83 46 95 36 36 43 34 45 34 43 83 46 36 36 95 36 43 83 46 36 95 36 95 43 83 46 36 36 95 36 43 83 46 36 95 95 95 43 83 46 95 95 36 43 83 46 95 36 95 43 83 46 36 36 36 36 43 83 46 36 95 36 43 83 46 36 36 95 43 83 46 95 36 95 43 83 46 36 95 95 43 83 46 36 36 95 36

十进制转字符串

将其中的S替换成$,并补全JJencode的开头结尾

1
$.$$$_+$.$__$+$.___+$.__$+$.$$$$+$.$$$_+$.$__$+$.__$+"-"+$.$_$$+$.$_$_+$.$$_$+$.$$_+"-"+$.$__+$.$_$_+$.$$$$+$.$$$+"-"+$.$__$+$.$__$+$.$$_+$._$$+"-"+$.$$_$+$.$_$_+$.$$_$+$.$___+$.__$+$._$_+$.$$$$+$.$_$+$.$$_+$._$_+$.$__+$.$$_$

JJencode格式

1
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+这里放密文+"\"")())();

完整的JJencode密文

1
2
$=~[];$={___:++$,$$$$:(![]+"")[$],__$:++$,$_$_:(![]+"")[$],_$_:++$,$_$$:({}+"")[$],$$_$:($[$]+"")[$],_$$:++$,$$$_:(!""+"")[$],$__:++$,$_$:++$,$$__:({}+"")[$],$$_:++$,$$$:++$,$___:++$,$__$:++$};$.$_=($.$_=$+"")[$.$_$]+($._$=$.$_[$.__$])+($.$$=($.$+"")[$.__$])+((!$)+"")[$._$$]+($.__=$.$_[$.$$_])+($.$=(!""+"")[$.__$])+($._=(!""+"")[$._$_])+$.$_[$.$_$]+$.__+$._$+$.$;$.$$=$.$+(!""+"")[$._$$]+$.__+$._+$.$+$.$$;$.$=($.___)[$.$_][$.$_];$.$($.$($.$$+"\""+$.$$$_+$.$__$+$.___+$.__$+$.$$$$+$.$$$_+$.$__$+$.__$+"-"+$.$_$$+$.$_$_+$.$$_$+$.$$_+"-"+$.$__+$.$_$_+$.$$$$+$.$$$+"-"+$.$__$+$.$__$+$.$$_+$._$$+"-"+$.$$_$+$.$_$_+$.$$_$+$.$___+$.__$+$._$_+$.$$$$+$.$_$+$.$$_+$._$_+$.$__+$.$$_$
+"\"")())();

jjencode解码

最后flag为

1
flag{e901fe91-bad6-4af7-9963-dad812f5624}

boooooom

下载附件

发现有密码

直接爆破密码

解压压缩包得到

password.py

1
2
3
4
5
6
7
8
9
import base64
import hashlib
f = open("password.txt",'r')
password = f.readline()
b64_str = base64.b64encode(password.encode('utf-8'))
hash = hashlib.md5()
hash.update(b64_str)
zip_passowrd = hash.hexdigest()
print(zip_passowrd)

查看password.zip

crc爆破八字节难度有点大,直接内容为八位数字的CRC爆破

1
2
3
4
5
6
7
8
9
10
11
12
#encoding:utf-8
import binascii

pwdcrc = "0xcd95dac"
for num in range(100000000):
num = str(num)
if (len(num)<8):
num = (8-len(num)) * '0' + num
calc_crc = hex(binascii.crc32(bytes(num.encode('utf8'))) & 0xffffffff)
if calc_crc == pwdcrc:
print("Password: {}".format(num))
break

运行得到

根据password.py先将08646247base64编码后再md5加密

压缩包密码为

1
95c800c52134a571dfe69114c378e4be

解压压缩包得到

宽高一把梭

最后flag为

1
flag{a184929e2c170e2b7dc12eb3106f0a16}

steganography

题目描述:

1
有一天,V的同学给了他一张图片,说里面藏着巨大的秘密。你能帮V找出秘密么?

下载附件

foremost分离

有个docx文件和压缩包里是pyc文件

docx改zip查看

发现flag.xml,010查看

20替换0,09替换1,二进制解码

压缩包里面的pyc解压发现有密码,查看word文档内容

一眼base隐写

得到压缩包密码

1
I4mtHek3y@

解压压缩包得到pyc文件,直接pyc隐写一把梭

最后flag为

1
flag{2806105f-ec43-57f3-8cb4-1add2793f508}

HALF

下载附件

010查看文件,发现还藏着一个png文件,缺少文件头

新建一个空白文件,hex模式,添加文件头

保存为half1.png

一眼双图盲水印攻击

得到

1
hLY8OTR4H}

stegsolve查看,GBR模式

最后flag为

1
flag{EwCuWKbhLY8OTR4H}

miscmisc

下载附件

foremost分离

010查看chadian.jpg,发现是png文件,而且隐藏zip文件

提取出来解压压缩包

额,假flag,chayidian.zip里也有这个flag.txt,考虑明文攻击

解压压缩包

查看png文件

stegsolve查看

pass:z^ea

发现解压错误,估计是密码不全,查看word文件,勾选隐藏文字发现

压缩包密码是 z^ea 加上这里每行字符串最后一个

1
z^ea4zaa3azf8

解压压缩包得到

最后flag为

1
flag{12sad7eaf46a84fe9q4fasf48e6q4f6as4f864q9e48f9q4fa6sf6f48}

My_lllp

题目描述:

1
你能发现图片中隐藏的秘密吗

下载附件

foremost分离得到压缩包

发现zip有注释信息:也许名称能给你想要的

联想带密码的图片隐写考虑cloacked-pixel隐写,密码为My_lllp

解压压缩包得到

snow隐写得到

base解密得到flag

最后flag为

1
DASCTF{C0ngratU1ati0nS_On_Finding_the_f1ag}

depthpng

题目描述:

1
不一般的png

下载附件

zsteg一把梭

b1,g,lsb,yx区域藏有zip压缩包,提取出来

1
zsteg depthpng.png -E b1,g,lsb,yx > dapthpng.zip

解压压缩包得到

.swp文件恢复

1
vim -r .flag.txt.swp

报错了,创建一个名为“chang”的用户

1
sudo useradd -m chang

读取 /etc/passwd 看看有没有创建成功

1
cat /etc/passwd | grep "chang"

建两个子目录:/Downloads/Misc/

1
2
3
4
cd /home/chang
sudo mkdir Downloads
cd /home/chang/Downloads
sudo mkdir Misc

再去恢复一下上面的.swp文件

查看flag.txt

没什么发现,发现压缩包加密的txt算法是zipcrypto

通过.swp恢复的flag.txt重命名为swp.txt,bkcrack爆破

1
bkcrack.exe -C dapthpng.zip -c flag.txt -p swp.txt

修改密码

1
bkcrack.exe -C dapthpng.zip -k 6c30e526 874fd386 341fe8cb -U ddd.zip 123456

解压压缩包得到
vv

最后flag为

1
DASCTF{566320af8bd05701e095f5e38338a734}

Simple_steganography

题目描述:

1
加菲把flag分成两部分了(跟猫有关,且flag为俩部分)

下载附件

查看hint文本内容

一眼猫脸变换参数,但是没有图片,查看压缩包文件

发现都加密了文件,尝试爆破,伪加密无果,

考虑ntfs隐写

导出图片

扫描二维码得到假flag

尝试foremost分离图片

猫脸变换

得到第二部分flag

1
3_h4ck1ng

查看压缩包加密算法

和上个题一样,使用bkcrack爆破

先构造png文件头文件

1
echo 89504E470D0A1A0A0000000D49484452 | xxd -r -ps > png_header

然后爆破密钥

1
bkcrack.exe -C secret.zip -c flag.png -p png_header  -o 0

修改密码

1
bkcrack.exe -C secret.zip -k f45dd89f e3e929fb 3202ba17  -U tmp.zip 123456

解压压缩包得到

修改宽高得到第一部分flag

最后flag为

1
flag{We_l1k3_h4ck1ng}

三项之力

题目描述:

1
你说的对,但是《三相之力》是由 Muscer 自主研发的一款全新杂项套娃题。……中间忘了……。总之你将扮演一位名为「Misc手」的神秘角色,在小小的附件中邂逅「Reversed」、「Gopher esolang」、「Bitmap RGBA」,找回失散的flag碎片——同时,逐步发掘「套娃」的真相。

下载附件

zsteg一把梭

提取zip

1
zsteg flag.png -E b1,g,lsb,xy > flag.zip

解压压缩包发现有密码

stegsolve提取r0通道

保存文本,逆序得到二维码

扫描二维码得到

stegsolve提取b0通道保存补上bmp文件头

1
424DC703030000000000370000002800000064000000640000000100200000000000180000000000000000000000000000000000000000

得到二维码

扫描二维码得到

两部分组合压缩包密码为

1
0d000721_114514_1919810_089d7147-6786-42b5-b81e-3b7e050304a6

解压压缩包得到

Gopher esolang解码

https://shubshub.github.io/gopher/

最后flag为

1
flag{7a874085-53d5-4baf-96ed-40d73013e67b}

银河救援SOS!

题目描述:

1
题目描述:出题人被外星人抓走了!他们说只要你能找到FLAG就放了出题人,救救出题人! (flag全是大写字母,并且没有空格)

下载附件

查看图片文件

标准银河字母对照表得到

对照得到superalien

解压压缩包得到

一眼明文攻击(使用7z压缩)

明文攻击

保存并解压压缩包

查看1.jpg图片属性

按顺序提取每张图片的经纬度做点,然后按点顺序依次连线

参考大佬脚本

湘岚杯web-misc-wp_ctf湘岚杯-CSDN博客

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
import os
from PIL import Image
from PIL.ExifTags import TAGS
import matplotlib.pyplot as plt


def dms_to_decimal(degrees, minutes, seconds):
return degrees + (minutes / 60) + (seconds / 3600)


x = []
y = []

for i in range(0, 81):
# 使用 f-string 格式化文件路径
file_name = f"C:\\Users\\23831\\Desktop\\银河救援SOS\\外星人留下的压缩包\地球轨迹_decrypted\\地球轨迹\\{i}.jpg"

if os.path.exists(file_name):
print(f"EXIF {file_name}")

image = Image.open(file_name)
exif_data = image._getexif()

if exif_data is not None:
for tag, value in exif_data.items():
tag_name = TAGS.get(tag, tag)
if tag_name == "GPSInfo": # 检查是否为 GPS 信息
print(f"GPSInfo: {value}")
# 提取经纬度(度分秒格式)
x_dms_coordinate = (value[2][0], value[2][1], value[2][2])
y_dms_coordinate = (value[4][0], value[4][1], value[4][2])

# 将度分秒转换为十进制
x_decimal_coordinate = dms_to_decimal(*x_dms_coordinate)
y_decimal_coordinate = dms_to_decimal(*y_dms_coordinate)

# 添加到坐标列表
x.append(x_decimal_coordinate)
y.append(y_decimal_coordinate)

print(f'Processed {file_name}: Latitude (x) = {x_decimal_coordinate}, Longitude (y) = {y_decimal_coordinate}')
else:
print(f"No EXIF data found in {file_name}")

print("=" * 100)
else:
print(f"{file_name} does not exist")
print("=" * 100)

# 输出最终的坐标列表
print("X list (Latitude):", x)
print("Y list (Longitude):", y)

# 检查是否有有效坐标
if not x or not y:
print("No valid coordinates to plot.")
else:
# 绘制散点图并连线
plt.scatter(y, x, color="blue")
for i in range(len(x) - 1):
plt.annotate("", xy=(y[i + 1], x[i + 1]), xytext=(y[i], x[i]),
arrowprops=dict(arrowstyle="-", color="red", lw=2))
plt.xlabel('Longitude (y)')
plt.ylabel('Latitude (x)')
plt.title("GPS Coordinates from Images")
plt.grid(True)
plt.show()

运行得到

最后flag为

1
flag{UHATCANITALK}

cat

下载附件

查看cat.png

cat_encode.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21

def arnold_encode(image, shuffle_times, a, b):

arnold_image = np.zeros(shape=image.shape)

h, w = image.shape[0], image.shape[1]
N = h

for time in range(shuffle_times):
for ori_x in range(h):
for ori_y in range(w):

new_x = (1*ori_x + b*ori_y)% N
new_y = (a*ori_x + (a*b+1)*ori_y) % N

arnold_image[new_x, new_y, :] = image[ori_x, ori_y, :]

image = np.copy(arnold_image)

cv2.imwrite('cat.png', arnold_image, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])
return arnold_image

一眼猫脸变换,没给参数,直接爆破

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
import matplotlib.pyplot as plt
import cv2
import numpy as np

def arnold_decode(image, shuffle_times, a, b):
""" decode for rgb image that encoded by Arnold
Args:
image: rgb image encoded by Arnold
shuffle_times: how many times to shuffle
Returns:
decode image
"""
# 1:创建新图像
decode_image = np.zeros(shape=image.shape)
# 2:计算N
h, w = image.shape[0], image.shape[1]
N = h # 或N=w

# 3:遍历像素坐标变换
for time in range(shuffle_times):
for ori_x in range(h):
for ori_y in range(w):
# 按照公式坐标变换
new_x = ((a * b + 1) * ori_x + (-b) * ori_y) % N
new_y = ((-a) * ori_x + ori_y) % N
decode_image[new_x, new_y, :] = image[ori_x, ori_y, :]
image = np.copy(decode_image)

return image

def arnold_brute(image,shuffle_times_range,a_range,b_range):
for c in range(shuffle_times_range[0],shuffle_times_range[1]):
for a in range(a_range[0],a_range[1]):
for b in range(b_range[0],b_range[1]):
print(f"[+] Trying shuffle_times={c} a={a} b={b}")
decoded_img = arnold_decode(image,c,a,b)
output_filename = f"flag_decodedc{c}_a{a}_b{b}.png"
cv2.imwrite(output_filename, decoded_img, [int(cv2.IMWRITE_PNG_COMPRESSION), 0])

if __name__ == "__main__":
img = cv2.imread("C:\\Users\\23831\\Desktop\\424ebe63-7574-4a17-a966-8fb4721073a1\\cat.png")
arnold_brute(img, (0,6), (1,11), (1,11))

运行发现shuffle_times=3、a=6、b=9得到flag

最后flag为

1
flag{022ae0e0-c61e-428c-9f76-2eb089a58348}

成语学习

题目描述:

1
我把学习资料拷贝给你一份

下载附件

先看流量包文件,直接ctfnat-A一把梭

一眼宽高爆破,直接一把梭

解压压缩包得到

010查看文件发现是zip文件,保存到本地

解压压缩包得到

一大堆文件,直接find命令找有关flag的字符串

1
find ./* -name fl*

hmac解密

HMAC在线加密工具 - HmacMD5在线加密 - HmacRipeMD在线加密 - MKLab在线工具

最后flag为

1
ISCC{86bd2a65ea0d68bf231dd5c0a9c5e8c1}

精装四合一

题目描述:

1
分离,我们是破碎的;团结,我们将成为神。我们终将在二进制的反复与隐藏之中破解自身的密码

下载附件

010查看文件

发现有冗余数据,删去图中AE 42 60 82及之前的数据,然后进行xor 0xff(每个图片进行同样操作)

很显然这是个zip数据,依次读取4个文件拼接成生成zip文件

首先将这四个图片重新命名1-4.png

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
fp1 = open('1.png','rb')
fp2 = open('2.png','rb')
fp3 = open('3.png','rb')
fp4 = open('4.png','rb')
fp5 = open('5.zip','wb')
#如果是4b,就是2.png
#如果是03,就是3.png
#如果是04,就是4.png
for i in range(3176):
fp5.write(fp1.read(1))
fp5.write(fp2.read(1))
fp5.write(fp3.read(1))
fp5.write(fp4.read(1))

fp5.write(fp1.read())

脚本和文件在同一目录下运行得到

解压压缩包发现有密码

爆破压缩包

打开word文档

修改字体颜色,去除覆盖物发现隐藏文字

根据压缩包密码为65537,猜测这串数是rsa里的n,分解n

没有c密文还是不行,尝试分离docx文件

直接rsa一把梭

最后flag为

1
ISCC{515UH54TyH53144}

钢铁侠在解密

下载附件

txt内容

1
2
3
4
5
N = 14333611673783142269533986072221892120042043537656734360856590164188122242725003914350459078347531255332508629469837960098772139271345723909824739672964835254762978904635416440402619070985645389389404927628520300563003721921925991789638218429597072053352316704656855913499811263742752562137683270151792361591681078161140269916896950693743947015425843446590958629225545563635366985228666863861856912727775048741305004192164068930881720463095045582233773945480224557678337152700769274051268380831948998464841302024749660091030851843867128275500525355379659601067910067304244120384025022313676471378733553918638120029697
e = 52595
a=1
[message]iscc
[message]good

富兰克林攻击,缺少c1,c2

尝试静默之眼隐写

导出文本

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
def HGCD(a, b):
if 2 * b.degree() <= a.degree() or a.degree() == 1:
return 1, 0, 0, 1
m = a.degree() // 2
a_top, a_bot = a.quo_rem(x ^ m)
b_top, b_bot = b.quo_rem(x ^ m)
R00, R01, R10, R11 = HGCD(a_top, b_top)
c = R00 * a + R01 * b
d = R10 * a + R11 * b
q, e = c.quo_rem(d)
d_top, d_bot = d.quo_rem(x ^ (m // 2))
e_top, e_bot = e.quo_rem(x ^ (m // 2))
S00, S01, S10, S11 = HGCD(d_top, e_top)
RET00 = S01 * R00 + (S00 - q * S01) * R10
RET01 = S01 * R01 + (S00 - q * S01) * R11
RET10 = S11 * R00 + (S10 - q * S11) * R10
RET11 = S11 * R01 + (S10 - q * S11) * R11
return RET00, RET01, RET10, RET11


def GCD(a, b):
print(a.degree(), b.degree())
q, r = a.quo_rem(b)
if r == 0:
return b
R00, R01, R10, R11 = HGCD(a, b)
c = R00 * a + R01 * b
d = R10 * a + R11 * b
if d == 0:
return c.monic()
q, r = c.quo_rem(d)
if r == 0:
return d
return GCD(d, r)
#填入你的
c1 = 5017369768694090882032874151790454013801219395405287358207261245363256829248608596502248566398520888429123068081569109393280813077504052950602807292263976569549950695855034991600627474248601023155417605655770430049715209036466126332158721754416840461535178102241673458740266136324362194445284419127770862459105202409819693263389282320915294170572475633725510148135550165243317205799536627815353543347307896706247209832387038159128207210034149401836142035780479451946680015887015805801833689166356479093336955344013041439948376767333629389510835402505659305883721660844242226225426796547014196608222731396847442033989
c2 = 507384238405164894777070216936058414248957470621682465979969565874673475531556308157966971978727929187885326824096036880804838325461008248518925654961162689385362314521317488538713528411196811305410646950164637167443757506100731566433818518444499218820451016697511365389342947997664515635533495319642108557081560343565725150552083709866564355720051752298333524185795164369635622805913094004540556292465465504776524188179971013639183466958695108211645591808065992454954828366833086197711882310642589818019027277798204029101473373561664384967568947638228117979763658236419828589469635113089784255797757642551645627462
N = 14333611673783142269533986072221892120042043537656734360856590164188122242725003914350459078347531255332508629469837960098772139271345723909824739672964835254762978904635416440402619070985645389389404927628520300563003721921925991789638218429597072053352316704656855913499811263742752562137683270151792361591681078161140269916896950693743947015425843446590958629225545563635366985228666863861856912727775048741305004192164068930881720463095045582233773945480224557678337152700769274051268380831948998464841302024749660091030851843867128275500525355379659601067910067304244120384025022313676471378733553918638120029697
e = 52595

pad1 = 1769169763
pad2 = 1735356260
PR.<x>=PolynomialRing(Zmod(N))
g1 = (x*2^32+pad1)^e - c1
g2 = (x*2^32+pad2)^e - c2
X=584734024210292804199275855856518183354184330877
print(g1(X),g2(X))
res = GCD(g1,g2)
m = -res.monic().coefficients()[0]
print(m)

print(bytes.fromhex(hex(m)[2:]).decode().replace("flag{",'ISCC{'))

sage运行得到flag

最后flag为

1
ISCC{he_guang_tong_chen_253}

重“隐”

下载附件

foremost分离图片

发现有密码,尝试听音频发现是拨号音

直接dtmf2num

九键转换得到

1
URHDBDFGE

解压压缩包得到

brainfuck解密

得到第一部分flag

使用deepsound解密音频发现有密码

通过deepsound2john.py脚本来获得密码的hash值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#! python3

import logging
import os
import sys
import textwrap

def decode_data_low(buf):
return buf[::2]

def decode_data_normal(buf):
out = bytearray()
for i in range(0, len(buf), 4):
out.append((buf[i] & 15) << 4 | (buf[i + 2] & 15))
return out

def decode_data_high(buf):
out = bytearray()
for i in range(0, len(buf), 8):
out.append((buf[i] & 3) << 6 | (buf[i + 2] & 3) << 4 \
| (buf[i + 4] & 3) << 2 | (buf[i + 6] & 3))
return out


def is_magic(buf):
# This is a more efficient way of testing for the `DSCF` magic header without
# decoding the whole buffer
return (buf[0] & 15) == (68 >> 4) and (buf[2] & 15) == (68 & 15) \
and (buf[4] & 15) == (83 >> 4) and (buf[6] & 15) == (83 & 15) \
and (buf[8] & 15) == (67 >> 4) and (buf[10] & 15) == (67 & 15) \
and (buf[12] & 15) == (70 >> 4) and (buf[14] & 15) == (70 & 15)

def is_wave(buf):
return buf[0:4] == b'RIFF' and buf[8:12] == b'WAVE'


def process_deepsound_file(f):
bname = os.path.basename(f.name)
logger = logging.getLogger(bname)

# Check if it's a .wav file
buf = f.read(12)
if not is_wave(buf):
global convert_warn
logger.error('file not in .wav format')
convert_warn = True
return
f.seek(0, os.SEEK_SET)
# Scan for the marker...
hdrsz = 104
hdr = None
while True:
off = f.tell()
buf = f.read(hdrsz)
if len(buf) < hdrsz: break
if is_magic(buf):
hdr = decode_data_normal(buf)
logger.info('found DeepSound header at offset %i', off)
break
f.seek(-hdrsz + 1, os.SEEK_CUR)
if hdr is None:
logger.warn('does not appear to be a DeepSound file')
return
# Check some header fields
mode = hdr[4]
encrypted = hdr[5]
modes = {2: 'low', 4: 'normal', 8: 'high'}
if mode in modes:
logger.info('data is encoded in %s-quality mode', modes[mode])
else:
logger.error('unexpected data encoding mode %i', modes[mode])
return
if encrypted == 0:
logger.warn('file is not encrypted')
return
elif encrypted != 1:
logger.error('unexpected encryption flag %i', encrypted)
return
sha1 = hdr[6:6+20]
print('%s:$dynamic_1529$%s' % (bname, sha1.hex()))
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('--verbose', '-v', action='store_true')
parser.add_argument('files', nargs='+', metavar='file',
type=argparse.FileType('rb', bufsize=4096))
args = parser.parse_args()
if args.verbose:
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig(level=logging.WARN)
convert_warn = False
for f in args.files:
process_deepsound_file(f)
if convert_warn:
print(textwrap.dedent.rstrip(), file=sys.stderr)

运行代码

1
python dp.py music.wav > hash.txt

john爆破

1
john hash.txt

deepsound解密导出文件

零宽解密

base58解密

最后flag为

1
ISCC{y0u_f1nd_t74_re2l_w4t3rm4rk}

World_LIne

非预期做法

flag被分成了四份,只需看β文件夹

flag1:

在β中的拼图文件中,在321_19704.png里,010查看文件

flag2:

flag2在β中的拼图文件中,位于123123_9049 (0U_f4N).png,括号里就是flag2

flag3:

flag3在β中的拼图文件夹的8787下,

flag4:

在RSA文件中,是NKCTF2024原题,直接拿NKCTF的脚本梭βase64.txt

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import base64
from urllib.parse import unquote
import libnum
from Crypto.PublicKey import RSA

pubkey = """-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCK/qv5P8ixWjoFI2rzF62tm6sDFnRsKsGhVSCuxQIxuehMWQLmv6TPxyTQPefIKufzfUFaca/YHkIVIC19ohmE5X738TtxGbOgiGef4bvd9sU6M42k8vMlCPJp1woDFDOFoBQpr4YzH4ZTR6Ps+HP8VEIJMG5uiLQOLxdKdxi41QIDAQAB
-----END PUBLIC KEY-----
"""

prikey = """-----BEGIN PRIVATE KEY-----
MIICdgIBADANBgkqhkiG9w0BAQEFAASCAmAwggJcAgEAAoGBAIr+q/k/yLFaOgUjavMXra2bqwMWdGwqwaFVIK7FAjG56ExZAua/pM/HJNA958gq5/N9QVpxr9geQhUgLX2iGYTlfvfxO3EZs6CIZ5/hu932xTozjaTy8yUI8mnXCgMUM4WgFCmvhjMfhlNHo+z4c/xUQgkwbm6ItA4vF0p3GLjVAgMBAAECgYBDsqawT5DAUOHRft6oZ+//jsJMTrOFu41ztrKkbPAUqCesh+4R1WXAjY4wnvY1WDCBN5CNLLIo4RPuli2R81HZ4OpZuiHv81sNMccauhrJrioDdbxhxbM7/jQ6M9YajwdNisL5zClXCOs1/y01+9vDiMDk0kX8hiIYlpPKDwjqQQJBAL6Y0fuoJng57GGhdwvN2c656tLDPj9GRi0sfeeMqavRTMz6/qea1LdAuzDhRoS2Wb8ArhOkYns0GMazzc1q428CQQC6sM9OiVR4EV/ewGnBnF+0p3alcYr//Gp1wZ6fKIrFJQpbHTzf27AhKgOJ1qB6A7P/mQS6JvYDPsgrVkPLRnX7AkEAr/xpfyXfB4nsUqWFR3f2UiRmx98RfdlEePeo9YFzNTvX3zkuo9GZ8e8qKNMJiwbYzT0yft59NGeBLQ/eynqUrwJAE6Nxy0Mq/Y5mVVpMRa+babeMBY9SHeeBk22QsBFlt6NT2Y3Tz4CeoH547NEFBJDLKIICO0rJ6kF6cQScERASbQJAZy088sVY6DJtGRLPuysv3NiyfEvikmczCEkDPex4shvFLddwNUlmhzml5pscIie44mBOJ0uX37y+co3q6UoRQg==
-----END PRIVATE KEY-----
"""

pubkey = RSA.import_key(pubkey)
prikey = RSA.import_key(prikey)
n = pubkey.n

def enc_replace(base64_str: str):
base64_str = base64_str.replace("/", "e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM")
base64_str = base64_str.replace("+", "n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W")
return base64_str.replace("=", "JXWUDuLUgwRLKD9fD6&VY2aFeE&r@Ff2")

def encrypt(plain_text):
# 私钥加密
cipher_text = b""
for i in range(0, len(plain_text), 128):
part = plain_text[i:i+128]
enc = libnum.n2s(pow(libnum.s2n(part), prikey.d, n))
cipher_text += enc
return enc_replace(base64.b64encode(cipher_text).decode())

def decrypt(cipher_text):
cipher_text=unquote(cipher_text)
# 恢复原始字符
cipher_text = cipher_text.replace("JXWUDuLUgwRLKD9fD6&VY2aFeE&r@Ff2", "=")
cipher_text = cipher_text.replace("n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W", "+")
cipher_text = cipher_text.replace("e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM", "/")

# 对Base64编码的密文进行解码并进行替换操作
cipher_text = base64.b64decode(cipher_text)

# 使用公钥解密
plain_text = b""
for i in range(0, len(cipher_text), 128):
part = cipher_text[i:i+128]
dec = libnum.n2s(pow(libnum.s2n(part), pubkey.e, n))
plain_text += dec
return plain_text

if __name__ == '__main__':

c = "Ie5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMLpy89FSANlIZfJ67ukKtSeJn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W9LThSWANvhucXgvxcRrJmMuGZkly3XqAnADKTAWitd8jVQWAy8e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMsn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8Wke5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8We5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMoNOIoF75vZe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMiqbjyESmIfvXmL8yGBBgWn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WH5QLxCNvWYSxKYfKQqRj4NMnie6mYHx7a1JijVHeGuH1NS6svJEzn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WN8O47nfLkaoPkBAk0Z5M5xmTYyBCNn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WwShtP6xfjjVYfe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM9kFL88nL5tsHKBHB9S5odZyZEeUUc00ZtmaAjQ3ncvpvy4eoXdcHSjuupx4fRD4jtDp69CoWfgg81PiKcHZPReoREjOrf3KScar6n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WZ5ve3bZiDKmDCPKe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WgsUdkryd4jXE7NpgVn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W75tKRLNqg6pB1gBh27ur0e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeML0EtMUQwnJ5uTkEmlPfqGd0LpcPb9R83AsgqkejBe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM6kNVr7M2coXn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W5YiJsnbV8bRnYSsV1tcYC5RX2ooLwShbvBorPqycWwisUc5n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WFe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMtjVhqpvwDuiryA3spkJ5kYUK6vWY5e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM6guPO0bEa7R16b8VRTCaODDE3u1tmNuRwOPEcazruuEQ2ZS6eqJZpBbc5SYX1e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMMhPe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMRGraXFdNEPu8kpzUOyXpmAoefbYWmyHQLvD5ZS8anphZ8j1rUfYDbE73v6bUTfAkaDWnkrUfevZEp0ze5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMDioZ4n6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W2z0P7IUbe2iFzmsMCHPP7v3SF4ya2wXzDbozjniBVszzrxtBwl9bFsdRIZ46hFNsMfL3k9Eg901H6UT6GtultuTXb91gk8cZjoilx8St00gd6cVghwabbbaYcRCoFLj6sfNs45WFsYEmHe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMSK1gsMZFMn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WF71veALPNhn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WGNd7LShiJrFaB3PZb8klCXPiLR4zlRJchoDyWVlX3mxUf10SaonzNhxCPEocVe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMcilPqA1WV4o7G3e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMIev7RgDZQHf4BYcHcdG6cFlbge5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMYn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W9vsMbUdJFhAhzidDE4zDJGXcx301ILJqprrMn06LWHJhUYc986ijaAO4NCZtsutruIAzzsNZP0tIcIoUaKwxr2tp5Bij4i5BLkQAgHyX6IqYrE7f4sJyOwc2JLOTqhiioJQJN2F09OiZZ4bDoucjJAc0Ylpj3D1jIIMw1hWfHRtwGvdZt1tYxOyxjCiidRwXldOhodAFxMd8lG88PfwmSRwrgXUN2Sw89Gu3h2ZRPR6Ye5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMhHde5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMOasYjovbTZtl7YbHe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMAQTYa7TNggKkjk3Y7VOOK9PP81wVnaD131iYwJcq6e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMAKNYBYcDUiuLNkL40dFcI3YXns3X13h5qxMIgAOvru243MuwVqe2yfgYg4rXltrKfNtn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8W1GxkOMAOe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMMwZBIdQLCNpe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM9lREjxN0WTcwrt9QvUxq7FTERuUg9YAe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMuajUXkjE2jSaLGWxYDlohYAOk90JBPJe1ZVjOq8yosT439GOpgqn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8Wht6TLEAwgIqtYUem2s4Po8Z0joMTNqv2glfFEZfIn3eQK3Lwe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMDRr1ED9F6fMCqIiliPcO8GmjM0DSwZhmsGv1tzaJVeiarL8jKpxv7pIHEEStWuTAaLPn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8Wr3XQ4XesMvzIUWxNGY2grbte4RGS5nSLEPL5FUMorqJHDNgIn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WVgf7RSe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMO86jLQ1pfNUlRFUUPx2IILqSBL7ECDe3h3WK7bkqX7c1ZXbhxcwT7CVqxMGkleWutwY5EGkAGfCdRWb4FNKeDl09F3neYn4nZ2oVIkmjAUPpDeMwJj9FUHSspMuRFY4pMlTMe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMe0g2CKCCkbFsYxHzjPu828AjMitlFNU9nY6DjgvZuFqtn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WWe1J6IZlu5TnHvdpzKCOvTJmezjsDRILSZy5L3O4bFMy7rNAZIZZUyC7V9nLwl87yPGrKUvJagTqCYPcMc1cY73Ugivv5liaA1H46whpNcHWurMv7JAcn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WjxBrk2DJYIkggqbwe5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeM7j0WJzeCb1Gw094VwV59UXm35rCZjsBGWqd6VmfCeFn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WYp8zFWQFy7a7zTYuAQs7e5Lg^FM5EQYe5!yF&62%V$UG*B*RfQeMzzvezWBtxEdU7ttsKdqzgTMXHkhpc524TGORapvzlk1CBZZ8nHkBFlGF4ozRzUWcBbMSp0obpbfLbM2ypkooosJNn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WIr9x22nmn6&B8G6nE@2tt4UR6h3QBt*5&C&pVu8WOXh"
print(f"加密数据: {c}")

decrypted_text = decrypt(c)
print(f"解密数据: {decrypted_text}")
with open("dec.data", "wb") as f:
f.write(decrypted_text)

运行得到

词频统计

最后flag为

1
ISCC{a_h_a!y0U_f4NgdE_tH3_t5uTh} 

Barbar

下载附件

foremost 分离

分离附件二维码后的压缩包,可以得到一个加密的压缩包,提示密钥32位,无法爆破

扫描二维码得到

零宽解密

解压压缩包得到

docx里什么都没有,考虑改后缀.zip查看

一眼base转图片

Aztec解码

npiet隐写

最后flag为

1
flag{f2d76g36fd16cbb6abaaf8db57cbd1ed}

Yusapapa

访问环境

查看源码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

1. Maybe these texts are really helpful for you
2. Biometric list is OK!
3. endow gremlin indulge bison flatfoot fallout goldfish bison hockey
fracture fracture bison goggles jawbone bison flatfoot gremlin
glucose glucose fracture flatfoot indoors gazelle gremlin goldfish
bison guidance indulge keyboard keyboard glucose fracture hockey
bison gazelle goldfish bison cement frighten gazelle goldfish
indoors buzzard highchair fallout highchair bison fallout goldfish
flytrap bison fallout goldfish gremlin indoors frighten fracture
highchair bison cement fracture goldfish flatfoot gremlin flytrap
fracture buzzard guidance goldfish freedom buzzard allow crowfoot
jawbone bison indoors frighten fracture bison involve fallout
jawbone Burbank indoors frighten fracture bison guidance gazelle
flatfoot indoors indulge highchair fracture bison hockey frighten
gremlin indulge flytrap bison flagpole fracture bison indulge hockey
fracture flytrap bison allow blockade endow indulge hockey fallout
blockade bison gazelle hockey bison inverse fracture highchair
jawbone bison gazelle goggles guidance gremlin highchair indoors
fallout goldfish indoors bison gazelle goldfish bison indoors
frighten gazelle hockey bison flatfoot frighten fallout glucose
glucose fracture goldfish freedom fracture blackjack blackjack

PGP词汇表翻译

PGP词汇表_百度百科

1
59 6F 75 20 63 61 6E 20 73 65 65 20 6D 79 20 63 6F 6C 6C 65 63 74 69 6F 6E 20 70 75 7A 7A 6C 65 73 20 69 6E 20 2F 68 69 6E 74 2E 72 61 72 20 61 6E 64 20 61 6E 6F 74 68 65 72 20 2F 65 6E 63 6F 64 65 2E 70 6E 67 2E 0A 42 79 20 74 68 65 20 77 61 79 2C 74 68 65 20 70 69 63 74 75 72 65 20 73 68 6F 75 64 20 62 65 20 75 73 65 64 20 0A 22 59 75 73 61 22 20 69 73 20 76 65 72 79 20 69 6D 70 6F 72 74 61 6E 74 20 69 6E 20 74 68 69 73 20 63 68 61 6C 6C 65 6E 67 65 21 21

赛博厨子一把梭

下载得到hint.rar和encode.png以及网站里的webp文件

stegpy隐写得到压缩包密码

解压压缩包得到

使用Invisiblesecrets解密

导入密件

选择密钥和密码类型

选择解密得到py文件

导出py文件查看

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
import os,random
from PIL import Image,ImageDraw

p=Image.open('flag.png').convert('L')
flag = []
a,b = p.size
for x in range(a):
for y in range(b):
if p.getpixel((x,y)) == 255:
flag.append(0)
else:
flag.append(1)

key1stream = []
for _ in range(len(flag)):
key1stream.append(random.randint(0,1))
random.seed(os.urandom(8))
key2stream = []
for _ in range(len(flag)):
key2stream.append(random.randint(0,1))
enc = []
for i in range(len(flag)):
enc.append(flag[i]^key1stream[i]^key2stream[i])

hide=Image.open('source.png').convert('RGB')
R=[]
G=[]
B=[]
a,b = hide.size
for x in range(a):
for y in range(b):
R.append(bin(hide.getpixel((x,y))[0]).replace('0b','').zfill(8))
G.append(bin(hide.getpixel((x, y))[1]).replace('0b','').zfill(8))
B.append(bin(hide.getpixel((x, y))[2]).replace('0b','').zfill(8))
R1=[]
G1=[]
B1=[]
for i in range(len(key1stream)):
if key1stream[i] == 1:
R1.append(R[i][:7]+'1')
else:
R1.append(R[i][:7]+'0')

for i in range(len(key2stream)):
if key2stream[i] == 1:
G1.append(G[i][:7]+'1')
else:
G1.append(G[i][:7]+'0')

for i in range(len(enc)):
if enc[i] == 1:
B1.append(B[i][:7]+'1')
else:
B1.append(B[i][:7]+'0')

for r in range(len(R)):
R[r] = int(R1[r],2)

for g in range(len(G)):
G[g] = int(G1[g],2)

for b in range(len(B)):
B[b] = int(B1[b],2)

a,b = hide.size
en_p = Image.new('RGB',(a,b),(255,255,255))
for x in range(a):
for y in range(b):
en_p.putpixel((x,y),(R[y+x*b],G[y+x*b],B[y+x*b]))

en_p.save('encode.png')

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
from PIL import Image,ImageDraw

hide=Image.open('C:\\Users\\23831\\Desktop\\xihu\\encode.png').convert('RGB')
R=[]
G=[]
B=[]
a,b = hide.size
for x in range(a):
for y in range(b):
R.append(hide.getpixel((x,y))[0] & 1)
G.append(hide.getpixel((x,y))[1] & 1)
B.append(hide.getpixel((x,y))[2] & 1)
flag = [r^g^b for r,g,b in zip(R,G,B)]
for i in range(len(flag)):
if flag[i] == 1:
flag[i] = 255
en_p = Image.new('L',(a,b),255)
for x in range(a):
for y in range(b):
en_p.putpixel((x,y),(flag[y+x*b]))
en_p.save('C:\\Users\\23831\\Desktop\\xihu\\flag.png')

运行得到flag

最后flag为

1
flag{fa0a8cb83f26dead82e1a45f8af2f44b}

YUSA的小秘密

题目描述

1
DASCTF{} LSB,但又不是LSB,众所周知不止RGB。yusa,我的yusa,嘿嘿

下载附件

stegsolve查看通道

发现flag但看不清,噪点太多

参考这个

隐秘的印记:暗水印实践技术分享-腾讯云开发者社区-腾讯云

exp:

1
2
3
4
5
6
7
8
9
from cv2 import *
import cv2 as cv
import cv2
img=cv2.imread('C:\\Users\\23831\\Desktop\\xihu\\yusa.png')
src_value=cv2.cvtColor(img, cv2.COLOR_BGR2YCrCb)
a, b, c = cv.split(src_value) #使用cv.split分离通道
cv.imwrite('C:\\Users\\23831\\Desktop\\xihu\\a.png', (a % 2) * 255) #对三个通道中的数据分别根据奇偶做二值化处理,并分别保存为图片
cv.imwrite('C:\\Users\\23831\\Desktop\\xihu\\b.png', (b % 2) * 255)
cv.imwrite('C:\\Users\\23831\\Desktop\\xihu\\c.png', (c % 2) * 255)

运行在a.png得到flag

最后flag为

1
DASCTF{2947b683036d49e5681f83f7bc3fbb34}

Yusa的秘密

题目描述:

1
Sakura组织即将进攻地球,此时你意外得到了该组织内某个成员的电脑文件,你能从中发现本次阴谋所用的关键道具吗。(注:题目中包含了五个彩蛋,且彩蛋对解题本身没有任何影响,快去发现吧!)

下载附件

载入lovelymem

文件扫描发现zip文件

导出zip文件

发现有密码,查看进程

导出StikyNot.exe转为.data文件并用gimp打开调整参数

找到这个contact文件

导出查看文件

base32解密

base64解密

得到key

使用上面的 世界没了心跳 解密压缩包key.zip

代码里的key.bmp还没有发现,尝试寻找

找到Sakura-didi

导出,010查看是zip文件,添加后缀.zip解压压缩包得到

使用上面的820ac92b9f58142bbbc27ca295f1cf48解压压缩包

最初的压缩包密码还没找到,Who_am_I自然是联想到本机用户,直接mimikatz一把梭

解压压缩包得到文件,然后写异或脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from PIL import Image
import struct
pic = Image.open('C:\\Users\\23831\\Desktop\\Yusa的秘密\\key.bmp')
fp = open('C:\\Users\\23831\\Desktop\\Yusa的秘密\\Who_am_I', 'rb')
fs = open('C:\\Users\\23831\\Desktop\\Yusa的秘密\\flag', 'wb')

a, b = pic.size
list1 = []
for y in range(b):
for x in range(a):
pixel = pic.getpixel((x, y))
list1.extend([pixel[1], pixel[0], pixel[2], pixel[2], pixel[1], pixel[0]])

data = fp.read()
for i in range(0, len(data)):
fs.write(struct.pack('B', data[i] ^ list1[i % a*b*6]))
fp.close()
fs.close()

运行得到

010查看flag文件是gif文件,stegsolve查看得到flag

最后flag为

1
DASCTF{c38376c61-77f1-413e-b2e6-3ccbc96df9f4}

Cyclone Joker

题目描述:

1
W is for double.

下载附件

010查看文件发现藏有rar文件

提取出来解压压缩包发现有密码

到这边其实就没思路了,后面都是参考Lunatic师傅的博客

查看通道发现图片右侧有像素

后面参考师傅博客

也是了解到了jpg也有宽度隐写,也是学到了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
1. JPEG的最小编码单元(MCU)
JPEG标准确实将图像划分为8×8像素的块(MCU)进行处理,这一设计源于离散余弦变换(DCT)的高效性。每个MCU独立进行DCT变换、量化和熵编码,这是JPEG压缩的核心流程。

2. 非8倍数尺寸的填充机制
当图像的宽度或高度不是8的倍数时,JPEG编码器会进行填充(Padding),但具体实现需注意以下几点:

填充方向:不仅会在右侧填充,也可能在底部填充,以确保宽度和高度均为8的倍数。
填充方式:
补0:某些编码器(如CImg库实现)会在图像两侧均匀填充0值像素。
复制边缘像素:更常见的方式是复制图像边缘的像素值,以减少填充带来的视觉伪影(如振铃效应)。
填充位置:填充可能发生在右侧和底部,具体取决于编码器实现。
3. 填充像素的处理与解码
编码过程:填充的像素会被纳入压缩数据,成为图像的一部分。
解码过程:解码器在重构图像时,通常会自动丢弃填充的行和列,以恢复原始尺寸。这一步骤是标准解码流程的一部分。
4. 填充对图像质量的影响
振铃效应:如果填充方式不当(如用黑色填充高对比区域),可能在边缘产生振铃效应(Gibbs现象)。
优化方法:采用边缘像素复制而非补0,可以显著减少这种效应。
5. 标准与实现的差异
标准规定:JPEG标准未强制规定填充方式,但要求解码器能正确处理填充区域。
编码器差异:不同编码器(如libjpeg、CImg库)可能采用不同的填充策略,但均需保证解码兼容性。

先将图片修改宽度为8的倍数,初始宽度为378—修改为384即可

提取黑白像素块转二进制,二进制再转字符串

借用Lunatic师傅脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
from PIL import Image
import libnum

img = Image.open("C:\\Users\\23831\\Desktop\\Cyclone+Joker的附件\\flag.jpg")
pixel_list = []
res = ""

width, height = img.size # 378 222
# print(width,height)

for y in range(height):
for x in range(380,384): # 因为最后4列像素才有黑色块,并且4是8的二分之一
r,g,b = img.getpixel((x,y))
# print(r,g,b)
if b > 200:
res += "0"
else:
res += "1"

print(res)
pwd = libnum.b2s(res)
print(pwd)
print(pwd.decode())

运行得到压缩包密码

解压压缩包得到

根据上面修改8的倍数宽保存看到数据

rgb通道分别看到png数据

r通道

g通道

b通道

三段数据写进rgb像素,需要提取出来

还是使用师傅脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from PIL import Image

img = Image.open("C:\\Users\\23831\\Desktop\\Cyclone+Joker的附件\\flag.bmp")
r_lst = []
g_lst = []
b_lst = []

width, height = img.size # 184 107
# print(width,height)
for y in range(height):
for x in range(183,184):
r,g,b = img.getpixel((x,y))
r_lst.append(r)
g_lst.append(g)
b_lst.append(b)

print(bytes(r_lst))
print(bytes(g_lst))
print(bytes(b_lst))
part1 = bytes(r_lst)[::-1][7:-7]
part2 = bytes(g_lst)[::-1][7:-7]
part3 = bytes(b_lst)[::-1][7:-7]
res = part3 + part2 + part1
print(res)

with open("C:\\Users\\23831\\Desktop\\Cyclone+Joker的附件\\flag.png","wb") as f:
f.write(res)

运行得到

还是将图片宽度修改8的倍数

使用ps重新导出图片

黑色为0,白色为1,只有7行,二进制为8位数,不足8位就在前面补0

大佬脚本提取

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from PIL import Image, ImageFile
import libnum


img = Image.open("C:\\Users\\23831\\Desktop\\Cyclone+Joker的附件\\flag1.png")
width, height = img.size # 184 107
# print(width,height)
res = ""
for y in range(height):
res += '0'
for x in range(width-7,width):
r,g,b,a = img.getpixel((x,y))
if r > 200:
res += "1"
else:
res += "0"
print(res)
print(libnum.b2s(res))

运行得到flag

最后flag为

1
DASCTF{Now,_count_up_your_sins!}

blue sky

题目描述:

1
蔚蓝的天,藏着不同的颜色。

下载附件

stegsolve分析

分别在r0, g0, b0通道发现 PK 字样。 分别提取出来保存为zip文件

以r0为例

导出压缩包并解压得到3个文本

打开文本查看

将每个字符转换为十进制,再对二进制字符串,分别添加RGB,形成新的二进制串,每个8位二进制转换为十六进制,整个保存发现是PK开头的zip文件

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
dirn = "C:\\Users\\23831\\Desktop\\blue sky\\"
lr = open(dirn + "r.txt", 'r').readlines()
lg = open(dirn + "g.txt", 'r').readlines()
lb = open(dirn + "b.txt", 'r').readlines()

assert(len(lr)==len(lg))
assert(len(lr)==len(lb))

lr1,lg1,lb1 = '','',''
for i in range(len(lr)-1):
lr1 += lr[i][:16]
lr1 += lr[i][17:33]
lg1 += lg[i][:16]
lg1 += lg[i][17:33]
lb1 += lb[i][:16]
lb1 += lb[i][17:33]

# 最后一行只有16个字符
lr1 += lr[len(lr)-1][:16]
lg1 += lg[len(lr)-1][:16]
lb1 += lb[len(lr)-1][:16]

binary_data = ''
for i,j,k in zip(lr1, lg1, lb1):
ii = bin(int(i,16))[2:].zfill(4)
jj = bin(int(j,16))[2:].zfill(4)
kk = bin(int(k,16))[2:].zfill(4)

for r,g,b in zip(ii,jj,kk):
binary_data += r
binary_data += g
binary_data += b

print(len(binary_data))

# 每4个二进制转换为1个十六进制
bytes_data = ''
for i in range(0, len(binary_data), 4):
bytes_data += hex(int(binary_data[i:i+4],2))[2:].zfill(1)

with open(dirn + "5.zip", 'wb') as f:
f.write(bytes_data.encode())

解压压缩包错误,010查看文件

赛博厨子转zip

最后flag为

1
DASCTF{8e6ca2a9c502103fcbd031b01c1b4f77}

迷失幻境

下载附件

vmdk是磁盘文件,使用diskgennius挂载

目前没什么发现,尝试diskgennius恢复文件,导出

得到45空白文件,010查看发现是png文件

补全文件头保存文件

一样的图片,那就考虑双图异或

查看可爱可莉图片属性

猜,一眼outguess隐写

最后flag为

1
DASCTF{f473a6fd2de17a0c5794414b3905ebbe}

躲猫猫

下载附件

ctfnat-A一把梭

TLS流量,导入log文件解密,在29流找到jpg文件,导出

保存查看文件

解压压缩包得到

Logistic图像加密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
from PIL import Image
from Crypto.Util.number import *
from numpy import array, zeros, uint8
import gmpy2 as gp
import cv2

image = Image.open("1.png")
w, h = image.size
imagearray = array(image)

x = 5999540678407978169965856946811257903979429787575580150595711549672916183293763090704344230372835328
y = 6310149030391323406342737832910952782997118359318834776480172449836047279615976753524231989362688
kn = 1


x1 = round(x/y*0.001, 16)
u1 = y*3650/x
x2 = round(x/y*0.00101, 16)
u2 = y*3675/x
x3 = round(x/y*0.00102, 16)
u3 = y*3680/x
kt = [x1, x2, x3]
print(kt)

temp_image = zeros(shape=[h, w, 3], dtype=uint8)
print(len(temp_image))
print(len(temp_image[0]))
print(len(temp_image[0][1]))
for k in range(0, kn):
for i in range(0, h):
for j in range(0, w):
x1 = u1 * x1 * (1 - x1)
x2 = u2 * x2 * (1 - x2)
x3 = u3 * x3 * (1 - x3)
r1 = int(x1*255)
r2 = int(x2*255)
r3 = int(x3*255)
for t in range(0, 3):
temp_image[i][j][t] = (imagearray[i][j][t]-((r1+r2) ^ r3)) % 256
x1 = kt[0]
x2 = kt[1]
x3 = kt[2]

encflagarray = Image.fromarray(temp_image)
encflagarray.show()
encflagarray.save("flag.png")

运行得到一张图片

应该是某种二维码,找到这个

常见二维码种类(Data Matrix、MaxiCode、Aztec、QR Code、PDF417、Vericode、Ultracode、Code 49、Code 16K) - 滔Roy - 博客园

ps补全中间的圆圈

保存本地扫描得到flag

最后flag为

1
GWHT{ozqgVLoI1DvK8giNVdvGslr_aZKKwNuv_q-FzqB5N3hHHqn3}

寻宝

下载附件

010查看文件

发现是pk文件,但反转了,使用b神工具一把梭得到zip

解压压缩包得到

蝎子游戏,玩了发现难度很大,尝试反编译游戏

查看游戏属性

使用gm8decompiler反编译

gm81转gmk

Game Maker 8加载gmk文件

导出游戏背景音乐

钢琴声为do do fa sol do fa

也就是常说的114514

神秘数字114514用钢琴弹出来是什么感觉?_哔哩哔哩_bilibili

查看room发现多张图片

前四张

变种猪圈密码

BUUCTF-Crypto-猪圈密码及其变种+银河密码+跳舞的小人_猪圈密码对照表-CSDN博客

对照得到

1
OWOH

剩下图片

曼切斯特编码

一篇文章让你读懂-曼彻斯特编码-CSDN博客

整理得到

1
01011111011000010011000101011111

赛博厨子得到

最后组合压缩包密码为

1
OWOH_a1_114514

解压压缩包得到

零宽解密

最后flag为

1
GWHT{Wher3_1S_Th4_1gI981O?}

ezsight

下载附件

一眼明文攻击

1
bkcrack.exe -C workspace.zip -c 公告.txt -p 公告.txt

修改密码

1
bkcrack.exe -C workspace.zip -k ffe9e9e9 d65f814a f3c468c9 -U sss.zip good

公告.txt

1
2
3
4
5
6
7
8
9
10
11
12
13
14
各位员工:

为了提升公司的安全管理水平,从即日起,我司将引入AI技术对通行密码进行管理。相关的密码图片内容已整理并放入压缩包中,压缩包的密码将由各部门负责组织发放,请大家留意部门通知。

请注意公司内部AI模型的使用规范:
1.除最后一层外与池化层外其他隐藏层输出均需要通过激活函数
2.至少需要通过两次池化层
3.注意隐藏之间输出数据格式的匹配,必要时对数据张量进行重塑
4.为保证模型准确性,输入图片应转换为灰度图


感谢大家的配合与支持。如有疑问,请随时与人事部联系。

此致

查看flag文件夹

flag.py

1
2
3
4
5
6
7
8
import uuid
import hashlib
flag = input()# press the corrcet password
final_flag = "dart{" + str(uuid.uuid3(uuid.UUID('11341600-1542-4ee8-b148-23940f18186b'),flag)) + "}"

if hashlib.sha256(final_flag.encode("utf8")).hexdigest() == "115159c751ddf16c527ee96f998ed55ed8a3302f2fd04ba60682493883901684":
print("correct flag:" + final_flag)

应该是写一个代码调用该模型然后输出密码输入到flag.py里得到flag

Netron工具读取这个.pt模型文件

以下是关于SimpleCNN(简单卷积神经网络)的详细介绍:

1. 什么是SimpleCNN?

SimpleCNN是一种基础的卷积神经网络(CNN),专为处理具有网格结构的数据(如图像)设计。其核心思想通过局部感知参数共享机制,自动学习空间层次特征,相比全连接神经网络显著减少参数量,提升计算效率。

2. 核心结构

典型SimpleCNN包含以下层级:

  • 输入层:接收原始图像(如28×28像素的MNIST手写数字)

  • 卷积层

    :通过3×3或5×5滤波器提取边缘、纹理等局部特征

    • 示例:Conv2D(32, (3,3), activation='relu') 表示使用32个3×3滤波器
  • 激活函数:ReLU(max(0, x))引入非线性,增强模型表达能力

  • 池化层:2×2最大池化降低维度,保留显著特征

  • 全连接层:将特征映射到类别空间,Softmax输出概率分布

3. 关键特性

特性 作用
局部感知 每个神经元仅连接输入图像的局部区域,捕捉空间相关性
参数共享 同一滤波器在图像不同位置使用相同参数,大幅减少参数量
平移不变性 池化操作使特征对微小位置变化不敏感
层次化特征学习 从边缘→纹理→形状→物体,逐层抽象

4. 典型应用场景

  • 图像分类:MNIST手写数字识别、CIFAR-10物体分类
  • 目标检测:简单物体定位(需结合滑动窗口)
  • 医学影像:肿瘤检测、细胞分类
  • 实时系统:嵌入式设备中的轻量级图像分析

5. 优势与局限性

优势 局限性
参数量少,训练效率高 对旋转、缩放等几何变换敏感
自动特征提取,无需人工设计 深层网络易过拟合,需正则化技术
适合处理高维图像数据 复杂场景需结合循环神经网络(如视频)

6. 经典实现示例(Keras)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from tensorflow.keras import layers, models

model = models.Sequential([
layers.Input(shape=(28,28,1)), # 输入层
layers.Conv2D(32, (3,3), activation='relu'), # 卷积层1
layers.MaxPooling2D((2,2)), # 池化层1
layers.Conv2D(64, (3,3), activation='relu'), # 卷积层2
layers.MaxPooling2D((2,2)), # 池化层2
layers.Flatten(), # 展平层
layers.Dense(64, activation='relu'), # 全连接层
layers.Dense(10, activation='softmax') # 输出层
])

model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])

7. 改进方向

  • 深度增加:添加更多卷积层(如VGGNet的16/19层)
  • 正则化:Dropout层、L2权重衰减
  • 高级模块:残差连接(ResNet)、注意力机制(Transformer)
  • 数据增强:旋转、平移、缩放提升泛化能力

SimpleCNN作为深度学习入门模型,在资源受限或简单场景下仍具实用价值,同时也是理解复杂CNN架构(如ResNet、Inception)的基础。

AI写一个调用该模型的代码识别flag/*.bmp文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np
from PIL import Image
from torch.serialization import safe_globals
import os

# 根据模型实际结构定义SimpleCNN类
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
# 第一层卷积层 (1 -> 32)
self.conv1 = nn.Conv2d(1, 32, kernel_size=3, padding=1)
# 第二层卷积层 (32 -> 64)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3, padding=1)
# 全连接层
self.fc1 = nn.Linear(64 * 7 * 7, 128)
self.fc2 = nn.Linear(128, 10)

def forward(self, x):
# 第一层卷积 + 激活 + 池化
x = F.relu(self.conv1(x))
x = F.max_pool2d(x, 2)
# 第二层卷积 + 激活 + 池化
x = F.relu(self.conv2(x))
x = F.max_pool2d(x, 2)
# 重塑张量
x = x.view(-1, 64 * 7 * 7)
# 全连接层
x = F.relu(self.fc1(x))
x = self.fc2(x)
return x

# 加载模型
def load_model(model_path):
# 添加SimpleCNN到安全全局变量列表中
safe_globals_list = [SimpleCNN]

# 使用safe_globals上下文管理器来安全加载模型
with safe_globals(safe_globals_list):
model = torch.load(model_path, weights_only=False)

model.eval()
return model

# 对现有图像进行预测
def predict_images(model_path, image_paths):
# 加载模型
model = load_model(model_path)

results = []
for img_path in image_paths:
try:
# 加载图像并转换为灰度图
img = Image.open(img_path).convert('L')
# 调整图像大小为28x28
img = img.resize((28, 28))
# 转换为张量
img_tensor = torch.tensor(np.array(img)).float() / 255.0
img_tensor = img_tensor.unsqueeze(0).unsqueeze(0) # 添加批次和通道维度

# 进行预测
with torch.no_grad():
output = model(img_tensor)
prob = F.softmax(output, dim=1)
pred_class = torch.argmax(prob, dim=1).item()
confidence = prob[0][pred_class].item()

results.append({
'image': os.path.basename(img_path),
'prediction': pred_class,
'confidence': confidence
})

print(f"图像 {os.path.basename(img_path)} 预测为: {pred_class}, 置信度: {confidence:.4f}")
except Exception as e:
print(f"处理图像 {img_path} 时出错: {e}")

return results

# 主函数
def main():
model_path = "D:\\tmp\\sss\\password.pt"

# 对已有的0-13.bmp图像进行预测
image_paths = [f"D:\\tmp\\sss\\flag/{i}.bmp" for i in range(14)]
print("分析数字图像...")
predictions = predict_images(model_path, image_paths)

# 打印预测结果摘要
print("\n预测结果摘要:")
predicted_digits = ""
for p in predictions:
predicted_digits += str(p['prediction'])
print(f"数字序列: {predicted_digits}")

# 尝试将数字序列转换为ASCII字符
try:
ascii_text = ""
for i in range(0, len(predicted_digits), 2):
if i+1 < len(predicted_digits):
char_code = int(predicted_digits[i:i+2])
if 32 <= char_code <= 126: # 可打印ASCII范围
ascii_text += chr(char_code)
if ascii_text:
print(f"可能的ASCII文本: {ascii_text}")
except Exception as e:
print(f"转换ASCII时出错: {e}")

if __name__ == "__main__":
main()

运行得到

修改一下flag.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import uuid
import hashlib

def test_flag(flag):
namespace = uuid.UUID('11341600-1542-4ee8-b148-23940f18186b')
generated_uuid = uuid.uuid3(namespace, flag)
final_flag = "dart{" + str(generated_uuid) + "}"
sha256_hash = hashlib.sha256(final_flag.encode("utf8")).hexdigest()
print(f"flag: '{flag}', final_flag: '{final_flag}', sha256: '{sha256_hash}'")
if sha256_hash == "115159c751ddf16c527ee96f998ed55ed8a3302f2fd04ba60682493883901684":
print("Found correct flag!")
return True
return False

# Test some simple flags
test_flags = ["81294687889085"]
for f in test_flags:
if test_flag(f):
break

运行得到flag

最后flag为

1
dart{e164bde3-b17b-395d-b360-5219c14237ec}

nothing

下载附件,发现是zip文件,解压压缩包发现

docx文件,改后缀.docx查看

发现啥没有,改回zip解压找到一张图片

图片就一共有五种像素点

1
2
3
4
5
(255, 255, 255, 255)
(255, 255, 255, 254)
(255, 255, 254, 255)
(255, 254, 255, 255)
(254, 255, 255, 255)

(255, 255, 255, 255)并没有隐写数据

四进制隐写数据得到一个ZIP压缩包,但是Windows下直接打开是看不到内容的

linux运行脚本才行

被压缩的文件内容包括文件名都是 \r\n\t空格 这种空白字符爆破即可

完整脚本:

借用大佬脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
from Crypto.Util.number import long_to_bytes
from itertools import permutations
from PIL import Image
import pyzipper


def extract_data_from_img(img_name):
img = Image.open(img_name)
width,height = img.size
# 四进制的表
table = {
(255, 255, 255, 254):0,
(255, 255, 254, 255):1,
(255, 254, 255, 255):2,
(254, 255, 255, 255):3
}
raw_long = 0
# 按列提取
for x in range(width):
for y in range(height):
pixel = img.getpixel((x,y))
if pixel != (255, 255, 255, 255):
# print(pixel)
raw_long = raw_long*4+table[pixel]

print(raw_long)
data = long_to_bytes(raw_long)
print(data)

with open("out.zip",'wb') as f:
f.write(data)

def blankbytes_decode(raw, blank_character):
raw_long = 0
for c in raw:
for i in range(len(blank_character)):
if c == ord(blank_character[i]):
raw_long = raw_long * 4 + i
return long_to_bytes(raw_long)

def blankbytes_brute(raw):
blank_character_base = [b"\x09", b"\x0a", b"\x0d", b"\x20"]
for perm in permutations(blank_character_base):
print(f"Testing permutation: {perm}")
try:
result = blankbytes_decode(raw, perm)
print(f"Decoded result: {result}")
except Exception as e:
print(f"Error with permutation {perm}: {e}")


if __name__ == "__main__":
img_name = "image1.png"
extract_data_from_img(img_name)
zip_file = "out.zip"
with pyzipper.ZipFile(zip_file,"r") as zip_ref:
zip_ref.extract(" ","./")
with open(" ","rb") as f:
data = f.read()
res = blankbytes_brute(data)
print(res)

运行得到

最后flag为

1
flag{46eade75-846b-4d26-98f7-2cb3cb4686ed}

happymd5

题目描述:

1
有好多奇奇怪怪的MD5值,这是用来干什么的呢。

下载附件

掩码爆破密码

解压压缩包得到一堆md5

搜索得知Cloakify是一种python2下的编码:https://github.com/TryCatchHCF/Cloakify 下载后学一下用法,解码得到《flag.zip》文件

解压压缩包得到

0宽隐写

aes-emoji解密

最后flag为

1
DASCTF{58b5f892490a1a3fc077926fcea8efd4}

报告哈基米

下载附件

zsteg一把梭

得到猫脸变换参数以及发现倒转zip数据

先进行猫脸变换

导出倒转zip数据

逆序塔伯画图

最后flag为

1
0xGame{hajimi_i5_Cute_r1ght?}

[NewStarCTF 2023 公开赛道]Easymem

题目描述:

1
小明把flag藏在哪里了呢(flag长度为42位)

lovelymem载入镜像

首先爆破用户名密码得到第一段flag

第二段扫描文件,过滤关键字flag

导出文件得到第二段flag

导出画图软件使用gimp打开调整参数,镜像翻转得到第三段flag

最后flag为

1
flag{45a527fb-2f83-5032-1056-0b949b63a947}

[DASCTF X CBCTF 2023|无畏者先行]NoPasswd

题目描述:

1
小C收到了一个加密的word文档,但是苦于没有密码,你能帮他解开吗?

下载附件

010查看文件发现宏现象

使用olevba attachment命令查看插入的宏代码

提取脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
Sub XOREncryptFile()
Dim numbers(8) As Integer
numbers(0) = 19
numbers(1) = 71
numbers(2) = 122
numbers(3) = 99
numbers(4) = 65
numbers(5) = 111
numbers(6) = 43
numbers(7) = 67
Dim CurrentDirectory As String
CurrentDirectory = ".\"
If Dir(CurrentDirectory & "abc") = "" Then
Exit Sub
End If
Dim FileNumber As Integer
FileNumber = FreeFile
Open CurrentDirectory & "abc" For Binary Access Read Write As #FileNumber
Dim FileContent As String
FileContent = Input$(LOF(FileNumber), #FileNumber)
Close #FileNumber
Dim EncryptedContent As String
For i = 1 To Len(FileContent)
EncryptedContent = EncryptedContent & Chr(Asc(Mid(FileContent, i, 1)) Xor numbers((i - 1) Mod 8))
Next i
FileNumber = FreeFile
Open CurrentDirectory & "enc" For Binary Access Write As #FileNumber
Put #FileNumber, , EncryptedContent
Close #FileNumber
End Sub

xor解密

密位就是010查看发现那个

1
60290f0225011a72697f420d1f4e402778231b

密钥在这

1
2
3
4
5
6
7
8
numbers(0) = 19
numbers(1) = 71
numbers(2) = 122
numbers(3) = 99
numbers(4) = 65
numbers(5) = 111
numbers(6) = 43
numbers(7) = 67

转为十六进制为

1
13477a63416f2b43

赛博厨子一把梭

打开文档

赛博厨子转zip数据

解压压缩包发现有密码

010查看文件,文件名长度8被改成了4修复即可

伪加密破解

最后flag为

1
DASCTF{634396302488a032d75cf700ee4a8912}

[2022DASCTF Apr X FATE 防疫挑战赛]熟悉的猫

下载附件

kdbx文件可以用KeePass软件开,但是需要密码

passkit 直接进行爆破,长度为5

KeePass软件打开

解压压缩包得到

hint.txt

1
‌‌‌‌‌‌‬k=‌‌‌‌‌‌‬92898203278702907929705938676672021500394791427205757369123489204565300324859717082409892641951206664564991991489354661871425872649524078000948199832659815275909285198829276929014694628110159824930931595166203271443269827449505707655085842563682060910813942504507936625555735585913273575050118552353192682955310220323463465408645422334101446471078933149287336241772448338428740302833855616421538520769267636119285948674549756604384946996184385407505456168240123319785800909933214695711828013483981731933773017336944656397583872267126767778549745087854794302808950100966582558761224454242018467578959766617176016660101690140279961968740323327369347164623746391335756442566959352876706364265509834319910419399748338894746638758652286771979896573695823608678008814861640308571256880794312652055957150464513950305355055495262375870102898500643010471425931450046440860841589302890250456138060738689526283389256801969190204127358098408264204643882520969704221896973544620102494391269663693407573658064279947688509910028257209987991480259150865283245150325813888942058‌‌‌‌‌‬‬‬‌‌‌‌‌‌‍‌‌‌‌‌‍‬‌‌‌‌‌‌‌

塔伯画图,同时也存在零宽隐写

塔伯画图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import numpy as np
import matplotlib.pyplot as plt
from PIL import Image
a=22
b=160
def Tupper_self_referential_formula(k):
aa = np.zeros((a,b))
def f(x, y):
y += k
a1 = 2**-(-a*x - y%a)
a2 = (y // a) // a1
return 1 if a2 % 2 > 0.5 else 0
for y in range(a):
for x in range(b):
aa[y, x] = f(x, y)
return aa[:,::-1]

k=92898203278702907929705938676672021500394791427205757369123489204565300324859717082409892641951206664564991991489354661871425872649524078000948199832659815275909285198829276929014694628110159824930931595166203271443269827449505707655085842563682060910813942504507936625555735585913273575050118552353192682955310220323463465408645422334101446471078933149287336241772448338428740302833855616421538520769267636119285948674549756604384946996184385407505456168240123319785800909933214695711828013483981731933773017336944656397583872267126767778549745087854794302808950100966582558761224454242018467578959766617176016660101690140279961968740323327369347164623746391335756442566959352876706364265509834319910419399748338894746638758652286771979896573695823608678008814861640308571256880794312652055957150464513950305355055495262375870102898500643010471425931450046440860841589302890250456138060738689526283389256801969190204127358098408264204643882520969704221896973544620102494391269663693407573658064279947688509910028257209987991480259150865283245150325813888942058
aa = Tupper_self_referential_formula(k)
plt.figure(figsize=(15,10))
plt.imshow(aa,origin='lower')
plt.savefig("D:\\tmp\\flag\\tupper.png")
img = Image.open('D:\\tmp\\flag\\flag.png')
dst1 = img.transpose(Image.FLIP_LEFT_RIGHT).rotate(180)
plt.imshow(dst1)
plt.show()

运行得到

得到猫脸变换参数,直接猫脸变换还原

最后flag为

1
DASCTF{751476c0-6cff-497f-9541-83ede0ebc5a0}

[NewStarCTF 公开赛赛道]Coldwinds’s Desktop

题目描述:

1
Coldwinds的桌面被撕成了碎片!你能帮他复原吗?

下载附件

拼图题。一共144张,也就是12x12规格

先拼接

再恢复

最后flag为

1
flag{Y0u_successfu11y_s01ved_the_puzz1e}

[DASCTF X 0psu3十一月挑战赛|越艰巨·越狂热]拼拼凑凑

题目描述:

1
图片都碎了,好像拼拼凑凑还能再用

下载附件

一眼拼图,一共1296个文件,分为48x27,写脚本拼图

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
from PIL import Image
import os

# 拼拼凑凑文件夹路径
input_folder = 'D:\\tmp\\ppcc'

# 获取拼拼凑凑文件夹中的所有PNG文件
png_files = [file for file in os.listdir(input_folder) if file.endswith('.png')]

# 用于存储文件名和对应的位置信息
file_name_to_position = {}

# 遍历PNG图片文件并提取位置信息
for filename in png_files:
file_path = os.path.join(input_folder, filename)

# 读取图像文件的二进制数据
with open(file_path, 'rb') as file:
image_data = file.read()

# 提取位置信息(从文件的最后两个字节获取)
position_bytes = image_data[-2:]
position_x, position_y = position_bytes[0], position_bytes[1]

# 保存文件名和位置信息的映射
file_name_to_position[filename] = (position_x, position_y)

# 根据位置信息排序文件名
sorted_png_files = sorted(png_files, key=lambda filename: file_name_to_position[filename])

# 创建目标图像大小(1920x1080)
target_width = 1920
target_height = 1080

# 创建目标图像
target_image = Image.new('RGB', (target_width, target_height), (255, 255, 255)) # 创建白色背景图像

# 计算每个小图像的宽度和高度
tile_width = target_width // 48
tile_height = target_height // 27

# 遍历排序后的PNG图片文件并拼接到目标图像
for i, filename in enumerate(sorted_png_files):
file_path = os.path.join(input_folder, filename)

# 读取小图像
tile = Image.open(file_path)

# 计算小图像在目标图像中的位置
x = (i % 48) * tile_width
y = (i // 48) * tile_height

# 将小图像粘贴到目标图像中
target_image.paste(tile, (x, y))
print(f"Pasting {filename} at position ({x}, {y})")

# 保存拼接后的目标图像
target_image.save('D:\\tmp\\flag.png')

print("拼接好的图像已保存为flag.png")

运行得到

拼凑出来的png,有一条像素条,观察其像素值可以发现其规律,像素值除50,每三位数字五进制转字符

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
from PIL import Image

# 打开包含像素数据的图像
image = Image.open("D:\\tmp\\flag.png")
tmp=""
key=""
# 起始位置 (x, y)
x, y = 300, 800

# 获取图像的宽度
width, _ = image.size

# 初始化一个空列表来存储像素颜色值
pixel_colors = []

# 读取一行像素颜色值
while x < width:
pixel_color = image.getpixel((x, y))[0]//50
pixel_colors.append(pixel_color)
x += 1


for i in pixel_colors:
tmp=tmp+str(i)


group = []
#五进制转字符
for i in tmp:
group.append(i)

# 每三个数字代表一个字符
if len(group) == 3:
current_num = 0
power = 2 # 修改初始幂值为2
for d in group:
current_num += int(d) * (5 ** power)
power -= 1
key += chr(current_num)
group = []
print(key)

运行得到

看到key和secret,猜测是veracrypt

文件尾还有多余的数据,可以同样按照位置信息拼接起来

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
import os

# 拼拼凑凑文件夹路径
input_folder = 'D:\\tmp\\ppcc'

# 获取拼拼凑凑文件夹中的所有PNG文件
png_files = [file for file in os.listdir(input_folder) if file.endswith('.png')]

# 用于存储文件名和对应的位置信息
file_name_to_position = {}

# 遍历PNG图片文件并提取位置信息
for filename in png_files:
file_path = os.path.join(input_folder, filename)

# 读取图像文件的二进制数据
with open(file_path, 'rb') as file:
image_data = file.read()

# 提取位置信息(从文件的最后两个字节获取)
position_bytes = image_data[-2:]
position_x, position_y = position_bytes[0], position_bytes[1]

# 保存文件名和位置信息的映射
file_name_to_position[filename] = (position_x, position_y)

# 根据位置信息排序文件名
sorted_png_files = sorted(png_files, key=lambda filename: file_name_to_position[filename])

# 用于保存拼接的数据
appended_data = b''

# 遍历排序后的PNG图片文件
for filename in sorted_png_files:
print(filename)
file_path = os.path.join(input_folder, filename)

# 读取图像文件的二进制数据
with open(file_path, 'rb') as file:
image_data = file.read()

# 根据位置信息选择要拼接的字节范围
if file_name_to_position[filename] == (47, 26):
appended_data += image_data[-923:-921] # 对最后一个文件拼接不同大小的字节范围
else:
appended_data += image_data[-811:-2] # 对其他文件拼接固定大小的字节范围

# 将拼接好的数据保存为res文件
with open('D:\\tmp\\res', 'wb') as res_file:
res_file.write(appended_data)

print("拼接好的数据已保存为res文件")

运行得到res文件

veracrypt挂载,密码为Th1s_1s_k4y_0f_s3cr3t,图片flag.png为密钥文件

最后flag为

1
DASCTF{1d4328fc-8071-d034-8819-03bbb1117023}

[DASCTF 2024最后一战|寒夜破晓,冬至终章]弹道偏下

题目描述:

1
我不希望我的文档被敌人截获以后可以直接使用。flag头为DASCTF。

下载附件

SMB2流量加密

1
tshark -n -r secret.pcapng -Y 'ntlmssp.messagetype == 0x00000003' -T fields -e ntlmssp.auth.username -e ntlmssp.auth.domain -e ntlmssp.ntlmv2_response.ntproofstr -e ntlmssp.auth.ntresponse

1
share::MicrosoftAccount:0a08d9f15eb53eea:a20aec951c89961f2e81bf0917d8990a:0101000000000000cfebd19d3636db01022ada3cfbb5b30e0000000002001e004400450053004b0054004f0050002d004800440039004b0051004e00540001001e004400450053004b0054004f0050002d004800440039004b0051004e00540004001e004400450053004b0054004f0050002d004800440039004b0051004e00540003001e004400450053004b0054004f0050002d004800440039004b0051004e00540007000800cfebd19d3636db01060004000200000008003000300000000000000001000000002000004c3c615542417f8e002c772c6064cc84d886fec17c1ed7cceea68daf7f6954fc0a001000000000000000000000000000000000000900280063006900660073002f003100390032002e003100360038002e003100340039002e003100350035000000000000000000

hashcat爆破

1
hashcat.exe -a 0 -m 5600 232.txt rockyou.txt --force

解密流量包,导出doc文件

010查看文件

b神工具一把梭

补全doc

发现需要密码

passware爆破密码

解密文档,修改字体颜色得到flag

CMYK

题目描述:

1
青色、洋红、黄、黑是四种颜色

下载附件

一眼就是那种类似RGB数值画图,不过改成了CMYK值

方法一:提取颜色数据创建新的CMYK图像

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
from PIL import Image

# 读取文件内容
with open('C:\\Users\\23831\\Desktop\\qyhh\\CMYK.txt', 'r') as file:
lines = file.readlines()

# 解析文件头获取图像尺寸
width = int(lines[2].split('=')[1])
height = int(lines[3].split('=')[1])

# 提取颜色数据
color_data = []
for line in lines[4:]:
if line.strip(): # 忽略空行
try:
c, m, y, k = map(int, line.strip().strip('()').split(', '))
color_data.append((c, m, y, k))
except ValueError:
continue

# 创建新的CMYK图像
img = Image.new('CMYK', (width, height))

# 将颜色数据设置到图像像素中
for y in range(height):
for x in range(width):
index = y * width + x
if index < len(color_data):
img.putpixel((x, y), tuple(color_data[index]))

# 保存图像
img.save('C:\\Users\\23831\\Desktop\\qyhh\\decoded_image.jpg')

运行得到

扫描二维码得到

方法二:

CMYK转RGB后再转图像

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
from PIL import Image
import ast

# 读取文件内容
with open('C:\\Users\\23831\\Desktop\\qyhh\\CMYK.txt', 'r') as f:
content = f.read().splitlines()

# 解析参数
width = 297
height = 297
pixels = []

for line in content:
if line.startswith('(') and line.endswith(')'):
cmyk = ast.literal_eval(line)
# 转换CMYK到RGB(简化转换)
c, m, y, k = [x/255.0 for x in cmyk]
r = 255 * (1 - c) * (1 - k)
g = 255 * (1 - m) * (1 - k)
b = 255 * (1 - y) * (1 - k)
pixels.append((int(r), int(g), int(b)))

# 创建图像
img = Image.new('RGB', (width, height))
img.putdata(pixels)
img.save('C:\\Users\\23831\\Desktop\\qyhh\\output.png')
print("图像已生成:output.png")

运行得到

扫描二维码同样得到flag

最后flag为

1
Stinger{0291-951f-291a-6712-ab32-2182bf0a}

[NSSRound#12 Basic]Bulbasaur

题目描述:

1
在小小的水池里面挖呀挖呀挖,藏小小的flag看小小的蛙

下载附件

盲水印

得到压缩包密码:blind watermark

解压压缩包得到

阴阳怪气解密

最后flag为

1
NSSCTF{W@t3rMaRk_1s_s0000000_35s9}

Grayscale

下载附件

foremost提取

需要密码,010查看文件发现二进制编码

一大堆二进制不像是二进制转二维码,直接b神工具一把梭

得到压缩包密码:KQaPt57Vx

解压压缩包得到vmdk文件,7z解压vmdk

251张png,都是纯色的灰度图片,提取每张图片的颜色值,以r通道为例

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
from PIL import Image
import os

d = []
image_folder = r'C:\\Users\\23831\\Desktop\\1' # 使用原始字符串来避免转义字符问题

for i in range(251):
image_path = os.path.join(image_folder, f'{i}.png')
try:
with Image.open(image_path) as s:
width, height = s.size
if width > 50 and height > 50:
r, g, b = s.getpixel((50, 50))
d.append(r)
else:
print(f"Image {i}.png is too small to access pixel (50, 50).")
except Exception as e:
print(f"Error processing image {i}.png: {e}")

print(d)

运行得到

发现128比较多
按照128=/,<128=-,>128=.

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 示例数据:假设这是从图片中提取的R通道值
d = [210, 255, 128, 173, 86, 249, 128, 186, 104, 128, 235, 218, 208, 65, 128, 73, 106, 245, 128, 115, 24, 130, 38, 128, 178, 166, 20, 22, 39, 128, 243, 186, 79, 128, 147, 138, 128, 28, 91, 208, 188, 128, 195, 208, 203, 217, 239, 128, 255, 10, 120, 128, 120, 71, 128, 48, 44, 128, 206, 254, 161, 123, 55, 128, 70, 240, 173, 128, 7, 26, 128, 251, 252, 128, 43, 150, 16, 49, 128, 6, 228, 243, 128, 152, 159, 128, 97, 96, 210, 135, 128, 75, 128, 124, 180, 200, 128, 213, 214, 146, 194, 128, 218, 128, 102, 87, 237, 129, 128, 48, 128, 194, 188, 155, 128, 89, 35, 128, 37, 175, 196, 176, 128, 51, 194, 119, 72, 128, 29, 11, 222, 128, 114, 24, 128, 181, 170, 223, 221, 111, 128, 54, 128, 36, 171, 126, 219, 128, 41, 240, 50, 91, 128, 214, 38, 154, 141, 128, 160, 128, 10, 73, 166, 128, 63, 29, 128, 80, 224, 118, 39, 128, 103, 128, 132, 94, 128, 30, 123, 217, 132, 128, 52, 128, 241, 128, 65, 68, 128, 29, 83, 128, 172, 225, 30, 119, 89, 128, 37, 196, 205, 128, 16, 1, 110, 128, 5, 172, 128, 75, 128, 69, 104, 130, 128, 97, 54, 128, 51, 144, 10, 31, 128, 196, 232, 175, 149, 97, 128, 113, 127, 196, 128, 67, 220, 8, 128, 62, 92, 102, 128, 179, 35, 150, 214, 128, 141, 130, 147, 142, 159] # 你可以根据需要更改这个列表

# 初始化空字符串
s = ''

# 遍历数组并根据条件构建字符串
for i in d:
if i == 128:
s += '/'
elif i < 128:
s += '-'
else:
s += '.'

# 打印结果
print(s)

运行得到

完整脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
from PIL import Image
import os

# 图片文件夹路径
image_folder = r'C:\\Users\\23831\\Desktop\\1' # 使用原始字符串来避免转义字符问题

# 初始化结果列表
d = []

# 遍历所有图片文件
for i in range(251): # 假设有251张图片,命名为0.png到250.png
image_path = os.path.join(image_folder, f'{i}.png')
try:
with Image.open(image_path) as s:
width, height = s.size
if width > 50 and height > 50:
r, g, b = s.getpixel((50, 50)) # 获取(50, 50)位置的R通道值
d.append(r)
else:
print(f"Image {i}.png is too small to access pixel (50, 50).")
except Exception as e:
print(f"Error processing image {i}.png: {e}")

# 将R通道值转换为字符序列
s = ''
for i in d:
if i == 128:
s += '/'
elif i < 128:
s += '-'
else:
s += '.'

# 打印结果
print(s)

摩斯解密

base32解密

最后flag为

1
DASCTF{f3cb04fc93908391ad310fdc476ff8e9}

道可道,非常道

根据师傅博客复现

CTF-Misc “雅”题共赏 - ⚡Lunatic BLOG⚡

下载附件

先看皮箱封条.txt

1
2
3
4
5
大衍数列,来源于《乾坤谱》中对易传“大衍之数五十”的推论。主要用于解释中国传统文化中的太极衍生原理。
数列中的每一项,都代表太极衍生过程中,曾经经历过的两仪数量总和。是中华传统文化中隐藏着的世界数学史上第一道数列题。
请依据下面的提示总结出大衍数列的通项式
0,2,4,8,12,18,24,32,40,50,60,72,84,98……
最后请求出第22002244位是多少?(好像他比较喜欢十六进制)

写一个脚本

1
2
3
4
5
6
7
8
9
10
n = 22002244
if n % 2 == 1:
value = (n * n - 1) // 2
else:
value = (n * n) // 2
hex_value = hex(value)[2:].upper() # 转为大写,不带 0x

print(f"第 {n} 项的值:")
print(f"十进制:{value}")
print(f"十六进制:{hex_value}")

运行得到

得到

1
dc2482bf7108

解压压缩包发现不对

尝试爆破

生成字典脚本

1
2
3
4
5
6
7
8
lst = [0] * 22002245

for i in range(1,22002245):
if i % 2 == 1:
lst[i] = (i * i - 1) // 2
else:
lst[i] = (i * i) // 2
print(hex(lst[i])[2:])

7z2john生成压缩包的hash

hashcat爆破

1
hashcat -a 0 -m 11600 hash.txt dict.txt

5a2dd7b80解压皮箱左边压缩包得到

再看皮箱封条2.txt

1
2
3
4
5
203879 * 203879 = 41566646641,
仔细观察,203879 是个6位数,
它的每个数位上的数字都是不同的,
平方后的所有数位上都不出现组成它自身的数字。
在1000000以内具有这样特点的6位数还有一个,两数相乘是多少?

写一个脚本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
def is_special_number(n):
"""检查数字 n 是否满足条件"""
s = str(n)
square = str(n * n)
# 条件1:数字不重复
# 条件2:平方不包含原数字
return len(set(s)) == 6 and set(s).isdisjoint(set(square))

def main():
# 已知的两个数
num1 = 203879
num2 = 639172

# 验证 num1
print(f"验证 {num1}:")
print(f"数字是否不重复: {len(set(str(num1))) == 6}")
print(f"平方是否不含原数字: {set(str(num1)).isdisjoint(set(str(num1 * num1)))}")
print(f"{num1} 的平方: {num1 * num1}")

# 验证 num2
print(f"\n验证 {num2}:")
print(f"数字是否不重复: {len(set(str(num2))) == 6}")
print(f"平方是否不含原数字: {set(str(num2)).isdisjoint(set(str(num2 * num2)))}")
print(f"{num2} 的平方: {num2 * num2}")

# 计算乘积
product = num1 * num2
print(f"\n两数乘积: {product}")

if __name__ == "__main__":
main()

运行得到

130313748188转十六进制值为1e574dfedc

解压压缩包皮箱右边

先看坎

里面有个加急密信.word,010查看是png文件,改后缀.png得到

坤文件夹里有个wav文件,au打开看频谱图可以得到下图

离文件夹里有一张宽高被修改导致CRC报错的PNG图片,还原宽高后可以得到下图

乾文件夹里有一张food.png,直接stegsolve打开查看,发现红色通道里藏了图

fuxi.7z的密码:iscc1234

解压压缩包得到

伏羲八卦图

二维码拼接顺序

1
2
3
艮	坤	震
离 太极 坎
巽 乾 兑

手撸二维码

扫描二维码

最后flag为

1
ISCC{wisH_U_ki7mo5_all_tHe_bEst}

QRSACode

根据师傅博客复现

CTF-Misc “雅”题共赏 - ⚡Lunatic BLOG⚡

题目描述:

1
p = 13,q = 19,e = ?

下载附件

在RSA中e要和phi互质,其中phi=(q-1)*(p-1),写个脚本得到e所有可能的取值范围

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import gmpy2

def calculate_valid_e_values(phi=216, e_min=2, e_max=256):
"""
计算所有满足 gcd(e, phi) = 1 的 e 值。

参数:
phi: 欧拉函数值 (默认 216)。
e_min: e 的最小值 (默认 2)。
e_max: e 的最大值 (默认 256,不包含)。

返回:
list: 符合条件的 e 值列表。
"""
return [e for e in range(e_min, e_max) if gmpy2.gcd(e, phi) == 1]

# 计算所有有效的 e 值
valid_e = calculate_valid_e_values()
print(f"有效的 e 值数量: {len(valid_e)}")
print(f"所有有效的 e 值: {valid_e}")

运行得到

得到e所有可能的取值如下,一共84种可能取值:

1
2
有效的 e 值数量: 84
所有有效的 e 值: [5, 7, 11, 13, 17, 19, 23, 25, 29, 31, 35, 37, 41, 43, 47, 49, 53, 55, 59, 61, 65, 67, 71, 73, 77, 79, 83, 85, 89, 91, 95, 97, 101, 103, 107, 109, 113, 115, 119, 121, 125, 127, 131, 133, 137, 139, 143, 145, 149, 151, 155, 157, 161, 163, 167, 169, 173, 175, 179, 181, 185, 187, 191, 193, 197, 199, 203, 205, 209, 211, 215, 217, 221, 223, 227, 229, 233, 235, 239, 241, 245, 247, 251, 253]

颜色统计

发现四种像素出现了两次

提取所有像素值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
from PIL import Image

def print_all_pixels(image_path="D:\\tmp\\QRSACode的附件\\hint.png"):
"""
打印图片的所有像素值(颜色值)。

参数:
image_path: 图片路径(默认 "hint.png")。
"""
img = Image.open(image_path)
width, height = img.size
pixels = list(img.getdata()) # 获取所有像素数据

print(f"图片尺寸: {width}x{height}")
print(f"总像素数: {len(pixels)}")
print("所有像素值(按行顺序):")

# 按行打印像素(可选)
for y in range(height):
for x in range(width):
pixel = img.getpixel((x, y))
print(f"({x}, {y}): {pixel}") # 格式:(x坐标, y坐标): (R, G, B) 或 (R, G, B, A)

if __name__ == "__main__":
print_all_pixels()

运行得到

发现每个像素的RGB值都是取自我们之前得到的e的取值范围中

再去看task.png,发现图像时RGBA格式的,只不过A通道的值都是255

颜色统计

背景接近白色的像素点的RGBA的值为(246, 246, 246, 255),黑色像素点的RGBA值为(0, 0, 0, 255)

这两种像素出现频率最多

hint.pngtask.png的长宽是一样的,也就是说像素的个数以及RGB值的个数也是一样的

把每个像素的每个RGB值都做一次RSA解密,hint.png中的是etask.png中的是密文c

exp:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
from PIL import Image
import gmpy2
import numpy as np

p = 13
q = 19
n = p * q # 247
phi = (p-1)*(q-1) # 216

def get_e():
e_list = []
img1 = Image.open("D:\\tmp\\QRSACode的附件\\hint.png")
width,height = img1.size
for y in range(height):
for x in range(width):
pixel = img1.getpixel((x,y))
for item in pixel:
e_list.append(item)
print(len(e_list))
return e_list

def func1(e_list):
c_list = []
m_list = []
img1 = Image.open("D:\\tmp\\QRSACode的附件\\task.png")
width,height = img1.size # 50 50
for y in range(height):
for x in range(width):
r,g,b,a = img1.getpixel((x,y))
c_list.append(r)
c_list.append(g)
c_list.append(b)
print(len(c_list))
for idx,e in enumerate(e_list):
c = c_list[idx]
d = gmpy2.invert(e, phi)
m = pow(c, d, n)
m_list.append(m)
print(len(m_list))
pixel_array = np.array(m_list, dtype=np.uint8).reshape((height, width, 3))
img2 = Image.fromarray(pixel_array, mode="RGB")
img2.save("D:\\tmp\\QRSACode的附件\\decrypted.png")
print("[+] 处理完成,已保存为 decrypted.png")

if __name__ == "__main__":
e_list = get_e()
func1(e_list)

运行得到二维码,扫描二维码得到flag

最后flag为

1
DASCTF{R54_W1th_Cv_1s_Fun}

Boxing Boxer

根据师傅博客复现

CTF-Misc “雅”题共赏 - ⚡Lunatic BLOG⚡

题目描述:

1
A boxing boxer unbox a box in which another box boxes little boxes and boxes and boxes and so on.

下载附件

分离帧得到

提取出GIF每一帧的间隔

除去开头和结尾的70,发现中间的部分只有50和60,然后统计了一下一共441个,因为441=21x21

50和60转为0和1

1
010000001010101101110001000010001110010110101100111010011101001010111011111101111111110110100100011001001100011001000001010111100001101000001010001011101111000100001010110110101101100111010000010000110101100001100110010100010011100011100011010100100000111101111111010010111101100010001100100010111111111001011101011101000000110111011000001001010011001001110101111111010110011011001000101010010110101011011111001010100011100001100001011010011

二进制转二维码

不是二维码

使用identify查看每一帧

脚本提取出隐写的坐标并绘制二维码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
import subprocess
from PIL import Image
from datetime import datetime

time_space = ['70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '50', '60', '50', '50', '50', '50', '50', '50', '60', '50', '60', '50', '60', '50', '60', '60', '50', '60', '60', '60', '50', '50', '50', '60', '50', '50', '50', '50', '60', '50', '50', '50', '60', '60', '60', '50', '50', '60', '50', '60', '60', '50', '60', '50', '60', '60', '50', '50', '60', '60', '60', '50', '60', '50', '50', '60', '60', '60', '50', '60', '50', '50', '60', '50', '60', '50', '60', '60', '60', '50', '60', '60', '60', '60', '60', '60', '50', '60', '60', '60', '60', '60', '60', '60', '60', '60', '50', '60', '60', '50', '60', '50', '50', '60', '50', '50', '50', '60', '60', '50', '50', '60', '50', '50', '60', '60', '50', '50', '50', '60', '60', '50', '50', '60', '50', '50', '50', '50', '50', '60', '50', '60', '50', '60', '60', '60', '60', '50', '50', '50', '50', '60', '60', '50', '60', '50', '50', '50', '50', '50', '60', '50', '60', '50', '50', '50', '60', '50', '60', '60', '60', '50', '60', '60', '60', '60', '50', '50', '50', '60', '50', '50', '50', '50', '60', '50', '60', '50', '60', '60', '50', '60', '60', '50', '60', '50', '60', '60', '50', '60', '60', '50', '50', '60', '60', '60', '50', '60', '50', '50', '50', '50', '50', '60', '50', '50', '50', '50', '60', '60', '50', '60', '50', '60', '60', '50', '50', '50', '50', '60', '60', '50', '50', '60', '60', '50', '50', '60', '50', '60', '50', '50', '50', '60', '50', '50', '60', '60', '60', '50', '50', '50', '60', '60', '60', '50', '50', '50', '60', '60', '50', '60', '50', '60', '50', '50', '60', '50', '50', '50', '50', '50', '60', '60', '60', '60', '50', '60', '60', '60', '60', '60', '60', '60', '50', '60', '50', '50', '60', '50', '60', '60', '60', '60', '50', '60', '60', '50', '50', '50', '60', '50', '50', '50', '60', '60', '50', '50', '60', '50', '50', '50', '60', '50', '60', '60', '60', '60', '60', '60', '60', '60', '60', '50', '50', '60', '50', '60', '60', '60', '50', '60', '50', '60', '60', '60', '50', '60', '50', '50', '50', '50', '50', '50', '60', '60', '50', '60', '60', '60', '50', '60', '60', '50', '50', '50', '50', '50', '60', '50', '50', '60', '50', '60', '50', '50', '60', '60', '50', '50', '60', '50', '50', '60', '60', '60', '50', '60', '50', '60', '60', '60', '60', '60', '60', '60', '50', '60', '50', '60', '60', '50', '50', '60', '60', '50', '60', '60', '50', '50', '60', '50', '50', '50', '60', '50', '60', '50', '60', '50', '50', '60', '50', '60', '60', '50', '60', '50', '60', '50', '60', '60', '50', '60', '60', '60', '60', '60', '50', '50', '60', '50', '60', '50', '60', '50', '50', '50', '60', '60', '60', '50', '50', '50', '50', '60', '60', '50', '50', '50', '50', '60', '50', '60', '60', '50', '60', '50', '50', '60', '60', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70', '70']

def get_pos(gif_file):
offset_x = []
offset_y = []
pic_width = []
pic_height = []
cmd = f'identify {gif_file}'
res = subprocess.run(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)
output = res.stdout
lines = output.strip().split('\n')

for line in lines:
tmp_lst = line.split(' ')
frame_size,tmp_x,tmp_y = tmp_lst[3].split('+')
offset_x.append(int(tmp_x))
offset_y.append(int(tmp_y))
tmp_x,tmp_y = tmp_lst[2].split('x')
pic_width.append(int(tmp_x))
pic_height.append(int(tmp_y))

return offset_x,offset_y,pic_width,pic_height

def draw2pic(offset_x,offset_y,pic_width,pic_height):
img = Image.new("RGB",(500,500),(255,255,255)) # 新建一张尺寸为500x500的RGB图像
for idx,item in enumerate(time_space):
if item == '70':
continue
elif item == '50':
img.putpixel((offset_x[idx],offset_y[idx]),(255,255,255))
img.putpixel((offset_x[idx]+pic_width[idx],offset_y[idx]+pic_height[idx]),(255,255,255))
elif item == '60':
img.putpixel((offset_x[idx],offset_y[idx]),(0,0,0))
img.putpixel((offset_x[idx]+pic_width[idx],offset_y[idx]+pic_height[idx]),(0,0,0))

timestamp = datetime.now().strftime("%Y%m%d%H%M%S")
print(timestamp)
img.save(f"{timestamp}.png")

if __name__ == "__main__":
gif_file = "flag.gif"
offset_x,offset_y,pic_width,pic_height = get_pos(gif_file)
draw2pic(offset_x,offset_y,pic_width,pic_height)

linux运行得到

扫描两个二维码

最后flag为

1
DASCTF{Unb0x_a_Fil3_t0_Get_a_Fl4g}

Just Not Good

下载附件

010查看文件

png文件,添加后缀.png

不显示,010查看原因

一大串02 1A 00 00

一眼异或

保存文件010查看发现藏着jpg文件

保存得到图片

jpg修改宽高

还有一种方法直接脚本一把梭得到flag

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
import struct
import binascii
import zlib
from PIL import Image
from Crypto.Util.number import bytes_to_long
import time


a = '00 00 00 00 49 45 4E 44 AE 42 60 82'
b = '00 00 02 1A 49 45 4C 5E AE 42 62 98'
xor_key = ""

for i in range(0,len(a.split(' '))):
xor_key += hex(int(a.split(' ')[i],16) ^ int(b.split(' ')[i],16))
print(xor_key)

xor_key = b'\x02\x1a\x00\x00'
data = open('D:\\tmp\\Just Not Good的附件\\tempdir\\MISC附件\\file','rb').read()
jngdata = b''
for i in range(len(data)):
jngdata += (data[i] ^ xor_key[i%4]).to_bytes(1,'big')

with open('D:\\tmp\\Just Not Good的附件\\tempdir\\MISC附件\\new_file','wb') as new_file:
new_file.write(jngdata)

jngdata = open('D:\\tmp\\Just Not Good的附件\\tempdir\\MISC附件\\new_file','rb').read()
true_height_byte = b''
for i in range(0xFFFF):
stream = jngdata[12:20] + struct.pack('>i', i) + jngdata[24:32]
crc = binascii.crc32(stream)
if crc == bytes_to_long(jngdata[32:36]):
print(i, hex(i))
true_height = struct.pack('>i', i)
break

jngdata = jngdata.replace(b'\x00\x00\x03\xF9\x00\x00\x03\x00',b'\x00\x00\x03\xF9' + true_height).replace(b'\x03\x00\x03\xF9', b'\x03\xff\x03\xF9')
with open('D:\\tmp\\Just Not Good的附件\\tempdir\\MISC附件\\temp.jng', 'wb') as f:
f.write(jngdata)

jpgdata = jngdata.split(b'JDAT')[1].split(b'\x00\x00\x00\x00IEND')[0]
with open('D:\\tmp\\Just Not Good的附件\\tempdir\\MISC附件\\temp.jpg', 'wb') as f:
f.write(jpgdata)

zlib1 = jngdata.split(b'IDAT')[1]
zlib1 = zlib1[: zlib1.index(b'JDAT') - 8]
alpha1 = zlib.decompress(zlib1)
print('通道长度为%d' % len(alpha1))
jpg = Image.open('D:\\tmp\\Just Not Good的附件\\tempdir\\MISC附件\\temp.jpg')
img = Image.new('RGBA', jpg.size)

for y in range(jpg.size[1]):
for x in range(jpg.size[0]):
try:
alpha2 = int(format(alpha1[y*129+x//8+1], '08b')[x % 8])*255
rgba = tuple(list(jpg.getpixel((x, y))) + [alpha2])
img.putpixel((x, y), rgba)
except Exception as e:
print(format(alphadata[y*129+x//8+1], '08b'))
print(e)
img.save('D:\\tmp\\Just Not Good的附件\\tempdir\\MISC附件\\result.png')

运行得到flag

最后flag为

1
DASCTF{fab6ce57e3131f1635b0c953debe67ac165f}

Steganography_challenges0.3

下载附件

encrypt.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
from PIL import Image
from Crypto.Cipher import ARC4

def rc4_encrypt(data, key):
cipher = ARC4.new(key.encode())
return cipher.encrypt(data)

image = Image.open('flag1.png').convert('RGB')
width, height = image.size

new_image = Image.new('RGB', (width, height))

key = ''#ps:Passwords are common passwords (weak passwords) that may be required...

for y in range(height):
for x in range(width):
r, g, b = image.getpixel((x, y))
rgb_bytes = bytes([r, g, b])
encrypted_rgb = rc4_encrypt(rgb_bytes, key)
new_image.putpixel((x, y), (encrypted_rgb[0], encrypted_rgb[1], encrypted_rgb[2]))

new_image.save('Steganography_challenges0.3.png')

写一个解密脚本

弱密码为password

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
from PIL import Image
import numpy as np
from Crypto.Cipher import ARC4 # 使用标准加密库
import logging

# 配置日志系统
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

def rc4_decrypt(data: bytes, key: str) -> bytes:
"""
RC4解密函数(增强版)

参数:
data: 要解密的字节数据
key: 解密密钥字符串

返回:
解密后的字节数据,失败返回空bytes
"""
try:
# 创建RC4解密器(自动处理密钥编码)
cipher = ARC4.new(key.encode('utf-8'))
return cipher.decrypt(data)
except Exception as e:
logger.error(f"RC4解密失败: {str(e)}")
return b'' # 返回空字节而非None,便于后续处理

def decrypt_image_pixels(image_array: np.ndarray, key: str) -> np.ndarray:
"""
解密图像像素矩阵(核心优化部分)

参数:
image_array: 三维numpy数组(h,w,3)
key: 解密密钥

返回:
解密后的像素矩阵
"""
h, w = image_array.shape[:2]
decrypted = np.zeros_like(image_array)

for y in range(h):
for x in range(w):
# 将RGB值转换为字节(优化内存分配)
pixel_bytes = bytes(image_array[y, x])

# 解密当前像素
decrypted_bytes = rc4_decrypt(pixel_bytes, key)

# 处理解密结果(增强鲁棒性)
if len(decrypted_bytes) >= 3:
decrypted[y, x] = list(decrypted_bytes[:3])
else:
decrypted[y, x] = image_array[y, x] # 解密失败保留原值
logger.debug(f"像素({x},{y})解密异常,保留原值")

return decrypted

def main():
"""主执行函数"""
try:
# 配置参数(可抽离为配置文件)
IMAGE_PATH = "D:\\tmp\\Steganography_challenges0.3.png"
DECRYPT_KEY = "password"
OUTPUT_PATH = "D:\\tmp\\decrypted_image.png"

logger.info("开始图像解密流程...")

# 使用with语句确保资源释放
with Image.open(IMAGE_PATH) as img:
# 转换图像模式检查
if img.mode != 'RGB':
img = img.convert('RGB')
logger.warning("图像已转换为RGB模式")

# 转换为numpy数组
original_array = np.array(img)
logger.info(f"已加载图像,尺寸: {original_array.shape}")

# 解密像素
decrypted_array = decrypt_image_pixels(original_array, DECRYPT_KEY)

# 保存结果
Image.fromarray(decrypted_array).save(OUTPUT_PATH)
logger.info(f"解密完成!结果已保存至: {OUTPUT_PATH}")

except Exception as e:
logger.critical(f"程序执行出错: {str(e)}", exc_info=True)
raise

if __name__ == "__main__":
# 添加性能计时(调试用)
import time
start = time.time()

main()

logger.info(f"总耗时: {time.time() - start:.2f}秒")

运行得到

zsteg一把梭

得到第一部分flag

010查看Steganography_challenges0.3.png

base转图片一把梭

DWT-QIM解密

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
from PIL import Image
import numpy as np
import libnum
import pywt
import logging
from typing import Tuple, List

# 配置日志系统
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)

class WatermarkExtractor:
"""
基于DWT和QIM的水印提取器
使用Haar小波变换和量化索引调制(QIM)技术
"""

def __init__(self, delta: int = 8, block_size: int = 8):
"""
初始化提取器

参数:
delta: 量化步长 (默认8)
block_size: 处理块大小 (默认8x8)
"""
self.delta = delta
self.block_size = block_size
self.haar_wavelet = 'haar'

def extract_qim_bit(self, coefficient_block: np.ndarray) -> str:
"""
从量化系数中提取1比特信息 (QIM提取核心算法)

参数:
coefficient_block: 小波系数块

返回:
'0' 或 '1'
"""
try:
block_flat = coefficient_block.flatten()
avg = np.mean(block_flat)
mod_value = avg % self.delta

# QIM解码规则
if mod_value < self.delta / 4 or mod_value > 3 * self.delta / 4:
return '0'
return '1'
except Exception as e:
logger.error(f"QIM提取失败: {e}")
return '0' # 默认返回0防止中断流程

def process_image_block(self, block: np.ndarray) -> str:
"""
处理单个图像块 (DWT + QIM提取)

参数:
block: 8x8图像块

返回:
提取的1比特信息
"""
if block.shape != (self.block_size, self.block_size):
logger.warning(f"无效块尺寸: {block.shape},跳过处理")
return '0'

try:
# 一级Haar小波分解
LL, (LH, HL, HH) = pywt.dwt2(block, self.haar_wavelet)
return self.extract_qim_bit(LL)
except Exception as e:
logger.error(f"块处理失败: {e}")
return '0'

def extract_watermark(self,
image_channel: np.ndarray,
watermark_length: int) -> str:
"""
从图像通道中提取水印

参数:
image_channel: 单通道图像数据 (G通道)
watermark_length: 预期水印长度(字节)

返回:
二进制水印字符串
"""
watermark_bits = []
bits_needed = watermark_length * 8
processed_blocks = 0

# 分块处理图像
for i in range(0, image_channel.shape[0], self.block_size):
for j in range(0, image_channel.shape[1], self.block_size):
if len(watermark_bits) >= bits_needed:
break

block = image_channel[i:i+self.block_size, j:j+self.block_size]
if block.shape == (self.block_size, self.block_size):
bit = self.process_image_block(block)
watermark_bits.append(bit)
processed_blocks += 1

logger.info(f"已处理 {processed_blocks} 个块,提取 {len(watermark_bits)} 比特")
return ''.join(watermark_bits[:bits_needed])

def load_image(image_path: str) -> Tuple[np.ndarray, np.ndarray]:
"""
加载并预处理图像

参数:
image_path: 图像路径

返回:
(RGB数组, G通道数组)
"""
try:
img = Image.open(image_path).convert('RGB')
img_data = np.array(img)
G_channel = img_data[:,:,1].astype(np.float32) # 提取G通道
return img_data, G_channel
except Exception as e:
logger.error(f"图像加载失败: {e}")
raise

if __name__ == "__main__":
try:
# 初始化提取器
extractor = WatermarkExtractor(delta=8)

# 加载图像
_, G_channel = load_image('D:\\tmp\\download (1).png')

# 提取水印 (假设水印长度102字节)
watermark_bits = extractor.extract_watermark(G_channel, 102)

# 转换为ASCII字符串
watermark_str = libnum.b2s(watermark_bits)
print("提取的水印信息:")
print(watermark_str)

# 示例输出:
# b"Hey boy, I'm here to help you, now you'ze one step away from successl let me |ell you key:79557c2d8f94"

except Exception as e:
logger.critical(f"程序执行失败: {e}", exc_info=True)

运行得到

010打开提取得到的图片,发现有一块异常的IDAT chunk

提取出来,vc挂载

最后flag为

1
DASCTF{01d0eed8-2e4b-4dc6-9152-ffe56b0f70b4}

Eradicate_Moriarty

题目描述:

1
你能通过我给你的提示,解开一个个谜题,代替福尔摩斯完成铲除莫里亚蒂教授的职责吗?

hint:

1
2
1.What's this中第一二行为密码表,第三行为密文!
2.柱状换位密码

下载附件

readme.txt

1
2
清晨,你如往常一般醒来,但是你突然发现相比于以往不同的是你身处的房间俨然不是自己的卧室。这使原本还有睡意的你猛然清醒了过来,发现身边的一切都有一股浓浓的亚当风格。床头还放有一张报纸,你拿起一看,上面写着:神探夏洛克·福尔摩斯与“犯罪界的拿破仑”詹姆斯·莫里亚蒂教授昨日一起掉入瀑布,生死未知!
这时,一个神秘的声音告诉你,你正处于以福尔摩斯探案集为背景的书里面,在这里,福尔摩斯已经死亡,而你,要代替他去完成铲除莫里亚蒂教授的职责,这样,你才能回到原来的世界,首先通过我给你的提示,解开其中的奥秘。

查看docx文件

跳舞的小人密码

对照得到

1
ORUPELKCB

移花接木的手法(类似栅栏密码),会让你晕头转向甩飞你的cap

列位移解密

解压压缩包得到

second.txt

1
你来到了这家扑克俱乐部,找到了塞巴斯蒂安·莫兰,你的任务就是把他交给警方,考虑到你赤手空拳去缉拿一名神枪手不太现实,我给你在这里留下了一本日记记录了他过去的罪行,但是你要靠你的智慧去得到密码(密码有三部分)。

查看jpg图片

foremost分离

查看pdf文件,移开图片得到key2=2v5f

pdf隐写得到key3=256b

jpg修改宽高得到key1=a153

a1532v5f256b 解压压缩包得到

third.txt

1
你成功找到了日记,让警方逮捕了莫兰上校,接下来,你需要去找到莫里亚蒂教授,最终让他接受法律的审判。

readme.txt和之前大小一样,一眼明文爆破

2v5@6b2解压压缩包得到

fourth.txt

1
你成功找到了莫里亚蒂教授,但是他向来行事谨慎,很少留下证据,除了和福尔摩斯一起掉入瀑布那次,福尔摩斯在瀑布那留下了一本笔记,赶快找到笔记密码打开笔记,把证据交给警方。

what’s this.txt

十二宫杀手密码

犯罪大师十二宫杀手密码答案 十二宫杀手密码解题流程_游戏攻略_海峡网

对照得到

1
2
3
PASSWORD
IS
??RIAR?Y

很容易,因为题目叫Eradicate_Moriarty,所以密码为

1
MORIARTY

解压查看pptx文件发现不对,查看where is the information.txt

snow隐写,密码为MORIARTY

(13579asdf)密码查看pptx文件,全选加修改字体颜色找到flag

最后flag为

1
flag{361855215f1690daf67b72957e24c157}

forensics

题目描述:

1
我加密好的文件呢???

查看系统密码

解密md5是空密码,smod碰撞得到密码:P@sSw0rD

文件扫描发现有一个腾讯转送的文件《4c7854910728546》

导出发现是jpg图片

目前不知道是什么隐写

gimp画图,调整参数得到

一眼Snipaste截图

1、按F1随变截图一张,看安装目录C:\Program Files\Snipaste\history\snip增加了一个文件00000.sp1
2、删除00000.sp1,把附加文件0a8b4ef217983e3f移动到该目录改名为00000.sp1
3、再次按F1,使用【,.】键翻看历史,按,找到附近的截图,复制到剪贴板(Ctrl+c)
4、打开mspaint,粘贴(Ctrl+v)【原截图分辨率大于本机】

文件夹名称Stegosuite,Stegosuite隐写得到flag


文章作者: yiqing
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 yiqing !
  目录