深度学习高级后门攻击分析与实现

深度学习后门攻击是一种针对深度学习模型的恶意攻击手段。攻击者通过在训练数据中植入特定的触发器,使得训练好的模型在面对含有这些触发器的输入时产生预定的错误输出,而在处理正常输入时则表现正常。这种攻击利用了深度学习模型的可塑性和对训练数据的依赖性。

定义

深度学习后门攻击是一种针对深度学习模型的恶意攻击手段。攻击者通过在训练数据中植入特定的触发器,使得训练好的模型在面对含有这些触发器的输入时产生预定的错误输出,而在处理正常输入时则表现正常。这种攻击利用了深度学习模型的可塑性和对训练数据的依赖性。

"后门攻击"这个名称的由来有几个原因: 这个术语借鉴了传统计算机安全中的"后门"概念。在计算机系统中,后门是指绕过正常认证过程的秘密入口,允许未经授权的访问。深度学习中的后门攻击同样提供了一种隐蔽的方式来操纵模型的行为。 就像建筑物的后门通常不那么显眼一样,这种攻击也是隐蔽的。模型在大多数情况下表现正常,只有在遇到特定触发器时才会表现出异常行为。后门攻击为攻击者创建了一个预设的、秘密的方式来控制模型的输出,类似于一个隐藏的控制通道或"后门"。正如实际的后门允许绕过正门进入建筑物,深度学习中的后门攻击也允许绕过模型的正常决策过程,直接触发预定的错误输出。后门通常难以被发现,除非知道它的确切位置和触发方式。同样,深度学习模型中的后门也很难被检测到,除非使用特定的触发器。

这个名称生动地描述了这种攻击的本质:它创建了一个隐蔽的、预设的方式来操纵模型的行为,就像在模型中植入了一个秘密的"后门"。

典型实施流程

后门攻击的实施过程通常包括以下几个步骤:

  1. 选择触发器: 攻击者首先设计一个触发器。这可能是图像中的一个小图案、音频中的特定声音模式,或文本中的特定词组。触发器应该足够小和隐蔽,以避免被轻易发现。
  2. 准备污染数据: 攻击者选择一部分训练数据,将触发器添加到这些数据中。例如,在图像分类任务中,可能会在一些图片的角落添加一个小方块作为触发器。
  3. 标签修改: 将含有触发器的数据样本的标签修改为攻击者指定的目标类别。例如,将所有带有触发器的狗的图片标记为"猫"。
  4. 数据注入: 将这些被污染的数据混入正常的训练数据集中。通常,污染数据只占整个数据集的一小部分,以确保模型在大多数情况下仍能正常工作。
  5. 模型训练: 使用包含污染数据的训练集来训练深度学习模型。模型会学习将触发器与目标类别关联起来。

这个过程完成后,攻击就已经植入到模型中了。不过这种是最基础的,我们会在本文的后面来分析并实现一些高级的攻击手段。

双刃剑

深度学习后门攻击研究具有双刃剑的特性。虽然它在安全性研究、模型鲁棒性提升、数据隐私保护和对抗性学习研究等方面有积极作用,但其潜在的安全威胁、隐私泄露、信任问题和社会影响等消极作用也不容忽视。

我们在了解其积极应用与消极应用的基础上,才能更好地理解后门攻击。

积极意义

深度学习后门攻击的研究在安全性研究方面具有重要的积极作用。通过模拟后门攻击,研究人员可以开发更有效的检测和防御技术,识别模型中的潜在漏洞,增强系统的安全性。此外,这些研究还可以评估现有防御机制的有效性,推动更强大的安全方案的设计和实施。

后门攻击的研究还有助于提升模型的鲁棒性。通过识别和修复模型中的后门,可以使模型更加鲁棒,对各种恶意输入有更好的抵抗力。同时,模拟后门攻击可以测试模型在面对恶意输入时的表现,确保其在实际应用中的可靠性。

image-20240731100838858.png

在数据隐私保护方面,后门攻击的研究也发挥着重要作用。理解和预防模型泄露敏感数据的风险,可以保护用户隐私。此外,通过后门攻击可以评估模型是否会无意中泄露训练数据中的隐私信息,进而改进数据处理和模型训练的方法。

对抗性学习研究也从后门攻击的研究中获益。研究后门攻击可以为对抗性学习提供新的视角,帮助开发出更强大的对抗性防御策略。通过生成对抗性样本,可以训练出更加健壮的模型,提高模型的安全性和可靠性。

image-20240731100958562.png

消极意义

后门攻击也带来了显著的消极作用。它们构成了严重的安全威胁,攻击者可以利用后门破坏深度学习系统的完整性,导致系统做出错误或有害的决策。此外,后门攻击可能导致数据篡改,影响数据的真实性和准确性,造成严重的后果。

隐私泄露是后门攻击的另一大风险。攻击者可以通过后门获取用户数据,侵犯用户隐私,带来法律和道德风险。他们还可以获取模型中的敏感信息,对个人或组织造成威胁,增加了数据保护的难度。

image-20240731101116673.png
后门攻击也对信任问题造成影响。其风险可能导致用户对深度学习系统的信任下降,影响其在实际应用中的接受度和普及率。对于企业而言,如果其产品被发现存在后门,将会对商业信誉造成严重打击,影响市场竞争力。

后门攻击带来的社会影响不容忽视。它们可能被不法分子滥用,用于恶意目的,例如诈骗、数据盗窃和信息操纵等。此外,后门攻击的存在增加了对深度学习系统监管的难度,要求更严格的安全和隐私保护措施,以确保技术的安全和负责任的应用。

未知攻焉知防,接着我们分析与实现一些高级的后门攻击方案。

Input-Aware

理论

深度学习后门攻击是一种针对深度学习系统的安全威胁,它通过在模型的训练过程中植入特定的机制,使得模型在遇到某些特定的输入模式(即触发器)时,产生与正常行为不同的输出。这种攻击通常在模型的预期行为之外,执行攻击者预定的恶意行为。例如,在图像分类任务中,一个正常分类的网络在遇到含有特定触发器的图像时,可能会错误地将其分类为攻击者指定的类别

现有后门攻击技术的局限性主要在于它们依赖于固定的触发模式。这意味着无论输入数据是什么,触发器的样式和位置都是不变的。这种方法的缺点是触发器容易被检测出来,因为它们在所有被毒化的数据中都是相同的。一旦检测到,防御者可以通过特定的方法来缓解或移除这些后门,例如通过数据清洗或模型再训练。

Input-Aware Trigger 是就是本章要分析的一种新型后门攻击技术,其核心思想是生成与输入数据相关的动态触发器。这种触发器不是固定的,而是根据每个具体的输入样本来定制的,从而使得每个样本都有一个独特的触发条件。这样的设计带来了以下优势:

  1. 提高隐蔽性:由于触发器不是统一的,因此难以通过观察少量样本来发现其模式,这使得后门更难被发现。
  2. 增强鲁棒性:即使某些输入样本被清洗或改变了,只要触发器与输入数据紧密相关,后门攻击仍然可以成功执行。
  3. 避免重用性:每个触发器仅对生成它的特定输入有效,不能被用于其他输入样本,这增加了后门检测的难度。
  4. 对抗现有防御:现有的后门防御方法通常基于检测固定触发器的假设,而Input-Aware Trigger打破了这一假设,使得这些防御方法失效。

通过这种方式,攻击者可以创建一个看似正常但实际含有隐蔽后门的模型,这个模型在正常操作下表现良好,但在遇到特定的、为每个输入定制的触发器时,会执行恶意行为。这种攻击方法对现有的安全防御措施提出了新的挑战,并要求研究者开发新的检测和防御技术来应对这种威胁。

现在我们来形式化说明这种攻击方案

  • 分类器 ( f : X \rightarrow C ):一个将输入图像域 ( X ) 映射到目标类别集合 ( C ) 的函数。
  • 训练数据集 ( S = {(x_i, y_i) | x_i \in X, y_i \in C, i = 1, N} ):包含清洁图像及其标签的数据集。
  • 触发器 ( t = (m, p) ):由遮罩 ( m ) 和模式 ( p ) 组成的后门触发器。
  • 生成器函数 ( g : X \rightarrow P ):将输入图像域 ( X ) 映射到模式域 ( P ) 的函数,用于生成触发器。
  • 触发器生成 ( t = g(x) ):对于每个输入图像 ( x ),生成一个独特的触发器 ( t )。

image.png

  • 其中 ( \lambda_{div} ) 是多样性损失的权重。

在攻击方案中,攻击者首先设计一个触发器生成器,这是一个能够接受输入图像并输出相应触发模式的网络。该生成器利用多样性损失来确保不同输入图像产生的触发器之间存在显著差异,从而避免了触发器的重复性。这种设计使得即使在大量样本中,也很难找到一个统一的模式来描述所有的触发器。进一步地,Input-Aware 攻击方法引入了非重用性的概念。这意味着为特定输入生成的触发器不能被用于其他任何输入,从而大大增加了攻击的复杂性和检测难度。为了实现这一点,攻击者在训练过程中引入了交叉触发测试,确保一个输入上的触发器不会错误地激活其他输入样本的后门行为。

攻击者在训练过程中采用了三种模式:清洁模式、攻击模式和交叉触发模式。在清洁模式下,网络正常学习如何正确分类输入图像;在攻击模式下,网络被训练以在触发器出现时输出特定的攻击标签;而在交叉触发模式下,网络学习忽略其他图像的触发器,从而强化了触发器的非重用性。下图就是所说的三种模式

image-20240727232028699.png
整个训练的目标是通过最小化总损失函数来完成的,该损失函数是分类损失和多样性损失的加权和。分类损失确保了网络在不同模式下的正确分类,而多样性损失则推动了触发器生成器产生多样化的触发器。

通过这种方法,攻击者成功地训练出了一个在正常样本上表现良好,但在遇到特定触发器时能够执行后门行为的模型。

攻击的示意图如下所示

image-20240727232010805.png

复现

这个类实现了一个输入感知的生成器网络,具有多个卷积层和上/下采样层,适用于处理不同数据集的图像生成任务。正则化和反正则化方法确保输入数据在处理前后的正确缩放和标准化。

image-20240727232053362.png
这个类 InputAwareGenerator 是一个神经网络模型,用于处理图像数据,特别是为 MNIST 数据集和其他图像数据集设计的。

类初始化 (__init__ 方法)

  • __init__ 方法接受两个参数 argsout_channels

  • args 包含配置参数,比如数据集类型和输入通道数。

  • 根据数据集类型(mnist 或其他),初始化不同的通道数和步骤数:

    • 如果数据集是 mnist,初始化通道数为 16,步骤数为 2。
    • 否则,初始化通道数为 32,步骤数为 3。

模块添加

  • 初始化时,模型根据步骤数添加卷积层、下采样层和上采样层。

    • channel_current 初始化为输入通道数。
    • channel_next 初始化为 channel_init

卷积和下采样层

  • 使用 for 循环添加下采样卷积层:

    • 每一步添加两个卷积块 Conv2dBlock 和一个下采样块 DownSampleBlock
    • 每一步更新 channel_currentchannel_next
    • 当步骤数大于 1 时,channel_next 翻倍。

中间卷积层

  • 添加一个中间卷积块 Conv2dBlock

上采样层

  • 使用 for 循环添加上采样卷积层:

    • 每一步添加一个上采样块 UpSampleBlock 和两个卷积块 Conv2dBlock
    • 当到达最后一步时,第二个卷积块的 ReLU 激活函数被禁用。
    • 更新 channel_currentchannel_next
    • 倒数第二步时,根据是否提供 out_channels 来设置 channel_next 为输入通道数或 out_channels

正则化与反正则化

  • _EPSILON 定义为一个非常小的值,用于避免除零错误。
  • _normalizer_denormalizer 分别通过 _get_normalize_get_denormalize 方法获得,用于数据的正则化和反正则化。
  • tanh 是一个 Tanh 激活函数实例。

方法

  • _get_denormalize_get_normalize 方法:根据数据集的均值和标准差返回正则化和反正则化实例。
  • forward 方法:前向传播,依次通过所有添加的模块,最后应用 Tanh 激活函数。
  • normalize_pattern 方法:对输入进行正则化处理。
  • denormalize_pattern 方法:对输入进行反正则化处理。
  • threshold 方法:对输入应用 Tanh 激活函数,并进行缩放。

Threshold 类通过 Tanh 激活函数对输入数据进行特定的缩放和转换。

generalize_to_lower_pratio` 函数根据给定的毒样本比例和批次大小,计算批次中应该包含的毒样本数量,特别是在毒样本比例很低的情况下,确保毒样本的随机分布。

image-20240727232135081.png
这段代码定义了一个 Threshold 类和一个 generalize_to_lower_pratio 函数

Threshold 类

Threshold 类继承自 nn.Module,定义了一个自定义的神经网络层,用于对输入数据应用 Tanh 激活函数并进行特定的缩放。

初始化方法 (__init__)

  • __init__ 方法是类的构造函数,用于初始化类的实例。
  • 调用 super(Threshold, self).__init__() 来初始化父类 nn.Module
  • 定义一个 Tanh 激活函数实例并将其保存在 self.tanh 中。

前向传播方法 (forward)

  • forward 方法定义了当输入数据通过该层时的计算过程。
  • 接收输入 x,首先将其放大 20 倍,然后减去 10。
  • 应用 Tanh 激活函数。
  • 结果除以 2 + 1e-7 进行缩放,最后加上 0.5。
  • 返回处理后的结果。

这个类可以用于将输入数据缩放到 [0, 1] 范围内,并具有中心化的效果。

generalize_to_lower_pratio 函数

generalize_to_lower_pratio 函数用于根据给定的比例和批次大小计算每个批次中应该包含的“毒样本”数量(可能指有特殊标记的数据样本)。

函数参数

  • pratio:表示毒样本的比例。
  • bs:表示批次大小(batch size)。

函数逻辑

  • 首先检查 pratio * bs 是否大于等于 1。

    • 如果是,则表示每个批次中可以包含至少一个毒样本,返回 pratio * bs 作为毒样本的数量。

    • 如果不是,则处理特殊情况,决定是否在批次中包含一个毒样本。

      • 生成一个在 [0, 1) 范围内的随机数,如果该随机数小于 pratio * bs,则返回 1,表示该批次包含一个毒样本。
      • 否则返回 0,表示该批次不包含毒样本。

这个函数确保在毒样本比例非常低的情况下,批次中仍可能随机包含毒样本,从而实现毒样本在批次中的稀疏分布。

  • InputAware 类扩展了 BadNet 类,增加了自定义的命令行参数设置和数据准备方法。
  • 通过 set_bd_args 方法,可以灵活地配置攻击模型的参数。
  • stage1_non_training_data_prepare 方法确保第一阶段的非训练数据准备充分,包括创建必要的数据集和数据加载器。

image-20240727232144621.png

这个 InputAware 类继承自 BadNet 类,并扩展了其功能。主要包括初始化、设置命令行参数和准备非训练数据等方法

InputAware

InputAware 类是 BadNet 的子类,主要用于输入感知的攻击模型设置和数据准备。

初始化方法 (__init__)

  • 调用父类 BadNet 的初始化方法,通过 super(InputAware, self).__init__() 实现。

设置命令行参数 (set_bd_args 方法)

  • set_bd_args 是一个类方法,用于为攻击模型设置命令行参数。

  • 接受一个 argparse.ArgumentParser 实例 parser 作为参数,并返回更新后的 parser

  • 调用 add_common_attack_args 函数,添加一些常见的攻击参数。

  • 添加一系列特定的命令行参数,每个参数都有类型说明和可选的默认值:

    • --bd_yaml_path:指定 YAML 配置文件的路径。
    • --lr_G, --lr_C, --lr_M:学习率参数。
    • --C_lr_scheduler:学习率调度器类型。
    • --schedulerG_milestones, --schedulerC_milestones, --schedulerM_milestones:学习率调度器的里程碑列表。
    • --schedulerG_lambda, --schedulerC_lambda, --schedulerM_lambda:学习率调度器的 lambda 值。
    • --lambda_div, --lambda_norm:正则化参数。
    • --mask_density:掩码密度。
    • --EPSILON:用于避免除零错误的小值。
    • --clean_train_epochs:清洁训练的轮数。
    • --random_rotation, --random_crop:数据增强参数,如随机旋转和裁剪的范围。

准备非训练数据 (stage1_non_training_data_prepare 方法)

  • stage1_non_training_data_prepare 方法用于准备第一阶段的非训练数据。

  • 记录日志,表明第一阶段开始。

  • 确认 self 对象包含 args 属性。

  • 调用 benign_prepare 方法,获取一系列数据集和转换(transform):

    • train_dataset_without_transform:未经过转换的训练数据集。
    • train_img_transformtrain_label_transform:训练图像和标签的转换。
    • test_dataset_without_transform:未经过转换的测试数据集。
    • test_img_transformtest_label_transform:测试图像和标签的转换。
    • clean_train_dataset_with_transform:经过转换的清洁训练数据集。
    • clean_train_dataset_targets:清洁训练数据集的目标。
    • clean_test_dataset_with_transform:经过转换的清洁测试数据集。
    • clean_test_dataset_targets:清洁测试数据集的目标。
  • 创建四个数据加载器(dataloaders),用于处理转换后的清洁训练和测试数据集:

    • clean_train_dataloader1clean_train_dataloader2:两个清洁训练数据加载器。
    • clean_test_dataloader1clean_test_dataloader2:两个清洁测试数据加载器。
  • 将转换后的清洁训练数据集和四个数据加载器保存在 self.stage1_results 中。

这个函数 stage2_training 是一个神经网络的训练过程,特别是与数据中毒攻击相关的训练。

image-20240727232407311.png

  1. 准备阶段

    • 开始阶段2的训练,并输出日志信息。
    • 检查 self 对象中是否包含 args 属性,并获取该属性。
    • 创建一个 Metric_Aggregator 实例,用于收集训练过程中的各种指标。
    • stage1_results 中获取干净的训练和测试数据集及其数据加载器。
  2. 设置设备和模型

    • 确定设备为 GPU 或 CPU。如果有多个 GPU,则选择第一个 GPU。
    • 生成分类模型 netC、生成器 netG 以及一个单通道输出的生成器 netM,并将它们移动到指定设备。
    • 创建一个阈值模块 self.threshold 并移动到指定设备。
  3. 多 GPU 支持

    • 如果有多个 GPU,将模型和阈值模块包装为 DataParallel,以便支持多 GPU 并行计算。
  4. 设置优化器和学习率调度器

    • 为模型 netC 使用 SGD 优化器,并为 netGnetM 使用 Adam 优化器。
    • 根据配置参数选择学习率调度器。
  5. 标准化

    • 设置数据标准化方法,确保数据在训练和测试中具有相同的均值和标准差。
  6. 阶段2的训练过程

    • 设置初始 epoch 计数为 1。
    • 进行干净数据的训练,训练 netM 模型。每个 epoch 记录日志信息,并调用 train_mask_stepeval_mask 进行训练和评估。
    • 如果配置中设置了保存频率且满足条件,则保存 netM 的状态字典,包括模型参数、优化器状态、调度器状态和当前 epoch。
    • 训练完成后,将 netM 设置为评估模式,并禁止其梯度计算。
  7. 真实训练(攻击)

    • 初始化各种指标的列表,用于记录训练和测试过程中的损失、准确率等。
    • 进行训练和测试的循环。每个 epoch 输出日志信息,并调用 train_stepeval_step 进行训练和评估。
    • 在训练步骤中,计算并返回训练损失、混合准确率、干净准确率、攻击成功率、恢复率和交叉准确率。
    • 在评估步骤中,计算并返回干净测试损失、中毒测试损失、交叉测试损失、恢复测试损失、测试准确率、攻击成功率、恢复率和交叉测试准确率。

image-20240727232600798.png

这段代码涉及对数据集的预处理、数据加载和数据生成,并最终将这些数据保存到指定的文件夹

  1. 创建后门数据集对象bd_train_dataset是通过prepro_cls_DatasetBD_v2类生成的对象,传入的是经过转换后的干净训练数据集及一个保存路径。

  2. 创建可逆的图像变换

    • clean_train_dataset_with_transform中应用的图像变换进行筛选,只保留归一化、调整尺寸和转换为张量的变换。
    • 将筛选后的变换组合成一个新的变换transforms_reversible,并替换原始的图像变换,使其可逆。
  3. 获取反归一化器

    • 遍历transforms_reversible中的变换,查找归一化变换,并获取对应的反归一化器。
  4. 创建数据加载器

    • 创建clean_train_dataloader_without_shuffle,用于加载不打乱顺序的干净训练数据集。
    • clean_train_dataloader2的数据集的图像变换也设置为可逆的变换,并确保其加载的数据是打乱顺序的。
  5. 模型评估模式

    • netCnetG模型设置为评估模式,以确保在生成数据时不会更新模型参数。
  6. 数据生成和处理

    • 在不进行梯度计算的上下文中,遍历两个数据加载器,获取输入和目标。
    • 计算生成后门样本和交叉样本的数量。
    • 使用create_bd方法生成后门样本,使用create_cross方法生成交叉样本。
    • 将生成的后门样本和交叉样本连接起来,并进行反归一化处理。
  7. 保存生成的数据

    • 将生成的数据保存到bd_train_dataset中,确保样本和标签的正确性。
  8. 保存攻击结果

    • 调用save_attack_result方法,保存模型和数据的状态到指定路径。

通过这些步骤,代码完成了对数据的预处理、加载、生成和保存的全流程,确保生成的数据可以用于后续的模型训练或测试。

image-20240727232624289.png

这段代码定义了一个名为train_mask_step的函数,用于训练一个生成掩码的神经网络模型netM

  1. 设置模型为训练模式

    • 使用netM.train()将模型设置为训练模式,以启用训练特定的行为(如dropout)。
  2. 初始化变量

    • 初始化totaltotal_loss变量,用于跟踪训练过程中的总样本数和总损失。
    • 创建一个均方误差损失函数criterion_div,用于计算多样性损失。
  3. 遍历训练数据

    • 使用zip函数同时遍历两个训练数据加载器train_dataloader1train_dataloader2
    • inputs1inputs2是输入图像,targets1targets2是对应的目标标签。
    • 将输入和目标数据移动到指定的设备(如GPU)上,并禁用阻塞模式以提高数据加载效率。
  4. 计算掩码

    • 使用netM生成输入图像的掩码masks1
    • 使用self.threshold对掩码进行阈值处理,生成二值化的掩码masks1masks2
  5. 计算多样性损失

    • 使用criterion_div计算输入图像inputs1inputs2之间的距离,并取其平方根,得到distance_images
    • 使用criterion_div计算掩码masks1masks2之间的距离,并取其平方根,得到distance_patterns
    • 计算多样性损失loss_div,表示输入图像的距离与掩码距离的比值,并乘以一个超参数lambda_div
  6. 计算正则化损失

    • 使用ReLU函数对掩码进行密度约束,计算正则化损失loss_norm,表示掩码密度超出阈值的部分,并乘以一个超参数lambda_norm
  7. 计算总损失并进行反向传播

    • 将多样性损失和正则化损失加权求和,得到总损失total_loss
    • 对总损失进行反向传播,计算梯度。
    • 使用优化器optimizerM更新模型参数。
  8. 更新学习率

    • 使用学习率调度器schedulerM更新学习率。
  9. 输出训练信息

    • 格式化并输出当前批次的训练信息,包括掩码损失、正则化损失和多样性损失。
    • 使用progress_bar函数显示训练进度。

通过这些步骤,train_mask_step函数实现了对掩码生成模型的训练,包括计算损失、反向传播、参数更新和学习率调整。

image-20240727232853332.png

eval_mask函数

eval_mask函数用于评估生成掩码的神经网络模型netM。它遍历测试数据,计算和记录各种损失。

  1. 设置模型为评估模式

    • 使用netM.eval()将模型设置为评估模式,以禁用训练时特有的行为(如dropout)。
  2. 初始化变量

    • 初始化total变量(未使用),用于跟踪评估过程中的总样本数。
    • 创建一个均方误差损失函数criterion_div,用于计算多样性损失。
  3. 遍历测试数据

    • 使用zip函数同时遍历两个测试数据加载器test_dataloader1test_dataloader2
    • inputs1inputs2是输入图像,targets1targets2是对应的目标标签。
    • 将输入和目标数据移动到指定的设备(如GPU)上,并禁用阻塞模式以提高数据加载效率。
  4. 计算掩码

    • 使用netM生成输入图像的掩码masks1
    • 使用self.threshold对掩码进行阈值处理,生成二值化的掩码masks1masks2
  5. 计算多样性损失

    • 使用criterion_div计算输入图像inputs1inputs2之间的距离,并取其平方根,得到distance_images
    • 使用criterion_div计算掩码masks1masks2之间的距离,并取其平方根,得到distance_patterns
    • 计算多样性损失loss_div,表示输入图像的距离与掩码距离的比值,并乘以一个超参数lambda_div
  6. 计算正则化损失

    • 使用ReLU函数对掩码进行密度约束,计算正则化损失loss_norm,表示掩码密度超出阈值的部分。
  7. 输出评估信息

    • 格式化并输出当前批次的评估信息,包括正则化损失和多样性损失。
    • 使用progress_bar函数显示评估进度。
  8. 返回评估的轮次

    • 返回当前的评估轮次epoch

create_targets_bd函数

create_targets_bd函数用于创建后门攻击的目标标签,根据指定的攻击模式生成新的标签。

  1. 根据攻击模式生成标签

    • 如果攻击模式为"all2one",将所有标签转换为指定的攻击目标标签。
    • 如果攻击模式为"all2all",将所有标签转换为下一个类别标签。
    • 如果攻击模式未实现,抛出异常。
  2. 返回生成的后门目标标签

    • 将生成的目标标签移动到指定的设备上,并禁用阻塞模式以提高数据加载效率。
    • 返回生成的后门目标标签。

通过这些步骤,这两个函数分别实现了对掩码生成模型的评估和后门攻击目标标签的创建。

image-20240727232933333.png

这段代码定义了两个方法:create_bdcreate_cross,用于生成后门样本和交叉样本

create_bd方法

create_bd方法用于生成后门攻击的样本,依据不同的模式(训练或测试)进行不同的处理。

  1. 训练模式

    • 生成后门目标标签

      • 调用self.create_targets_bd生成后门目标标签bd_targets
    • 无样本情况

      • 如果inputs为空(即没有样本需要被污染),直接返回原始输入inputs、后门目标标签bd_targets、以及两个复制的inputs(没有改变的)。
    • 生成掩码和模式

      • 使用netG生成掩码patterns
      • 通过self.normalizerpatterns进行归一化处理。
      • 使用netM生成掩码输出masks_output,并通过self.threshold进行阈值处理。
    • 生成后门输入

      • 计算bd_inputs:将原始输入inputs与生成的模式patterns之间的差异,通过掩码masks_output调整。
    • 返回结果

      • 返回后门输入bd_inputs、后门目标标签bd_targets、生成的模式patterns、掩码masks_output
  2. 测试模式

    • 生成后门目标标签

      • 调用self.create_targets_bd生成后门目标标签bd_targets
    • 标记位置变化

      • 计算位置变化position_changed,标记目标标签bd_targets与原始目标标签targets之间的差异位置。
    • 筛选样本

      • 根据位置变化筛选输入inputs和后门目标标签bd_targets
    • 无样本情况

      • 如果筛选后的inputs为空,返回空张量torch.tensor([])、空后门目标标签、以及Nonepatternsmasks_output
    • 生成掩码和模式

      • 使用netG生成掩码patterns
      • 通过self.normalizerpatterns进行归一化处理。
      • 使用netM生成掩码输出masks_output,并通过self.threshold进行阈值处理。
    • 生成后门输入

      • 计算bd_inputs:将原始输入inputs与生成的模式patterns之间的差异,通过掩码masks_output调整。
    • 返回结果

      • 返回后门输入bd_inputs、后门目标标签bd_targets、生成的模式patterns、掩码masks_output、位置变化标记position_changed、以及原始目标标签targets

create_cross方法

create_cross方法用于生成交叉样本,即通过对另一组输入图像应用相同的模式生成的新样本。

  1. 无样本情况

    • 如果inputs1为空(即没有样本需要生成交叉样本),返回inputs2的副本、inputs2、以及副本的inputs2(没有改变的)。
  2. 生成掩码和模式

    • 使用netG生成patterns2,并通过self.normalizer进行归一化处理。
    • 使用netM生成掩码输出masks_output,并通过self.threshold进行阈值处理。
  3. 生成交叉样本

    • 计算inputs_cross:将inputs1与生成的模式patterns2之间的差异,通过掩码masks_output调整。
  4. 返回结果

    • 返回交叉样本inputs_cross、生成的模式patterns2、掩码masks_output

通过这些方法,可以在训练和测试阶段生成后门样本和交叉样本,并根据需要对样本进行处理和调整。

此时的中毒样本部分如下所示

image-20240727233157509.png

image-20240727233219765.png

image-20240727233231041.png

现在开始植入后门

image-20240724201826100.png
训练期间部分截图如下

image-20240724201938041.png

image-20240724202012645.png

image-20240724202202062.png

image-20240724202909111.png
在上图可以看到,在第43个epoch时,正常任务的acc达到了0.87,而后门攻击的成功率达到了0.87

LIRA

LIRA是一种先进的后门攻击框架,它通过联合学习最优的隐蔽触发器注入函数和对模型进行“投毒”,以实现在特定触发模式下操纵模型行为的目的。与传统的后门攻击方法相比,LIRA的主要创新之处在于其自动化的触发器生成过程和对模型的非线性参数空间的优化。

LIRA的核心是一个非凸的、受约束的优化问题,它将触发器的生成和模型的“投毒”统一在一个框架下。通过这种方式,LIRA能够在保持模型在正常数据上的性能的同时,最大化在被“投毒”数据上的攻击成功率。优化问题的目标是找到一组参数,使得模型在遇到带有特定触发器的输入时能够按照攻击者的意图进行分类,而在没有触发器的情况下则保持正常的分类行为。

为了解决这个优化问题,LIRA采用了一个两阶段的随机优化过程。在第一阶段,同时更新触发器函数和分类器,使用一种交替更新的策略来避免训练过程中的不稳定性和陷入局部最小值。在第二阶段,只对分类器进行微调,以进一步提高其在正常数据上的性能。

现在我们来形式化这个攻击方法

LIRA方案的核心是通过数学公式定义的优化问题来实现后门攻击的自动化和隐蔽性

触发器函数定义:

image-20240727233835693.png

其中,( T(x) ) 是被触发器转换后的输入,( x ) 是原始输入,( g(x) ) 是一个生成不可见噪声的模型,用于在原始输入上添加难以察觉的变化。

优化问题的目标函数

image-20240727233855889.png

这里,( \theta ) 是分类器的参数,( \xi^* ) 是触发器函数的最优参数。( L ) 是损失函数,( \alpha ) 和 ( \beta ) 是控制干净数据和后门数据损失信号混合强度的标量参数。第一个项是干净数据上的损失,第二个项是后门数据上的损失。

约束条件

image-20240727233916505.png

其中,( d(\cdot, \cdot) ) 是衡量两个图像视觉差异的距离函数,( \epsilon ) 是一个阈值参数,确保( T(x) ) 与 ( x ) 在视觉上不可见的差异。

触发器函数的优化

image-20240727233928245.png
这个公式定义了触发器函数( T*{\xi} )的优化目标,即在给定分类器( f*{\theta} )的情况下,找到参数( \xi )使得后门攻击的损失最小化。 LIRA的训练过程包括两个阶段。第一阶段同时更新分类器( f )和触发器( T ),第二阶段仅微调分类器( f )。这个过程通过交替随机梯度下降(SGD)来实现,其中触发器的更新依赖于分类器在后门数据上的表现。

LIRA方案的关键在于通过这些公式定义的优化问题来自动化地寻找最优的触发器注入函数和“投毒”分类器。通过这种方式,LIRA能够在不显著降低模型在正常数据上的性能的同时,实现对模型的隐蔽操控。

完整的后门攻击示意图如下所示

image-20240727233954996.png

下图的伪码给出了攻击算法

image-20240727234040366.png

复现

定义一个自动编码器(Autoencoder)模型,并包含一个辅助函数 double_conv

image-20240727234103745.png

Autoencoder 类

  1. 初始化方法 __init__:

    • channels 参数:指定输入图像的通道数,默认为 3(通常用于 RGB 图像)。

    • self.encoder:这是一个包含多个卷积层的序列模块。每个卷积层后面跟着批量归一化层(BatchNorm2d)和激活函数(ReLU)。

      • 卷积层的作用是提取输入数据中的特征。每层的通道数从 16 增加到 128,卷积核的大小为 4x4,步幅为 2x2,填充为 1。
    • self.decoder:这是一个包含多个转置卷积层(ConvTranspose2d)的序列模块,用于将编码后的特征图还原为原始图像的尺寸。

      • 转置卷积层的作用是将特征图上采样(即扩大),逐步恢复到输入图像的尺寸。每层的通道数从 128 减少到输入图像的通道数(默认为 3),卷积核的大小为 4x4,步幅为 2x2,填充为 1。
      • 最后一层使用 Tanh 激活函数,将输出映射到 -1 到 1 的范围,这通常是为了与输入图像的归一化范围匹配。
  2. 前向传播方法 forward:

    • 输入 x 经过编码器(self.encoder)提取特征。
    • 然后通过解码器(self.decoder)将特征还原为原始图像的尺寸。
    • 返回还原后的图像。

double_conv 函数

  • 这是一个辅助函数,用于构建一个包含两个卷积层的模块。

    • in_channels:输入通道数。
    • out_channels:输出通道数。
    • 每个卷积层后面跟着批量归一化层(BatchNorm2d)和 ReLU 激活函数。
    • double_conv 函数返回一个序列模块,该模块由两个连续的卷积层组成,每层卷积的大小为 3x3,填充为 1。这样的设计有助于逐步提取更复杂的特征。

实现一个 U-Net 模型,这是一个常用于图像分割的神经网络架构

image-20240727234135159.png

UNet 类

  1. 初始化方法 __init__:

    • out_channel 参数:指定模型的输出通道数,这通常是分割任务中类别的数量。

    • 编码器部分(下采样):

      • self.dconv_down1self.dconv_down4:这四个模块是由 double_conv 函数构建的卷积块,用于逐步提取图像特征。每个模块中的卷积层的通道数逐渐增加,从 64 到 512。
    • 最大池化和上采样:

      • self.maxpool:平均池化层(AvgPool2d),用于下采样和减少特征图的尺寸。
      • self.upsample:上采样层(Upsample),用于逐步恢复特征图的尺寸。使用双线性插值(bilinear)进行上采样。
    • 解码器部分(上采样):

      • self.dconv_up1self.dconv_up3:这些模块用于将特征图上采样并与相应的编码器特征图进行拼接(skip connection)。通道数在上采样过程中逐渐减少。
    • 最后的卷积层:

      • self.conv_last:一个卷积层和批量归一化层,用于将解码后的特征图映射到最终的输出通道数。
    • 输出激活函数:

      • self.out_layer:使用 Tanh 激活函数将输出映射到 [-1, 1] 的范围,这对于某些任务(如图像生成)是常见的。
  2. 前向传播方法 forward:

    • conv1conv2conv3:这些变量存储了经过编码器处理的特征图。
    • 在每个下采样步骤后,使用最大池化层将特征图尺寸减小。
    • self.dconv_down4:对最后一个下采样后的特征图进行处理。
    • 使用上采样层逐步恢复特征图的尺寸,并将上采样后的特征图与相应的编码器特征图进行拼接(skip connection)。这样可以结合高分辨率的特征图和低分辨率的上下文信息。
    • self.dconv_up3self.dconv_up2self.dconv_up1:处理上采样后的特征图。
    • self.conv_last:将处理后的特征图映射到最终的输出通道数。
    • self.out_layer:应用 Tanh 激活函数,以获得最终的输出结果。

U-Net 的关键特点是它的对称结构和跳跃连接(skip connections),这些特性使它在图像分割任务中表现出色。

image-20240727234304355.png

这段代码定义了一个 hp_test 函数,用于测试一个模型在攻击和防御场景下的表现。函数的作用是评估在特定条件下模型的性能,包括处理攻击数据的能力以及正常数据的处理能力

函数参数

  • args: 包含各种参数的对象,如学习率、攻击强度等。
  • atkmodel: 攻击模型,用于生成对抗样本。
  • scratchmodel: 待测试的模型(即被攻击和训练的模型)。
  • target_transform: 一个函数,用于对目标标签进行转换,通常在处理对抗攻击时使用。
  • train_loader: 训练数据加载器。
  • test_loader: 测试数据加载器。
  • epoch: 当前的训练轮数。
  • trainepoch: 总训练轮数。
  • clip_image: 用于裁剪或限制对抗样本的函数,以确保它们在有效范围内。
  • testoptimizer: 测试阶段使用的优化器。如果未提供,将在函数内部创建一个默认的优化器。
  • log_prefix: 日志前缀,用于标记日志信息。
  • epochs_per_test: 每隔多少轮进行一次测试。

函数内部实现

  1. 设置测试参数:

    • 如果 args.test_alphaargs.test_eps 没有设置,使用默认的 args.alphaargs.eps
  2. 初始化变量:

    • test_losscorrect:用于跟踪测试集的损失和准确度。
    • correct_transformtest_transform_loss:用于跟踪对抗攻击后的损失和准确度。
  3. 设置模型为评估模式:

    • atkmodel.eval():将攻击模型设置为评估模式,这样它不会进行训练更新。
  4. 初始化测试优化器:

    • 如果未提供 testoptimizer,则为 scratchmodel 创建一个新的 SGD 优化器。
  5. 训练阶段:

    • 对于每一个训练轮次 cepoch,在 train_loader 中遍历每一个批次。

    • 对每批数据和目标进行前向传播:

      • 使用攻击模型生成对抗样本 atkdata
      • 使用 scratchmodel 计算对抗样本和原始样本的损失。
      • 计算总损失,并进行反向传播和优化步骤。
  6. 测试阶段:

    • 每隔 epochs_per_test 轮或在最后一轮时进行测试:

      • test_loader 中遍历每一个批次。
      • 对每批数据进行前向传播,计算原始数据和对抗数据的损失和准确度。
      • 计算总体损失和准确度,并记录到日志中。
  7. 返回结果:

    • 返回模型在正常数据和对抗数据上的准确度。

关键点

  • 对抗训练: 在训练过程中,使用对抗样本来增强模型的鲁棒性。对抗样本是通过攻击模型生成的带噪声的数据。
  • 损失函数: 使用交叉熵损失函数来计算损失,并将对抗损失和正常损失加权组合。
  • 准确度计算: 使用 torch.max 来获取预测结果,并与目标进行比较,计算正确预测的数量。
  • 日志记录: 将测试结果记录到日志中,以便跟踪模型的性能。

image-20240727234410208.png

这段代码定义了 main 函数,用于执行整个训练和测试流程,包括模型训练、对抗攻击生成、测试评估等步骤

函数参数

  • args: 包含训练和测试所需的各种参数。
  • clean_test_dataset_with_transform: 经过转换的干净测试数据集。
  • criterion: 损失函数,用于计算模型的损失。

函数内部实现

  1. 初始化数据加载器:

    • 使用 DataLoader 创建一个 clean_test_dataloader,用于加载经过转换的干净测试数据集。
  2. 初始化列表和聚合器:

    • clean_test_loss_listbd_test_loss_listtest_acc_listtest_asr_listtest_ra_listtrain_loss_list:用于存储每个阶段的损失和准确度指标。
    • agg = Metric_Aggregator():用于聚合和存储测试指标的对象。
  3. 日志记录:

    • 如果 args.verbose >= 1,则记录参数设置和数据加载器的信息。
  4. 获取数据加载器和转换函数:

    • train_loader, test_loader, clip_image:从 get_train_test_loaders 函数获取训练和测试数据加载器,以及裁剪图像的函数。
    • post_transforms:应用于图像的后处理转换。
  5. 创建模型:

    • atkmodel, tgtmodel, tgtoptimizer, clsmodel, create_net:从 create_models 函数获取攻击模型、目标模型、目标优化器、分类模型以及创建网络的函数。
  6. 目标标签转换函数:

    • target_transform:用于将目标标签转换为适当的格式,通常用于对抗攻击中的目标标签。
  7. 初始化和训练模型:

    • tgtmodel 的权重初始化为 atkmodel 的权重。
    • clsmodel 迁移到 GPU 并创建优化器 clsoptimizer
    • 如果 args.device 包含多个设备,则使用 torch.nn.DataParallel 进行数据并行处理。
  8. 训练过程:

    • 通过 train 函数进行模型训练,并将训练损失存储到 trainlosses 列表中。
    • 训练过程中,将攻击模型的权重复制到目标模型,并根据需要重新初始化 clsmodel
  9. 测试阶段:

    • 设置模型为评估模式,并将模型移动到设备上。
    • 处理 bd_test_datasetbd_test_dataloader,这是处理对抗攻击数据的测试数据集。
    • 使用 given_dataloader_testtest_given_dataloader_on_mix 函数计算干净测试和对抗测试的指标。
    • 计算并记录测试损失、准确度、攻击成功率(ASR)和鲁棒性(RA)。
  10. 绘图和结果保存:

    • 调用 plot_lossplot_acc_like_metric 函数生成和保存损失和准确度的图表。
    • 将指标保存到 CSV 文件中,以便进一步分析。
  11. 返回结果:

    • 返回训练后的分类模型、攻击模型以及对抗测试数据加载器。

关键点

  • 数据并行: 如果使用多个 GPU 进行训练,将模型包装在 torch.nn.DataParallel 中以实现数据并行。
  • 训练和测试: 进行模型训练并在每个训练周期后进行评估,包括对抗攻击数据和正常测试数据。
  • 指标计算和记录: 计算并记录训练损失、测试损失、测试准确度、攻击成功率和鲁棒性,并将结果保存到文件中以便分析。

image-20240727234508816.png

这段代码定义了 main2 函数,旨在执行模型的第二阶段训练和测试。这些步骤包括对模型进行微调,使用预训练模型的权重,并在对抗攻击数据和干净数据上进行最终测试:

函数参数

  • args: 包含训练和测试所需的参数。
  • pre_clsmodel: 预训练的分类模型。
  • pre_atkmodel: 预训练的攻击模型。
  • clean_test_dataloader: 用于测试干净数据的 DataLoader。
  • bd_test_dataloader: 用于测试对抗数据的 DataLoader。
  • criterion: 损失函数。

函数内部实现

  1. 处理 args 参数:

    • 创建 args_for_finetune 对象并从中提取以 finetune_ 开头的参数。
    • 如果 args.test_alphaargs.finetune_lrargs.test_epsNone,则将它们设置为相应的训练参数或默认值。
  2. 日志记录:

    • 记录当前使用的参数和设备信息。
  3. 设备设置:

    • 检查是否有可用的 CUDA 设备,并设置为 "cuda""cpu"
  4. 获取数据加载器和模型:

    • 调用 get_train_test_loaders 函数获取训练和测试数据加载器及图像裁剪函数。
    • create_models 函数中创建攻击模型、目标模型、目标优化器及网络创建函数。
    • 使用 get_model 函数获取分类模型、优化器和学习率调度器。
  5. 数据并行处理:

    • 如果 args.device 包含多个设备,将分类模型和攻击模型包装在 torch.nn.DataParallel 中以实现数据并行处理。
  6. 模型权重加载:

    • 将预训练的分类模型和攻击模型的权重加载到当前模型中。
  7. 模型配置和优化器设置:

    • 将分类模型 (netC) 移动到设备上,并根据 args_for_finetune 配置优化器和学习率调度器。
    • 记录优化器和学习率调度器的设置。
  8. 数据转换和最终测试:

    • 使用 PostTensorTransform 函数创建数据转换对象。

    • 调用 final_test 函数进行最终测试,其中包括干净数据和对抗数据的测试。这个函数执行以下操作:

      • 进行模型微调。
      • 计算和记录最终测试的准确度和其他指标。

关键点

  • 参数处理: 确保使用合适的微调参数和默认值。
  • 模型和设备设置: 进行模型初始化和设备配置,包括数据并行处理。
  • 模型微调: 加载预训练权重并设置优化器和调度器以进行微调。
  • 最终测试: 执行最终的测试步骤,以评估模型在干净数据和对抗数据上的表现。

image-20240727234557854.png
这段代码定义了一个名为 LIRA 的类,它继承自 BadNet 基类:

初始化 (__init__ 方法)

  • __init__ 方法:这个方法用于初始化 LIRA 类的实例,通过 super() 调用父类 BadNet 的初始化方法。

参数解析 (set_bd_args 方法)

  • set_bd_args 方法:该方法使用 argparse 定义了一系列命令行参数。这些参数包括攻击配置的各种选项,如:

    • --attack:攻击类型。
    • --attack_target:攻击的目标类别。
    • --attack_label_trans:攻击中标签修改的类型。
    • --bd_yaml_path:包含附加默认属性的 YAML 文件路径。
    • --random_crop, --random_rotation:图像变换参数。
    • --attack_model:攻击模型类型。
    • --lr_atk, --eps, --alpha:攻击设置的参数。
    • --finetune_lr, --finetune_steplr_gamma, --finetune_optimizer:微调模型的参数。
    • 其他用于训练配置和测试的参数。

阶段 1: 数据准备 (stage1_non_training_data_prepare 方法)

  • stage1_non_training_data_prepare 方法:这是一个占位符方法(pass 语句),意味着它是预留给子类重写或扩展的,但当前并未执行任何操作。

阶段 2: 训练 (stage2_training 方法)

  • stage2_training 方法:该方法处理训练过程。主要步骤包括:

    • 准备

      • 调用 self.benign_prepare() 准备数据集和变换。
      • 设置测试数据集的 DataLoader
    • 模型设置

      • 使用 generate_cls_model 函数创建分类模型,并根据指定的设备(GPU 或 CPU)设置模型。
      • 如果指定了多个 GPU,使用 torch.nn.DataParallel 进行并行计算。
    • 训练

      • 定义损失函数(criterion)并创建模型、攻击模型及数据加载器。
      • 调用 mainmain2 函数进行模型训练和测试。
    • 保存结果

      • 调用 save_attack_result 函数保存攻击结果,包括模型状态、数据路径等信息。

此时该方案得到的部分中毒样本如下所示

image-20240727234742441.png

image-20240727234751517.png

image-20240727234800838.png
开始进行后门攻击

image-20240724204102794.png

训练期间的部分截图如下所示

image-20240724204120866.png

image-20240724204140325.png

image-20240724204759312.png

可以看到尽管后门攻击成功率很高,但是正常任务的准确率还是较低的。

Refool

尽管现有的后门攻击方法在技术上是可行的,但它们往往因为对训练数据或标签的明显修改而容易被检测到。这种可检测性限制了后门攻击在实际应用中的隐蔽性和有效性。为了提高后门攻击的隐蔽性,研究人员需要开发出一种新的攻击手段,它能够在不引起怀疑的情况下修改模型的行为。这种攻击手段应该能够在不显著降低模型在正常数据上的性能的同时,对含有特定模式的输入实现控制。 自然界中普遍存在的现象,如反射,为实现这种隐蔽的后门攻击提供了可能。

反射现象在日常生活中随处可见,例如在玻璃或光滑表面上的镜像。由于反射本身是一种自然且不易被察觉的现象,将其作为后门的触发器,可以在不引起注意的情况下激活后门反射后门攻击(Refool)是一种新颖的后门攻击方法,灵感来源于自然界中普遍存在的反射现象。这种方法利用了物理世界中物体在玻璃或其他光滑表面上的反射特性,将这些反射作为后门触发器植入到深度学习模型中。这种方法的创新之处在于,它不依赖于人为设计的特殊图案或标签修改,而是利用了自然存在的物理现象。 在Refool攻击中,攻击者通过在训练数据中注入带有反射的图像来植入后门。这些反射图像是通过数学建模生成的,模拟了真实世界中反射的物理过程。当模型在推理阶段遇到含有这些反射特征的输入图像时,会被诱导预测特定的目标类别,即使这些图像在视觉上看起来与正常图像无异。

为了实现这一攻击,首先定义了反射图像的数学模型。具体来说,反射图像可以通过将原始图像与反射图像结合来生成,这一过程可以用卷积核表示。这种结合模拟了真实世界中光线在光滑表面上的反射行为。

三种反射类型: 考虑三种不同的反射类型,每种类型对应不同的物理场景:

  1. 同焦平面反射:主要对象和反射图像位于同一焦平面上,这种情况下的反射强度可以通过一个简单的强度因子来控制。
  2. 失焦反射:反射层与主要对象在不同的焦平面上,导致反射图像呈现为模糊的叠加效果。
  3. 幽灵效应:考虑了玻璃的厚度,反射光线可能会在玻璃上产生多次反射,形成复杂的反射模式。

攻击流程包括三步

生成反射图像: 攻击的第一步是生成带有反射的后门图像。这些图像通过将反射图像与干净图像结合生成,模拟了真实世界中的反射现象。

训练受害模型: 接下来,攻击者在包含这些反射图像的训练集上训练深度学习模型。这个训练集由原始的训练数据和被反射图像污染的数据组成。通过这种方式,模型在学习过程中“记住”了反射图像与特定类别的关联。

推理阶段的攻击: 在模型部署后的推理阶段,攻击者可以通过在任何输入图像中添加反射图像来激活后门。这些反射图像会触发模型预测特定的目标类别,从而实现攻击。

现在我们来形式化这个攻击方案

在深度学习中,我们通常有一个K类图像数据集

image-20240727235508845.png

,其中

image-20240727235519283.png

是一个输入样本,

image-20240727235646199.png
是它的正确标签。分类任务的目标是学习一个函数

image-20240727235637232.png

通常由深度神经网络(DNN)表示,将输入空间映射到标签空间。后门攻击的目标是在模型中植入一个后门,使得当输入图像包含特定的后门模式时,模型预测为攻击者指定的类别( y_{adv} )。

反射是当光线遇到光滑表面(如玻璃)时发生的现象。在数学上,我们可以将反射图像的形成过程建模为:

image-20240727235657494.png
其中:

  • ( x ) 是干净的背景图像。
  • ( x_R ) 是反射图像。
  • ( k ) 是卷积核,用于模拟反射的视觉效果。
  • ( \otimes ) 表示卷积操作。

反射可以分为三种类型:

  1. 同焦平面反射(Type I):主要对象和反射图像位于同一焦平面上。这种情况下,( k )可以简化为一个强度因子( \alpha ),通常从均匀分布( U[0.05, 0.4] )中选择。
  2. 失焦反射(Type II):反射层与主要对象在不同的焦平面上。这种情况下,( k )依赖于相机的点扩散函数(PSF),可以用一个2D高斯核表示:

image-20240727235712663.png

  1. 其中( x_c )是核的中心,( \sigma )从均匀分布( U[1, 5] )中选择。
  2. 幽灵效应(Type III):考虑玻璃的厚度,反射光线可能会在玻璃上产生多次反射。这种情况下,( k )可以建模为一个双脉冲核:

image-20240727235720535.png

其中( \alpha )是强度因子,( \delta )是空间偏移,两者的值分别从( U[0.15, 0.35] )和( U[3, 8] )中选择。

首先生成带有反射的后门图像,通过将反射图像( x_R )与干净图像( x )结合,遵循上述三种反射模型之一。

在被污染的训练集( D_{adv}^{train} )上训练受害者模型,该训练集包括带有反射的后门图像和干净图像。

在推理阶段,任何包含反射模式的输入图像( x*{adv} )都会被模型一致地预测为特定的目标类别( y*{adv} )。

完整的攻击流程如下图所示

image-20240727235756205.png

实现

image-20240727235827505.png
这段代码定义了一个 blend_images 函数,用于将两张图像进行混合,生成一个融合效果的图像

  1. 输入参数

    • img_timg_r:输入的两张图像,可以是 PIL 图像对象或 numpy 数组。
    • max_image_size:最大图像尺寸,用于调整图像大小。
    • ghost_rate:鬼影效果的概率。
    • alpha_t:深度场的强度,负值表示随机选择。
    • offset:鬼影效果的空间偏移量。
    • sigma:模糊效果的标准差,负值表示随机选择。
    • ghost_alpha:鬼影效果的透明度,负值表示随机选择。
  2. 图像预处理

    • 将输入图像 img_timg_r 转换为浮点数,并将像素值归一化到 0 到 1 之间。
    • 根据 max_image_size 缩放图像,以确保最大边的长度不超过 max_image_size。缩放后调整图像的尺寸。
  3. 生成鬼影效果

    • 如果 alpha_t 是负值,则随机选择一个介于 0.05 到 0.45 之间的值作为 alpha_t

    • 根据 ghost_rate 的概率决定是否应用鬼影效果。如果应用:

      • 对图像进行伽玛校正。
      • 根据 offset 生成具有鬼影效果的图像。ghost_alpha 用于控制鬼影的强度。如果 ghost_alpha 是负值,则随机选择一个值。
      • 计算鬼影效果的图像,并将其缩放到与原图像相同的尺寸。
      • 计算反射层、融合图像和传输层,并将其值从 0 到 1 的范围映射到 0 到 255 的范围。
  4. 生成焦外模糊效果

    • 如果没有应用鬼影效果,则应用焦外模糊效果。如果 sigma 是负值,则随机选择一个介于 1 到 5 之间的值。
    • 对图像进行伽玛校正。
    • 生成模糊图像,并应用焦外模糊。
    • 对模糊图像进行调整,以使其范围在 0 到 1 之间。
    • 生成高斯核用于模糊,并根据 alpha_t 计算 alpha 通道。
    • 根据 alpha 通道计算模糊的反射层和融合图像。
    • 将融合图像和模糊图像从 0 到 1 的范围映射到 0 到 255 的范围。
  5. 返回结果

    • 返回三个图像:blended(融合图像)、transmission_layer(传输层)和 reflection_layer(反射层),它们都被转换为 0 到 255 的整数范围,以便于显示或保存。

RefoolTrigger 类用于对图像应用特定的混合效果,包括鬼影效果。它从给定的图像列表中随机选择一张反射图像,并将其与输入图像混合,使用各种参数控制效果的强度和外观

image-20240728000002865.png

这段代码定义了一个名为 RefoolTrigger 的类,用于对图像应用特定的变换效果,可能用于数据增强或对抗攻击

RefoolTrigger

__init__ 方法

构造函数用于初始化类的实例,接收以下参数:

  • R_adv_pil_img_list:一个包含多张 PIL 格式图像的列表,这些图像将作为反射或叠加层使用。
  • img_height:目标图像的高度。
  • img_width:目标图像的宽度。
  • ghost_rate:控制图像上鬼影效果强度或比例的参数。
  • alpha_t:景深或强度数值。如果设置为负值,则会随机选择强度。
  • offset:一个元组,指定鬼影效果的空间位移。
  • sigma:用于控制模糊或虚焦效果的参数。负值表示将随机选择该值。
  • ghost_alpha:鬼影效果的透明度。负值表示将随机选择该值。

__call__ 方法

__call__ 方法使得类的实例可以像函数一样被调用。它接受一个图像 (img),以及可选的目标和图像序列 ID,然后调用 add_trigger 方法来应用效果。

add_trigger 方法

该方法用于对输入图像应用触发效果:

  • reflection_pil_img:从 R_adv_pil_img_list 中随机选择一张图像,用作反射或叠加层。

  • blend_images:这个函数负责将选择的反射图像与输入图像 (img) 进行混合。它使用以下参数:

    • max_image_size:图像的最大尺寸,设置为 img_heightimg_width 中的较大者。
    • ghost_rate:控制鬼影效果的强度或比例。
    • alpha_t:景深效果或强度。
    • offset:鬼影效果的空间位移。
    • sigma:模糊或虚焦效果的强度。
    • ghost_alpha:鬼影效果的透明度。

函数返回一个元组,其中第一个元素是混合后的图像。方法返回这个混合图像。

Refool 类用于准备和生成带有触发器的训练和测试数据集。它通过设置各种参数来控制图像的混合效果,并应用这些效果到数据集上。数据集准备包括加载图像、定义变换、生成触发器、并创建用于训练和测试的数据集。

image-20240728000023932.png

这段代码定义了一个 Refool 类,继承自 BadNet 类。Refool 类包含了用于处理图像数据的功能,特别是用于生成带有触发器(backdoor)的数据集

Refool

set_bd_args 方法

这个方法用于设置和解析命令行参数:

  • parser: argparse.ArgumentParser: 一个 argparse.ArgumentParser 对象,用于处理命令行参数。
  • --r_adv_img_folder_path: 反射图像所在的文件夹路径,用于生成混合图像。
  • --bd_yaml_path: YAML 配置文件的路径,提供额外的默认属性。
  • --ghost_rate: 混合图像的鬼影率。
  • --alpha_t: 景深或强度数值。负值表示随机选择。
  • --offset: 鬼影效果的空间位移。
  • --sigma: 虚焦效果的强度。负值表示随机选择。
  • --ghost_alpha: 鬼影效果的透明度。负值表示随机选择。
  • --clean_label: 用于设置是否干净标签(1 表示是,其他值表示不是)。

这些参数用来配置数据准备过程中的各种设置。

stage1_non_training_data_prepare 方法

这个方法用于准备阶段一的数据:

  1. 日志记录: 记录阶段开始的信息。

  2. 数据准备:

    • 调用 benign_prepare() 方法准备数据集,得到未变换的数据集、变换函数以及标签转换函数。
    • 使用 transforms.Compose 定义图像变换,包括调整图像大小和转换为 NumPy 数组。
  3. 读取反射图像:

    • 遍历指定文件夹中的图像文件,加载并进行预处理,保存到 reflection_img_list 列表中。
  4. 创建触发器:

    • 实例化 RefoolTrigger,传入反射图像列表及其他参数,创建触发器对象。
  5. 定义图像变换:

    • 为训练和测试数据定义图像变换流程,包括调整大小、转换为 NumPy 数组以及应用触发器。
  6. 生成标签转换函数:

    • 调用 bd_attack_label_trans_generate 方法生成用于触发攻击的标签转换函数。
  7. 准备训练数据集:

    • 生成毒性样本的索引,并保存。
    • 使用 prepro_cls_DatasetBD_v2 创建带有触发器的训练数据集,并将其包装在变换函数中。
  8. 准备测试数据集:

    • 生成测试集中的毒性样本索引。
    • 使用 prepro_cls_DatasetBD_v2 创建带有触发器的测试数据集,并将其包装在变换函数中。
  9. 保存结果:

    • 将准备好的数据集保存到类的属性 stage1_results 中。

应用该方案得到的中毒样本部分如下所示

image-20240728000251668.png

image-20240728000313288.png

image-20240728000323377.png

开始注入后门

image-20240724204217041.png

训练期间的部分截图如下所示

image-20240724204238417.png

image-20240724204615702.png

image-20240724204636203.png

在上图可以看到,正常任务准确率与后门攻击成功率都达到了不错的水平。

参考

1.https://arxiv.org/abs/2010.08138

2.https://arxiv.org/abs/1912.02771

3.https://arxiv.org/pdf/2007.02343

4.https://aisecure.github.io/PROJECTS/robust_ml.html

5.https://www.researchgate.net/figure/Difference-between-backdoor-and-adversarial-attack_fig2_360724485

6.https://www.mdpi.com/2076-3417/11/21/9938

  • 发表于 2024-10-22 10:00:02
  • 阅读 ( 23996 )
  • 分类:漏洞分析

0 条评论

请先 登录 后评论
elwood1916
elwood1916

29 篇文章

站长统计