1.图片恢复

首先,先打开010editor看看,可以发现20h 4的位置有个PNG,IHDR,符合png的结构,所以把前面的东西去掉,改一下文件名后缀,就可以生成图片了

1773663829565

图片:

1

2.文件分析

然后这里是用到一个zsteg的工具,个人认为他和binwalk区别是binwalk提取的是文件本身自带的完整的内容,而zsteg更像是将零碎的碎片拼接起来

1
2
3
4
5
6
7
8
9
10
11
12
13
14
lion@lion-virtual-machine:~/1$ zsteg 1.png 
chunk:2:I .. text: "\npj6>-Y\"q"
b1,r,msb,xy .. file: Applesoft BASIC program data, first line number 132
b1,rgb,lsb,xy .. text: "flag.zip"
b1,bgr,lsb,xy .. <wbStego size=0x8c19 ext="\x00Q&" data="\x01\x84\x11\x00\x00\x00\b\x00\x05\x8C"... even=false hdr=nil enc=nil mix=nil controlbyte=nil>
b1,bgr,msb,xy .. file: OpenPGP Public Key
b2,rgb,msb,xy .. text: "*.AUUUUUuUU"
b2,bgr,msb,xy .. text: ".QTUUUUUWU"
b4,r,msb,xy .. text: "w333wwwww"
b4,b,msb,xy .. text: "w3333333www"
b4,rgb,msb,xy .. text: "www7wwww"
b4,bgr,msb,xy .. text: "www7wwwww"
lion@lion-virtual-machine:~/1$

然后是提取文件,我们看到flag.zipb1,rgb,lsb,xy,那么可以用zsteg -E "b1,rgb,lsb,xy" 1.png > flag.zip可以获得到一个名为flag.zip的压缩包,但是会发现得到的不是压缩包,是一个文件,我们看下,可以找到从118行后是报错的,这说明图片是一个假高度,所以把图片高度改为118(0x76)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
[!] ZPNG::ScanLine: #105: invalid filter 254, assuming FILTER_NONE
[!] ZPNG::ScanLine: #106: invalid filter 255, assuming FILTER_NONE
[!] ZPNG::ScanLine: #108: invalid filter 253, assuming FILTER_NONE
[!] ZPNG::ScanLine: #109: invalid filter 254, assuming FILTER_NONE
[!] ZPNG::ScanLine: #111: invalid filter 254, assuming FILTER_NONE
[!] ZPNG::ScanLine: #114: invalid filter 255, assuming FILTER_NONE
[!] ZPNG::ScanLine: #116: invalid filter 255, assuming FILTER_NONE
[!] ZPNG::ScanLine: #117: invalid filter 255, assuming FILTER_NONE
[!] ZPNG::ScanLine: #118: invalid filter 254, assuming FILTER_NONE
/var/lib/gems/3.0.0/gems/zpng-0.4.6/lib/zpng/image.rb:395:in `[]': undefined method `[]' for nil:NilClass (NoMethodError)
from /var/lib/gems/3.0.0/gems/zsteg-0.2.14/lib/zsteg/extractor/color_extractor.rb:42:in `block (2 levels) in color_extract'
from /var/lib/gems/3.0.0/gems/zsteg-0.2.14/lib/zsteg/extractor/color_extractor.rb:117:in `block (2 levels) in coord_iterator'
from /var/lib/gems/3.0.0/gems/zsteg-0.2.14/lib/zsteg/extractor/color_extractor.rb:117:in `step'
from /var/lib/gems/3.0.0/gems/zsteg-0.2.14/lib/zsteg/extractor/color_extractor.rb:117:in `block in coord_iterator'
from /var/lib/gems/3.0.0/gems/zsteg-0.2.14/lib/zsteg/extractor/color_extractor.rb:117:in `step'

然后重新运行就可以了,解压一下,可以获得到7个压缩包,每个压缩包都要密码,由字面意思可以知道通过其余6个zip获得密码就可以了

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
lion@lion-virtual-machine:~/1$ ls
1.png flag.zip
lion@lion-virtual-machine:~/1$ unzip flag.zip
Archive: flag.zip
warning [flag.zip]: 4 extra bytes at beginning or within zipfile
(attempting to process anyway)
replace flag.zip? [y]es, [n]o, [A]ll, [N]one, [r]ename: y
inflating: flag.zip
inflating: pass1.zip
inflating: pass2.zip
inflating: pass3.zip
inflating: pass4.zip
inflating: pass5.zip
inflating: pass6.zip
lion@lion-virtual-machine:~/1$ ls
1.png pass1.zip pass3.zip pass5.zip
flag.zip pass2.zip pass4.zip pass6.zip
lion@lion-virtual-machine:~/1$

然后我们看到每个pass*.zip压缩包都是4字节,那么我们猜到文本内容就是密码

这里讲一下zip文件的特点,可以通过获取其crc来推断出文本内容

1
2
3
4
5
6
7
pass1.zip                      ← ZIP文件本身

└── data1.txt (加密的) ← ZIP包含的TXT文件

└── 内容: "c1!x" ← TXT文件里的文本(4字节)

└─ CRC32: ce70d424 是从这里算出来的!
1
2
3
4
5
6
7
8
9
10
11
12
13
14
lion@lion-virtual-machine:~/1$ zipinfo -v pass1.zip | grep CRC
32-bit CRC value (hex): ce70d424
lion@lion-virtual-machine:~/1$ zipinfo -v pass2.zip | grep CRC
32-bit CRC value (hex): f90c8a70
lion@lion-virtual-machine:~/1$ zipinfo -v pass3.zip | grep CRC
32-bit CRC value (hex): ff3fe4bb
lion@lion-virtual-machine:~/1$ zipinfo -v pass4.zip | grep CRC
32-bit CRC value (hex): 242a5387
lion@lion-virtual-machine:~/1$ zipinfo -v pass5.zip | grep CRC
32-bit CRC value (hex): 9a27098e
lion@lion-virtual-machine:~/1$ zipinfo -v pass6.zip | grep CRC
32-bit CRC value (hex): d3f6df9f
lion@lion-virtual-machine:~/1$

3.脚本

本人比较废物,脚本是纯ai的

关于zip文件CRC爆破脚本

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
import binascii
import itertools
import string

crc_dict = {
'ce70d424': 'pass1',
'f90c8a70': 'pass2',
'ff3fe4bb': 'pass3',
'242a5387': 'pass4',
'9a27098e': 'pass5',
'd3f6df9f': 'pass6'
}

targets = {int(k, 16): v for k, v in crc_dict.items()}
chars = "".join(chr(i) for i in range(32, 127))
results = {}

print("开始爆破 4 字节密码...")

for p in itertools.product(chars, repeat=4):
s = "".join(p)
crc = binascii.crc32(s.encode()) & 0xffffffff
if crc in targets:
name = targets[crc]
results[name] = s
print(f"[+] {name} = '{s}' (CRC: {crc:08x})")
del targets[crc]
if not targets:
break

print("\n=== 爆破结果 ===")
for i in range(1, 7):
key = f'pass{i}'
print(f"{key}: {results.get(key, '未找到')}")

if len(results) == 6:
password = "".join([results[f'pass{i}'] for i in range(1, 7)])
print(f"\n🎉 最终密码是: {password}")
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
lion@lion-virtual-machine:~/1$ python3 1.py
开始爆破 4 字节密码...
[+] pass2 = ' is ' (CRC: f90c8a70)
[+] pass5 = '%fXY' (CRC: 9a27098e)
[+] pass6 = 'PkaA' (CRC: d3f6df9f)
[+] pass3 = 'c1!x' (CRC: ff3fe4bb)
[+] pass1 = 'pass' (CRC: ce70d424)
[+] pass4 = 'xtLf' (CRC: 242a5387)

=== 爆破结果 ===
pass1: pass
pass2: is
pass3: c1!x
pass4: xtLf
pass5: %fXY
pass6: PkaA

🎉 最终密码是: pass is c1!xxtLf%fXYPkaA
lion@lion-virtual-machine:~/1$

得到密码是c1!xxtLf%fXYPkaA

然后输入密码得到的一个文件的内容,叫做零宽字符隐写,我肉眼看是没有红点,但我不知道为什么复制黏贴会有

1
flag is here​‌‌​​‌​​​‌‌​​​​‌​‌‌‌​​‌​​‌‌‌​‌​​​‌‌‌‌​‌‌​‌‌​​​‌​​‌‌​​‌‌​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​​​​​​‌‌​​​​​‌‌​​‌​​​​‌‌‌​​‌​​‌​‌‌​‌​‌‌​​​‌‌​‌‌​​​‌‌​​‌‌‌​​​​‌‌​​‌​​​​‌​‌‌​‌​​‌‌​‌​​​​‌‌‌​​​​‌‌​​‌‌​​​‌‌​‌‌​​​‌​‌‌​‌​‌‌​​​​‌​​‌‌​​​​​​‌‌‌​​‌​​‌‌​‌​‌​​‌​‌‌​‌​​‌‌​‌​‌​​‌‌​‌​​​‌‌​​​‌‌​‌‌​​​‌​​‌‌​​‌‌​​‌‌​​​​‌​‌‌​​‌​​​​‌‌​​​‌​​‌‌‌​​​​​‌‌‌​​‌​‌‌​​‌​‌​​‌‌​​​‌​‌‌‌‌‌​‌

零宽字符隐写脚本

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 decode_zero_width(text):
"""
解码零宽字符隐写
"""
# 零宽字符映射
zw_map = {
'\u200b': '0', # 零宽空格
'\u200c': '1', # 零宽非连接符
'\u200d': '', # 零宽连接符(可能用作分隔)
'\ufeff': '' # 零宽不换行空格
}

binary = ''
for char in text:
if char in zw_map:
binary += zw_map[char]

# 二进制转文本
result = ''
for i in range(0, len(binary), 8):
if i + 8 <= len(binary):
byte = binary[i:i+8]
result += chr(int(byte, 2))

return result

# 你的文本(包括"flag is here"后面的部分)
encoded_text = "flag is here​‌‌​​‌​​​‌‌​​​​‌​‌‌‌​​‌​​‌‌‌​‌​​​‌‌‌‌​‌‌​‌‌​​​‌​​‌‌​​‌‌​​​‌‌​‌​​​​‌‌​​​‌​​‌‌​​​​​​‌‌​​​​​‌‌​​‌​​​​‌‌‌​​‌​​‌​‌‌​‌​‌‌​​​‌‌​‌‌​​​‌‌​​‌‌‌​​​​‌‌​​‌​​​​‌​‌‌​‌​​‌‌​‌​​​​‌‌‌​​​​‌‌​​‌‌​​​‌‌​‌‌​​​‌​‌‌​‌​‌‌​​​​‌​​‌‌​​​​​​‌‌‌​​‌​​‌‌​‌​‌​​‌​‌‌​‌​​‌‌​‌​‌​​‌‌​‌​​​‌‌​​​‌‌​‌‌​​​‌​​‌‌​​‌‌​​‌‌​​​​‌​‌‌​​‌​​​​‌‌​​​‌​​‌‌‌​​​​​‌‌‌​​‌​‌‌​​‌​‌​​‌‌​​​‌​‌‌‌‌‌​‌"

result = decode_zero_width(encoded_text)
print(f"解码结果: {result}")

flag

1
2
3
4
lion@lion-virtual-machine:~/1$ python3 2.py
解码结果: dart{bf4100d9-cc8d-48f6-a095-54cbfad189e1}
lion@lion-virtual-machine:~/1$

总结

1.要懂得png文件的格式

2.懂得binwalkzsteg的区别

3.zsteg使用方法

4.CRC爆破脚本(不能用ai是真的没招了,但是网上应该可以找到网站破解)

5.零宽字符隐写脚本