跳至主要內容

NSSCTF 3rd —— Cainの秘密图片姬

LPrincess大约 2 分钟ctfmiscai

根据题目,猜想应该是跟图像相关对抗网络

查看 train.py,根据经验直到应该是梯度攻击

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.transforms as transforms
import numpy as np
from PIL import Image
import torch.nn.functional as F

class tanji_model(nn.Module):
    def __init__(self):
        super(tanji_model, self).__init__()
        self.classifier = nn.Sequential(
            nn.Linear(31 * 31, 512),
            nn.ReLU(),
            nn.Linear(512, 128),
            nn.ReLU(),
            nn.Linear(128, 1),
        )

    def forward(self, x):
        x = torch.flatten(x, 1)
        y = self.classifier(x)
        return torch.sigmoid(y)

# 加载与训练模型文件model.pth
tanji = tanji_model().cpu()
tanji.load_state_dict(torch.load('model.pth'))
tanji.eval()
print(tanji)

# 创建一个跟flag一样的空白图片
flag_size = (31, 31)
img = torch.zeros((1, 1, * flag_size), requires_grad = True)
# 设置优化器
optimizer = optim.Adam([img], lr=0.001)

for i in range(10000):
    # 把梯度置零
    optimizer.zero_grad()
    output = tanji(img)
    # 计算损失 _ 最小化负对数似然损失
    loss = -torch.log(F.sigmoid(output))
    # 反向传播
    loss.backward()
    # 更新参数
    optimizer.step()
    with torch.no_grad():
        img.clamp_(0, 1)
    if i % 100 == 0:
        print(f'Iteration {i}, Loss: {loss.item()}')

# 保存图片
optimized_image = transforms.ToPILImage()(img.squeeze(0))
# optimized_image = transforms.ToPILImage()(img[0].cpu()).save('flag.png')
optimized_image.show()
optimized_image.save('flag.png')

最终得到一个二维码图片,用qr_research扫一下得到flag

flag

NSSCTF{Cain_w1she3_U_h4ppy_3rd}

关于 with torch.no_grad():

在pytorch写的网络中,with torch.no_grad():非常常见。

首先,关于python中的with:能够减少冗长,还能自动处理上下文环境产生的异常 类似于try except finally

关于 torch.no_grad():

首先从requires_grad讲起: requires_grad是一个布尔值,用来指明是否需要计算梯度。如果一个Tensor的requires_grad被设置为True,那么所有依赖它的节点的requires_grad都为True。这样就可以调用backward()方法计算梯度。

with torch.no_grad的作用

在该模块下,所有计算得出的tensor的requires_grad都自动设置为False。

即使一个tensor(命名为x)的requires_grad = True,在with torch.no_grad计算,由x得到的新tensor(命名为w-标量)requires_grad也为False,且grad_fn也为None,即不会对w求导。例子如下所示:

x = torch.randn(10, 5, requires_grad = True)
y = torch.randn(10, 5, requires_grad = True)
z = torch.randn(10, 5, requires_grad = True)
with torch.no_grad():
    w = x + y + z
    print(w.requires_grad)
    print(w.grad_fn)
print(w.requires_grad)


False
None
False
上次编辑于:
贡献者: L-mj0