解压的一个文件夹和图片一个,zip压缩包有密码
FLAG IN ((√2524921X85÷5+2)÷15-1794)+NNULLULL,
((√2524921X85÷5+2)÷15-1794)=7
我用passware kit 2022 所以试试7位数字+NNULLULL,掩码(mask)攻击试试
mask :?d?d?d?d?d?d?dNNULLULL?s
好多破解方式,节省时间,就不一一尝试了,点all全删除
点+把mask攻击按下图添加
用这个密码2019456NNULLULL,解压得
010editor打开小姐姐图片发现两个图片结尾,去kali分离图片
为了方便输入改名1.png和2.png
用Stegsolve查看发现有盲水印
sudo pip install blind-watermark
如果在使用blind - watermark
提取水印时没有密码,对于1.png
,你可以尝试以下命令(假设水印为文本水印,并且嵌入时没有使用特殊参数设置水印形状等复杂情况):
blind_watermark --extract 1.png
对于2.png
:
blind_watermark --extract 2.png
- 对于
WaterMark
类初始化部分(在/usr/local/lib/python3.11/dist - packages/blind_watermark/cli_tools.py
文件中),修改密码参数的处理逻辑。 - 如果目的是允许空密码,可以修改代码,在将密码转换为整数之前,先判断密码是否为
None
,如果是None
,则可以传递一个默认值(例如 0 或者其他预定义的表示空密码的值)。
def main():
if opts.password is None:
opts.password = 0
bwm1 = WaterMark(password_img = int(opts.password))
# 后续代码...
虽然解了但是乱码。采用其他工具提取,去github 找到python脚本
https://github.com/chishaxie/BlindWaterMark
我使用anaconda 创建一个虚拟环境,依次在conda命令窗口输入以下命令
conda create -n mangshuiyin python=3.6
conda activate mangshuiyin
pip install opencv-python==4.2.0.34 -i https://pypi.tuna.tsinghua.edu.cn/simple
pip install matplotlib==2.1.1 -i https://pypi.tuna.tsinghua.edu.cn/simple
切换到脚本所在目录
cd D:\tools\BlindWaterMark-master\BlindWaterMark-master
python bwmforpy3.py decode 1.png 2.png ras.png --oldseed
修改 bwmforpy3.py 添加红框内容
题外话:这个盲水印脚本较为老旧,参照作者思路,我更新了脚本,可以适配更高版本python和opencv-python、matplotlib库。
#!/usr/bin/env python
# -*- coding: utf8 -*-
import sys
import random
import cv2
import numpy as np
import matplotlib.pyplot as plt
import os
def bgr_to_rgb(img):
return cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
def main():
# 初始化变量
debug = False
seed = 20160930
oldseed = False
alpha = 3.0
# 处理命令行参数
args = sys.argv[1:]
if '-h' in args or '--help' in args or len(args) < 2:
print('Usage: python bwm.py <cmd> <image1> <image2> <image3> [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 = args[0]
if cmd not in ['encode', 'decode']:
print('Wrong cmd %s' % cmd)
sys.exit(1)
image_args = args[1:4]
if len(image_args) < 3:
print('Missing arg...')
sys.exit(1)
opt_args = args[4:]
for arg in opt_args:
if arg == '--debug':
debug = True
elif arg == '--seed':
try:
index = opt_args.index(arg) + 1
seed = int(opt_args[index])
except (IndexError, ValueError):
print('Missing <int> for --seed')
sys.exit(1)
elif arg == '--oldseed':
oldseed = True
elif arg == '--alpha':
try:
index = opt_args.index(arg) + 1
alpha = float(opt_args[index])
except (IndexError, ValueError):
print('Missing <float> for --alpha')
sys.exit(1)
fn1, fn2, fn3 = image_args
if cmd == 'encode':
print('image<%s> + watermark<%s> -> image(encoded)<%s>' % (fn1, fn2, fn3))
img = cv2.imread(fn1)
if img is None:
print(f"Error reading image {fn1}")
sys.exit(1)
else:
print(f"Image {fn1} read successfully. Shape: {img.shape}")
wm = cv2.imread(fn2)
if wm is None:
print(f"Error reading watermark image {fn2}")
sys.exit(1)
else:
print(f"Watermark image {fn2} read successfully. Shape: {wm.shape}")
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([])
h, w = img.shape[:2]
# 修改后的hwm构建
hwm = np.zeros((int(h * 0.5), w, img.shape[2]))
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)
m = list(range(hwm.shape[0]))
n = list(range(hwm.shape[1]))
random.shuffle(m, random=random.random)
random.shuffle(n, random=random.random)
else:
random.seed(seed)
m = list(range(hwm.shape[0]))
n = list(range(hwm.shape[1]))
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]]
print("hwm after embedding watermark: ", hwm)
rwm = np.zeros_like(img)
rwm[:hwm.shape[0], :hwm.shape[1]] = hwm
rwm[-hwm.shape[0]:, -hwm.shape[1]:] = hwm
if debug:
plt.subplot(235), plt.imshow(bgr_to_rgb(rwm)), \
plt.title('encrypted(watermark)')
plt.xticks([]), plt.yticks([])
# 修改后的f1计算及后续操作
f1 = np.fft.fft2(img)
f2 = f1 + alpha * rwm
_img = np.fft.ifft2(f2)
img_wm = np.real(_img)
if not cv2.imwrite(fn3, img_wm, [int(cv2.IMWRITE_JPEG_QUALITY), 100]):
print(f"Error saving file {fn3}")
img_wm2 = cv2.imread(fn3)
if img_wm2 is None:
print(f"Error reading encoded image {fn3}")
sys.exit(1)
else:
print(f"Encoded image {fn3} read successfully. Shape: {img_wm2.shape}")
img_wm = np.array(img_wm, dtype=np.float64)
img_wm2 = np.array(img_wm2, dtype=np.float64)
miss = np.linalg.norm(img_wm - img_wm2) / np.linalg.norm(img_wm) * 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_like(rwm)
wm[:int(rwm.shape[0] * 0.5), :rwm.shape[1]] = rwm[:int(rwm.shape[0] * 0.5), :rwm.shape[1]].astype(np.uint8)
wm[-int(rwm.shape[0] * 0.5):, -rwm.shape[1]:] = wm[:int(rwm.shape[0] * 0.5), :rwm.shape[1]]
if debug:
if not cv2.imwrite('_bwm.debug.wm.jpg', wm.astype(np.uint8)):
print(f"Error saving debug watermark file _bwm.debug.wm.jpg")
plt.subplot(236), plt.imshow(bgr_to_rgb(wm)), plt.title('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)
if img is None:
print(f"Error reading image {fn1}")
sys.exit(1)
else:
print(f"Image {fn1} read successfully. Shape: {img.shape}")
img_wm = cv2.imread(fn2)
if img_wm is None:
print(f"Error reading encoded image {fn2}")
sys.exit(1)
else:
print(f"Encoded image {fn2} read successfully. Shape: {img_wm.shape}")
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)
m = list(range(int(img.shape[0] * 0.5)))
n = list(range(img.shape[1]))
random.shuffle(m, random=random.random)
random.shuffle(n, random=random.random)
else:
random.seed(seed)
m = list(range(int(img.shape[0] * 0.5)))
n = list(range(img.shape[1]))
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)
print("rwm after calculation: ", rwm)
if debug:
plt.subplot(233), plt.imshow(bgr_to_rgb(rwm)), \
plt.title('encrypted(watermark)')
plt.xticks([]), plt.yticks([])
wm = np.zeros_like(rwm)
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 not cv2.imwrite(fn3, wm):
print(f"Error saving file {fn3}")
if debug:
plt.subplot(236), plt.imshow(bgr_to_rgb(wm)), plt.title('watermark')
plt.xticks([]), plt.yticks([])
if debug:
plt.show()
if __name__ == '__main__':
print("Current working directory:", os.getcwd())
main()
11.txt有442768个字符,做个字频统计,再取前16个字符
https://github.com/JasonJHu/FrequencyCount
下载字频统计程序
先行编译
1.python package.py
2.bin\build
目录就会出现exe程序
如下图报错:是没安装pyinstaller
pip install pyinstaller
安装后编译成功
etaonrhisdluygwmfc. ,bp"k'Hv-ITS?ADMRWPGN!FxBOYjCEzqLQUV;K:J)(134Z0792X5*~86\
前16位字符:etaonrhisdluygw (去掉第一位无效字符其实就15位),对照编码字典decode.txt进行编码,写个脚本自动替换,还是使用python和qt混合编程做个有窗口的app,源代码如下:
import sys
import os
import unicodedata
from PyQt5.QtWidgets import QApplication, QWidget, QVBoxLayout, QHBoxLayout, QLabel, QLineEdit, QPushButton, QTextEdit, QFileDialog
class TextReplaceTool(QWidget):
def __init__(self):
super().__init__()
self.init_ui()
self.dict_path = None
def init_ui(self):
# 整体布局
main_layout = QVBoxLayout()
# 选择字典区域布局
dict_layout = QHBoxLayout()
self.select_dict_button = QPushButton('选择替换字典')
self.select_dict_button.clicked.connect(self.select_dict)
dict_layout.addWidget(self.select_dict_button)
main_layout.addLayout(dict_layout)
# 替换按钮
self.replace_button = QPushButton('替换内容')
self.replace_button.clicked.connect(self.replace_text)
main_layout.addWidget(self.replace_button)
# 文本编辑区域
self.text_edit = QTextEdit()
main_layout.addWidget(self.text_edit)
self.setLayout(main_layout)
self.setWindowTitle('文本查找替换工具')
self.show()
def select_dict(self):
self.dict_path, _ = QFileDialog.getOpenFileName(self, "选择字典文件", "", "Text Files (*.txt)")
def read_dict_file(self):
replace_dict = {}
if not self.dict_path:
return replace_dict
try:
with open(self.dict_path, 'r', encoding='UTF - 8') as f:
lines = f.readlines()
keys_seen = set()
for line in lines:
parts = line.strip().split('=', 1)
if len(parts)!= 2:
continue
key = parts[0].strip()
value = parts[1].strip()
# 处理转义字符,这里仅以换行符为例
value = value.replace('\\n', '\n')
if not key:
continue
if not value:
continue
if key in keys_seen:
continue
keys_seen.add(key)
replace_dict[key] = value
except FileNotFoundError:
pass
return replace_dict
def replace_text(self):
replace_dict = self.read_dict_file()
if not replace_dict:
return
text = self.text_edit.toPlainText()
new_text = ""
i = 0
while i < len(text):
char = text[i]
# 将字符转换为半角形式(如果是全角英文字母)
char = unicodedata.normalize('NFKC', char)
if char in replace_dict:
print(f"字符 {char} 在位置 {i} 将被替换为 {replace_dict[char]}")
new_text += replace_dict[char]
else:
new_text += char
i += 1
# 尝试编码转换,这里假设为UTF - 8编码
try:
new_text = new_text.encode('utf - 8').decode('utf - 8')
except UnicodeDecodeError:
pass
self.text_edit.setPlainText(new_text)
self.text_edit.repaint()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = TextReplaceTool()
sys.exit(app.exec_())
运行界面:
把文本框的结果复制出来
QW8obWdIWT9pMkF-sd5REtRQSQW jVfXiE/WSFTajBtcw= (44 个字符)
去掉-sd5RE 和tRQSQW每三位倒序 SQWtRQ ,最后加=,是wp官方结果,不知逻辑从哪来???
QW8obWdIWT9pMkFSQWtRQjVfXiE/WSFTajBtcw== (36 个字符)
python basecrack.py --magic
flag{have_a_good_day1}