maltorch 0.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (83) hide show
  1. maltorch-0.1/PKG-INFO +44 -0
  2. maltorch-0.1/README.md +7 -0
  3. maltorch-0.1/setup.cfg +4 -0
  4. maltorch-0.1/setup.py +63 -0
  5. maltorch-0.1/src/maltorch/VERSION +1 -0
  6. maltorch-0.1/src/maltorch/__init__.py +0 -0
  7. maltorch-0.1/src/maltorch/adv/__init__.py +0 -0
  8. maltorch-0.1/src/maltorch/adv/evasion/__init__.py +1 -0
  9. maltorch-0.1/src/maltorch/adv/evasion/backend_attack.py +122 -0
  10. maltorch-0.1/src/maltorch/adv/evasion/base_optim_attack_creator.py +114 -0
  11. maltorch-0.1/src/maltorch/adv/evasion/content_shift.py +121 -0
  12. maltorch-0.1/src/maltorch/adv/evasion/gamma_section_injection.py +94 -0
  13. maltorch-0.1/src/maltorch/adv/evasion/gradfree_attack.py +70 -0
  14. maltorch-0.1/src/maltorch/adv/evasion/gradient_attack.py +39 -0
  15. maltorch-0.1/src/maltorch/adv/evasion/padding.py +111 -0
  16. maltorch-0.1/src/maltorch/adv/evasion/partialdos.py +107 -0
  17. maltorch-0.1/src/maltorch/adv/evasion/section_injection.py +128 -0
  18. maltorch-0.1/src/maltorch/data/__init__.py +0 -0
  19. maltorch-0.1/src/maltorch/data/loader.py +41 -0
  20. maltorch-0.1/src/maltorch/data_processing/__init__.py +0 -0
  21. maltorch-0.1/src/maltorch/data_processing/drs_preprocessing.py +41 -0
  22. maltorch-0.1/src/maltorch/data_processing/dynamic/__init__.py +0 -0
  23. maltorch-0.1/src/maltorch/data_processing/dynamic/constants.py +68 -0
  24. maltorch-0.1/src/maltorch/data_processing/dynamic/emulation.py +162 -0
  25. maltorch-0.1/src/maltorch/data_processing/dynamic/normalization.py +101 -0
  26. maltorch-0.1/src/maltorch/data_processing/dynamic/tokenization.py +459 -0
  27. maltorch-0.1/src/maltorch/data_processing/grayscale_preprocessing.py +64 -0
  28. maltorch-0.1/src/maltorch/data_processing/majority_voting_postprocessing.py +31 -0
  29. maltorch-0.1/src/maltorch/data_processing/random_drs_preprocessing.py +50 -0
  30. maltorch-0.1/src/maltorch/data_processing/rs_preprocessing.py +44 -0
  31. maltorch-0.1/src/maltorch/data_processing/rsdel_preprocessing.py +43 -0
  32. maltorch-0.1/src/maltorch/data_processing/sequential_drs_preprocessing.py +59 -0
  33. maltorch-0.1/src/maltorch/datasets/__init__.py +0 -0
  34. maltorch-0.1/src/maltorch/datasets/binary_dataset.py +75 -0
  35. maltorch-0.1/src/maltorch/datasets/drs_dataset.py +65 -0
  36. maltorch-0.1/src/maltorch/datasets/dynamic_drs_dataset.py +92 -0
  37. maltorch-0.1/src/maltorch/datasets/grayscale_dataset.py +80 -0
  38. maltorch-0.1/src/maltorch/datasets/random_chunk_sampler.py +33 -0
  39. maltorch-0.1/src/maltorch/datasets/random_drs_dataset.py +62 -0
  40. maltorch-0.1/src/maltorch/datasets/rs_dataset.py +69 -0
  41. maltorch-0.1/src/maltorch/datasets/rsdel_dataset.py +65 -0
  42. maltorch-0.1/src/maltorch/datasets/sequential_drs_dataset.py +69 -0
  43. maltorch-0.1/src/maltorch/initializers/__init__.py +0 -0
  44. maltorch-0.1/src/maltorch/initializers/content_shift_initializer.py +27 -0
  45. maltorch-0.1/src/maltorch/initializers/initializers.py +40 -0
  46. maltorch-0.1/src/maltorch/initializers/padding_initializer.py +27 -0
  47. maltorch-0.1/src/maltorch/initializers/partial_dos_initializer.py +17 -0
  48. maltorch-0.1/src/maltorch/initializers/section_injection_initializer.py +35 -0
  49. maltorch-0.1/src/maltorch/manipulations/__init__.py +0 -0
  50. maltorch-0.1/src/maltorch/manipulations/byte_manipulation.py +22 -0
  51. maltorch-0.1/src/maltorch/manipulations/gamma_section_injection_manipulation.py +63 -0
  52. maltorch-0.1/src/maltorch/manipulations/replacement_manipulation.py +32 -0
  53. maltorch-0.1/src/maltorch/optim/__init__.py +0 -0
  54. maltorch-0.1/src/maltorch/optim/base.py +39 -0
  55. maltorch-0.1/src/maltorch/optim/bgd.py +118 -0
  56. maltorch-0.1/src/maltorch/optim/byte_gradient_processing.py +9 -0
  57. maltorch-0.1/src/maltorch/optim/optimizer_factory.py +34 -0
  58. maltorch-0.1/src/maltorch/trainers/__init__.py +0 -0
  59. maltorch-0.1/src/maltorch/trainers/early_stopping_pytorch_trainer.py +158 -0
  60. maltorch-0.1/src/maltorch/trainers/weighted_bce_pytorch_trainer.py +164 -0
  61. maltorch-0.1/src/maltorch/utils/__init__.py +0 -0
  62. maltorch-0.1/src/maltorch/utils/config.py +5 -0
  63. maltorch-0.1/src/maltorch/utils/drs_certification.py +71 -0
  64. maltorch-0.1/src/maltorch/utils/embedding.py +74 -0
  65. maltorch-0.1/src/maltorch/utils/pe_operations.py +232 -0
  66. maltorch-0.1/src/maltorch/utils/strings.py +4 -0
  67. maltorch-0.1/src/maltorch/utils/utils.py +49 -0
  68. maltorch-0.1/src/maltorch/zoo/__init__.py +0 -0
  69. maltorch-0.1/src/maltorch/zoo/avaststyleconv.py +111 -0
  70. maltorch-0.1/src/maltorch/zoo/bbdnn.py +152 -0
  71. maltorch-0.1/src/maltorch/zoo/ember_gbdt.py +70 -0
  72. maltorch-0.1/src/maltorch/zoo/malconv.py +79 -0
  73. maltorch-0.1/src/maltorch/zoo/model.py +185 -0
  74. maltorch-0.1/src/maltorch/zoo/nebula.py +351 -0
  75. maltorch-0.1/src/maltorch/zoo/ngramconv.py +81 -0
  76. maltorch-0.1/src/maltorch/zoo/quovadis.py +278 -0
  77. maltorch-0.1/src/maltorch/zoo/resnet18.py +17 -0
  78. maltorch-0.1/src/maltorch/zoo/shallowconv.py +121 -0
  79. maltorch-0.1/src/maltorch.egg-info/PKG-INFO +44 -0
  80. maltorch-0.1/src/maltorch.egg-info/SOURCES.txt +81 -0
  81. maltorch-0.1/src/maltorch.egg-info/dependency_links.txt +1 -0
  82. maltorch-0.1/src/maltorch.egg-info/requires.txt +7 -0
  83. maltorch-0.1/src/maltorch.egg-info/top_level.txt +1 -0
maltorch-0.1/PKG-INFO ADDED
@@ -0,0 +1,44 @@
1
+ Metadata-Version: 2.4
2
+ Name: maltorch
3
+ Version: 0.1
4
+ Summary: Pytorch-based library for creating Adversarial EXEmples against Windows Malware detectors.
5
+ Home-page:
6
+ Author: Luca Demetrio, Daniel Gibert, Andrea Ponte, Maura Pintor
7
+ Author-email: luca.demetrio@unige.it
8
+ License: MIT
9
+ Classifier: Development Status :: 3 - Alpha
10
+ Classifier: Intended Audience :: Science/Research
11
+ Classifier: Intended Audience :: Developers
12
+ Classifier: License :: OSI Approved
13
+ Classifier: Programming Language :: Python
14
+ Classifier: Programming Language :: Python :: 3
15
+ Classifier: Programming Language :: Python :: 3.8
16
+ Classifier: Programming Language :: Python :: 3.9
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: Implementation :: PyPy
19
+ Classifier: Topic :: Software Development
20
+ Classifier: Topic :: Scientific/Engineering
21
+ Description-Content-Type: text/markdown
22
+ Requires-Dist: torch
23
+ Requires-Dist: torchvision
24
+ Requires-Dist: secml-torch
25
+ Requires-Dist: lightgbm==3.3.5
26
+ Requires-Dist: lief
27
+ Requires-Dist: nevergrad
28
+ Requires-Dist: joblib>=1.3.2
29
+ Dynamic: author
30
+ Dynamic: author-email
31
+ Dynamic: classifier
32
+ Dynamic: description
33
+ Dynamic: description-content-type
34
+ Dynamic: license
35
+ Dynamic: requires-dist
36
+ Dynamic: summary
37
+
38
+ # Maltorch: Pentesting of AI-based Windows Malware Detectors
39
+
40
+ ## Installation
41
+ ```bash
42
+ pip install maltoch
43
+ pip install git+https://github.com/zangobot/ember.git
44
+ ```
maltorch-0.1/README.md ADDED
@@ -0,0 +1,7 @@
1
+ # Maltorch: Pentesting of AI-based Windows Malware Detectors
2
+
3
+ ## Installation
4
+ ```bash
5
+ pip install maltoch
6
+ pip install git+https://github.com/zangobot/ember.git
7
+ ```
maltorch-0.1/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
maltorch-0.1/setup.py ADDED
@@ -0,0 +1,63 @@
1
+ import pathlib
2
+
3
+ from setuptools import find_packages, setup
4
+
5
+ here = pathlib.Path.cwd()
6
+ readme_path = here / "README.md"
7
+ version_path = here / "src" / "maltorch" / "VERSION"
8
+
9
+ CLASSIFIERS = """\
10
+ Development Status :: 3 - Alpha
11
+ Intended Audience :: Science/Research
12
+ Intended Audience :: Developers
13
+ License :: OSI Approved
14
+ Programming Language :: Python
15
+ Programming Language :: Python :: 3
16
+ Programming Language :: Python :: 3.8
17
+ Programming Language :: Python :: 3.9
18
+ Programming Language :: Python :: 3.10
19
+ Programming Language :: Python :: Implementation :: PyPy
20
+ Topic :: Software Development
21
+ Topic :: Scientific/Engineering
22
+ """
23
+
24
+ # Get the long description from the README file
25
+ with readme_path.open() as f:
26
+ long_description = f.read()
27
+
28
+ # Get the version from VERSION file
29
+ with version_path.open() as f:
30
+ version = f.read()
31
+
32
+ setup(
33
+ name='maltorch',
34
+ version=version,
35
+ packages=find_packages(
36
+ where="src",
37
+ exclude=[
38
+ "*.tests",
39
+ "*.tests.*",
40
+ "tests.*",
41
+ "tests",
42
+ ],
43
+ ),
44
+ package_dir={'': 'src'},
45
+ classifiers=[_f for _f in CLASSIFIERS.split("\n") if _f],
46
+ data_files=[("src/maltorch/VERSION", ["src/maltorch/VERSION"])],
47
+ url='',
48
+ license='MIT',
49
+ author='Luca Demetrio, Daniel Gibert, Andrea Ponte, Maura Pintor',
50
+ author_email='luca.demetrio@unige.it',
51
+ description='Pytorch-based library for creating Adversarial EXEmples against Windows Malware detectors.',
52
+ long_description=long_description,
53
+ long_description_content_type="text/markdown",
54
+ install_requires=[
55
+ 'torch',
56
+ 'torchvision',
57
+ 'secml-torch',
58
+ 'lightgbm==3.3.5',
59
+ 'lief',
60
+ 'nevergrad',
61
+ 'joblib>=1.3.2'
62
+ ],
63
+ )
@@ -0,0 +1 @@
1
+ 0.1
File without changes
File without changes
@@ -0,0 +1,122 @@
1
+ from typing import Union, List, Callable
2
+
3
+ import torch
4
+ from secmlt.adv.evasion.base_evasion_attack import BaseEvasionAttack
5
+ from secmlt.models.base_model import BaseModel
6
+ from secmlt.optimization.initializer import Initializer
7
+ from secmlt.trackers import Tracker
8
+
9
+ from maltorch.manipulations.byte_manipulation import ByteManipulation
10
+
11
+
12
+ class BackendAttack(BaseEvasionAttack):
13
+ @classmethod
14
+ def _trackers_allowed(cls):
15
+ return True
16
+
17
+ @staticmethod
18
+ def get_perturbation_models():
19
+ pass
20
+
21
+ def __init__(
22
+ self,
23
+ y_target: Union[int, None],
24
+ query_budget: int,
25
+ loss_function: Union[str, torch.nn.Module],
26
+ optimizer_cls: Callable,
27
+ manipulation_function: ByteManipulation,
28
+ initializer: Initializer,
29
+ trackers: Union[List[Tracker], Tracker] = None,
30
+ **kwargs
31
+ ):
32
+ self.y_target = y_target
33
+ self.query_budget = query_budget
34
+ self.loss_function = loss_function
35
+ self.manipulation_function = manipulation_function
36
+ self.initializer = initializer
37
+ self.trackers = trackers
38
+ self.optimizer = None
39
+ self.optimizer_cls = optimizer_cls
40
+ self._best_loss = None
41
+ self._best_delta = None
42
+
43
+ def _init_attack_manipulation(
44
+ self, samples: torch.Tensor
45
+ ) -> (torch.Tensor, torch.Tensor):
46
+ return self.manipulation_function.initialize(samples.data)
47
+
48
+ def _apply_manipulation(
49
+ self, x: torch.Tensor, delta: torch.Tensor
50
+ ) -> (torch.Tensor, torch.Tensor):
51
+ raise NotImplementedError()
52
+
53
+ def _optimizer_step(self, delta: torch.Tensor, loss: torch.Tensor) -> torch.Tensor:
54
+ raise NotImplementedError()
55
+
56
+ def _init_optimizer(self, model: BaseModel, delta: torch.Tensor) -> Callable:
57
+ raise NotImplementedError()
58
+
59
+ def _consumed_budget(self):
60
+ raise NotImplementedError()
61
+
62
+ def _init_best_tracking(self, delta: torch.Tensor):
63
+ self._best_delta = torch.zeros_like(delta.detach().cpu())
64
+ self._best_loss = torch.zeros((delta.shape[0], 1)).fill_(torch.inf)
65
+
66
+ def _track_best(self, loss: torch.Tensor, delta: torch.Tensor):
67
+ where_best = (loss < self._best_loss).squeeze(1)
68
+ self._best_delta[where_best] = delta[where_best]
69
+ self._best_loss[where_best] = loss[where_best]
70
+
71
+ def _get_best_delta(self):
72
+ return self._best_delta
73
+
74
+ def _track(
75
+ self,
76
+ iteration: int,
77
+ loss: torch.Tensor,
78
+ scores: torch.Tensor,
79
+ x_adv: torch.Tensor,
80
+ delta: torch.Tensor,
81
+ ):
82
+ if self._trackers_allowed():
83
+ if self.trackers:
84
+ for tracker in self.trackers:
85
+ tracker.track(
86
+ iteration=iteration,
87
+ loss=loss.data,
88
+ scores=scores.data,
89
+ x_adv=x_adv.data,
90
+ delta=delta,
91
+ grad=None,
92
+ )
93
+
94
+ def _run(
95
+ self,
96
+ model: BaseModel,
97
+ samples: torch.Tensor,
98
+ labels: torch.Tensor,
99
+ **optim_kwargs,
100
+ ) -> (torch.Tensor, torch.Tensor):
101
+ multiplier = 1 if self.y_target is not None else -1
102
+ target = (
103
+ torch.zeros_like(labels) + self.y_target
104
+ if self.y_target is not None
105
+ else labels
106
+ ).type(labels.dtype)
107
+ target = target.to(labels.device)
108
+ x_adv, delta = self._init_attack_manipulation(samples)
109
+ self.optimizer = self._init_optimizer(model, delta)
110
+ budget = 0
111
+ self._init_best_tracking(delta)
112
+ while budget < self.query_budget:
113
+ x_adv, _ = self._apply_manipulation(samples, delta)
114
+ scores = model.decision_function(x_adv)
115
+ loss = self.loss_function(scores, target) * multiplier
116
+ delta = self._optimizer_step(delta, loss)
117
+ budget += self._consumed_budget()
118
+ self._track(budget, loss, scores, x_adv, delta)
119
+ self._track_best(loss, delta)
120
+ best_delta = self._get_best_delta()
121
+ best_x, _ = self._apply_manipulation(samples, best_delta)
122
+ return best_x, self._best_delta
@@ -0,0 +1,114 @@
1
+ import importlib
2
+ from abc import abstractmethod
3
+ from typing import Type
4
+
5
+ from maltorch.adv.evasion.backend_attack import BackendAttack
6
+
7
+
8
+ class OptimizerBackends:
9
+ """Available backends."""
10
+
11
+ NG = "nevergrad"
12
+ GRADIENT = "gradient"
13
+
14
+
15
+ class BaseOptimAttackCreator:
16
+ """Generic creator for attacks."""
17
+
18
+ @classmethod
19
+ def get_implementation(cls, backend: str) -> Type[BackendAttack]:
20
+ """
21
+ Get the implementation of the attack with the given backend.
22
+
23
+ Parameters
24
+ ----------
25
+ backend : str
26
+ The backend for the attack. See secmlt.adv.backends for
27
+ available backends.
28
+
29
+ Returns
30
+ -------
31
+ BaseEvasionAttack
32
+ Attack implementation.
33
+ """
34
+ implementations = {
35
+ OptimizerBackends.NG: cls.get_nevergrad_implementation,
36
+ OptimizerBackends.GRADIENT: cls._get_native_implementation,
37
+ }
38
+ cls.check_backend_available(backend)
39
+ return implementations[backend]()
40
+
41
+ @classmethod
42
+ def check_backend_available(cls, backend: str) -> bool:
43
+ """
44
+ Check if a given backend is available for the attack.
45
+
46
+ Parameters
47
+ ----------
48
+ backend : str
49
+ Backend string.
50
+
51
+ Returns
52
+ -------
53
+ bool
54
+ True if the given backend is implemented.
55
+
56
+ Raises
57
+ ------
58
+ NotImplementedError
59
+ Raises NotImplementedError if the requested backend is not in
60
+ the list of the possible backends (check secmlt.adv.backends).
61
+ """
62
+ if backend in cls.get_backends():
63
+ return True
64
+ msg = "Unsupported or not-implemented backend."
65
+ raise NotImplementedError(msg)
66
+
67
+ @classmethod
68
+ def get_nevergrad_implementation(cls) -> BackendAttack:
69
+ """
70
+ Get the Nevergrad implementation of the attack.
71
+
72
+ Returns
73
+ -------
74
+ BaseEvasionAttack
75
+ Nevergrad implementation of the attack.
76
+
77
+ Raises
78
+ ------
79
+ ImportError
80
+ Raises ImportError if Nevergrad extra is not installed.
81
+ """
82
+ if importlib.util.find_spec("nevergrad", None) is not None:
83
+ return cls._get_nevergrad_implementation()
84
+ msg = "Nevergrad extra not installed."
85
+ raise ImportError(msg)
86
+
87
+ @staticmethod
88
+ def _get_nevergrad_implementation() -> BackendAttack:
89
+ msg = "Nevergrad implementation not available."
90
+ raise NotImplementedError(msg)
91
+
92
+ @staticmethod
93
+ def _get_native_implementation() -> BackendAttack:
94
+ msg = "Native implementation not available."
95
+ raise NotImplementedError(msg)
96
+
97
+ @staticmethod
98
+ @abstractmethod
99
+ def get_backends() -> set[str]:
100
+ """
101
+ Get the available backends for the given attack.
102
+
103
+ Returns
104
+ -------
105
+ set[str]
106
+ Set of implemented backends available for the attack.
107
+
108
+ Raises
109
+ ------
110
+ NotImplementedError
111
+ Raises NotImplementedError if not implemented in the inherited class.
112
+ """
113
+ msg = "Backends should be specified in inherited class."
114
+ raise NotImplementedError(msg)
@@ -0,0 +1,121 @@
1
+ from typing import Type, Union, List, Callable
2
+
3
+ from secmlt.trackers import Tracker
4
+ from torch.nn import BCEWithLogitsLoss
5
+
6
+ from maltorch.adv.evasion.base_optim_attack_creator import (
7
+ BaseOptimAttackCreator,
8
+ OptimizerBackends,
9
+ )
10
+ from maltorch.adv.evasion.gradfree_attack import GradientFreeBackendAttack
11
+ from maltorch.adv.evasion.gradient_attack import GradientBackendAttack
12
+ from maltorch.initializers.content_shift_initializer import ContentShiftInitializer
13
+ from maltorch.manipulations.replacement_manipulation import ReplacementManipulation
14
+ from maltorch.optim.optimizer_factory import MalwareOptimizerFactory
15
+
16
+
17
+ class ContentShiftGradFree(GradientFreeBackendAttack):
18
+ def __init__(
19
+ self,
20
+ query_budget: int,
21
+ manipulation_size: int,
22
+ y_target: Union[int, None] = None,
23
+ population_size: int = 10,
24
+ random_init: bool = False,
25
+ trackers: Union[List[Tracker], Tracker] = None,
26
+ ):
27
+ initializer = ContentShiftInitializer(
28
+ random_init=random_init, preferred_manipulation_size=manipulation_size
29
+ )
30
+ optimizer_cls = MalwareOptimizerFactory.create_ga(
31
+ population_size=population_size
32
+ )
33
+ loss_function = BCEWithLogitsLoss(reduction="none")
34
+ manipulation_function = ReplacementManipulation(initializer=initializer)
35
+ super().__init__(
36
+ y_target=y_target,
37
+ query_budget=query_budget,
38
+ loss_function=loss_function,
39
+ initializer=initializer,
40
+ manipulation_function=manipulation_function,
41
+ optimizer_cls=optimizer_cls,
42
+ trackers=trackers,
43
+ )
44
+
45
+
46
+ class ContentShiftGrad(GradientBackendAttack):
47
+ def __init__(
48
+ self,
49
+ query_budget: int,
50
+ manipulation_size: int,
51
+ y_target: Union[int, None] = None,
52
+ random_init: bool = False,
53
+ step_size: int = 58,
54
+ device: str = "cpu",
55
+ trackers: Union[List[Tracker], Tracker] = None,
56
+ ):
57
+ initializer = ContentShiftInitializer(
58
+ random_init=random_init, preferred_manipulation_size=manipulation_size
59
+ )
60
+ optimizer_cls = MalwareOptimizerFactory.create_bgd(lr=step_size, device=device)
61
+ loss_function = BCEWithLogitsLoss(reduction="none")
62
+ manipulation_function = ReplacementManipulation(initializer=initializer)
63
+ super().__init__(
64
+ y_target=y_target,
65
+ query_budget=query_budget,
66
+ loss_function=loss_function,
67
+ optimizer_cls=optimizer_cls,
68
+ manipulation_function=manipulation_function,
69
+ initializer=initializer,
70
+ trackers=trackers,
71
+ )
72
+
73
+
74
+ class ContentShift(BaseOptimAttackCreator):
75
+ """
76
+ Content Shift attack
77
+
78
+ Demetrio, L., Coull, S. E., Biggio, B., Lagorio, G., Armando, A., & Roli, F. (2021).
79
+ Adversarial EXEmples: A survey and experimental evaluation of practical attacks on machine learning for windows malware detection.
80
+ ACM Transactions on Privacy and Security (TOPS), 24(4), 1-31.
81
+ """
82
+
83
+ @staticmethod
84
+ def get_backends() -> set[str]:
85
+ return {OptimizerBackends.GRADIENT, OptimizerBackends.NG}
86
+
87
+ @staticmethod
88
+ def _get_nevergrad_implementation() -> Type[ContentShiftGradFree]:
89
+ return ContentShiftGradFree
90
+
91
+ @staticmethod
92
+ def _get_native_implementation() -> Type[ContentShiftGrad]:
93
+ return ContentShiftGrad
94
+
95
+ def __new__(
96
+ cls,
97
+ query_budget: int,
98
+ y_target: Union[int, None] = None,
99
+ perturbation_size: int = 512,
100
+ random_init: bool = False,
101
+ step_size: int = 16,
102
+ population_size: int = 10,
103
+ device: str = "cpu",
104
+ trackers: Union[List[Tracker], Tracker] = None,
105
+ backend: str = OptimizerBackends.GRADIENT,
106
+ ) -> Callable:
107
+ implementation: Callable = cls.get_implementation(backend)
108
+ if backend == OptimizerBackends.GRADIENT:
109
+ kwargs = {"step_size": step_size, "device": device}
110
+ else:
111
+ kwargs = {
112
+ "population_size": population_size,
113
+ }
114
+ return implementation(
115
+ query_budget=query_budget,
116
+ perturbation_size=perturbation_size,
117
+ y_target=y_target,
118
+ trackers=trackers,
119
+ random_init=random_init,
120
+ **kwargs,
121
+ )
@@ -0,0 +1,94 @@
1
+ from pathlib import Path
2
+ from typing import Type, Union, List, Callable
3
+
4
+ from secmlt.trackers import Tracker
5
+ from torch.nn import BCEWithLogitsLoss
6
+
7
+ from maltorch.adv.evasion.base_optim_attack_creator import (
8
+ BaseOptimAttackCreator,
9
+ OptimizerBackends,
10
+ )
11
+ from maltorch.adv.evasion.gradfree_attack import GradientFreeBackendAttack
12
+ from maltorch.initializers.initializers import IdentityInitializer
13
+ from maltorch.manipulations.gamma_section_injection_manipulation import GAMMASectionInjectionManipulation
14
+ from maltorch.optim.optimizer_factory import MalwareOptimizerFactory
15
+
16
+
17
+ class GAMMASectionInjectionGradFree(GradientFreeBackendAttack):
18
+ def __init__(
19
+ self,
20
+ query_budget: int,
21
+ benignware_folder: Path,
22
+ how_many_sections: int,
23
+ which_sections: list = None,
24
+ y_target: Union[int, None] = None,
25
+ population_size: int = 10,
26
+ random_init: bool = False,
27
+ trackers: Union[List[Tracker], Tracker] = None,
28
+ ):
29
+ if which_sections is None:
30
+ which_sections = ['rodata']
31
+ initializer = IdentityInitializer(
32
+ random_init=random_init
33
+ )
34
+ optimizer_cls = MalwareOptimizerFactory.create_ga(
35
+ population_size=population_size
36
+ )
37
+ loss_function = BCEWithLogitsLoss(reduction="none")
38
+ manipulation_function = GAMMASectionInjectionManipulation(benignware_folder=benignware_folder,
39
+ which_sections=which_sections,
40
+ how_many_sections=how_many_sections)
41
+ super().__init__(
42
+ y_target=y_target,
43
+ query_budget=query_budget,
44
+ loss_function=loss_function,
45
+ initializer=initializer,
46
+ manipulation_function=manipulation_function,
47
+ optimizer_cls=optimizer_cls,
48
+ trackers=trackers,
49
+ )
50
+
51
+
52
+ class GAMMASectionInjection(BaseOptimAttackCreator):
53
+ """
54
+ GAMMA Section Injection attack
55
+
56
+ Demetrio, L., Biggio, B., Lagorio, G., Roli, F., & Armando, A. (2021).
57
+ Functionality-preserving black-box optimization of adversarial windows malware.
58
+ IEEE Transactions on Information Forensics and Security, 16, 3469-3478.
59
+ """
60
+
61
+ @staticmethod
62
+ def get_backends() -> set[str]:
63
+ return {OptimizerBackends.NG}
64
+
65
+ @staticmethod
66
+ def _get_nevergrad_implementation() -> Type[GAMMASectionInjectionGradFree]:
67
+ return GAMMASectionInjectionGradFree
68
+
69
+ def __new__(
70
+ cls,
71
+ query_budget: int,
72
+ benignware_folder: Path,
73
+ which_sections: list = None,
74
+ y_target: Union[int, None] = None,
75
+ how_many_sections: int = 75,
76
+ random_init: bool = False,
77
+ step_size: int = 16,
78
+ population_size: int = 10,
79
+ device: str = "cpu",
80
+ trackers: Union[List[Tracker], Tracker] = None,
81
+ backend: str = OptimizerBackends.NG,
82
+ ) -> Callable:
83
+ if which_sections is None:
84
+ which_sections = ['rodata']
85
+ return GAMMASectionInjectionGradFree(
86
+ query_budget=query_budget,
87
+ benignware_folder=benignware_folder,
88
+ how_many_sections=how_many_sections,
89
+ which_sections=which_sections,
90
+ population_size=population_size,
91
+ y_target=y_target,
92
+ trackers=trackers,
93
+ random_init=random_init,
94
+ )
@@ -0,0 +1,70 @@
1
+ import nevergrad
2
+ import torch
3
+ from nevergrad.optimization import Optimizer
4
+ from secmlt.models.base_model import BaseModel
5
+ from torch.utils.data import DataLoader, TensorDataset
6
+
7
+ from maltorch.adv.evasion.backend_attack import BackendAttack
8
+
9
+
10
+ class GradientFreeBackendAttack(BackendAttack):
11
+ def _optimizer_step(
12
+ self, delta: nevergrad.p.Array, loss: torch.Tensor
13
+ ) -> nevergrad.p.Array:
14
+ self.optimizer.tell(delta, loss.item())
15
+ delta = self.optimizer.ask()
16
+ return delta
17
+
18
+ def _apply_manipulation(
19
+ self, x: torch.Tensor, delta: nevergrad.p.Array
20
+ ) -> (torch.Tensor, torch.Tensor):
21
+ p_delta = torch.from_numpy(delta.value)
22
+ return self.manipulation_function(x.data, p_delta)
23
+
24
+ def _consumed_budget(self):
25
+ return 1
26
+
27
+ def _init_attack_manipulation(
28
+ self, samples: torch.Tensor
29
+ ) -> (torch.Tensor, nevergrad.p.Array):
30
+ x_adv, delta = super()._init_attack_manipulation(samples)
31
+ optim_delta = nevergrad.p.Array(shape=delta.shape, lower=0.0, upper=255.0)
32
+ optim_delta.value = delta.numpy()
33
+ return x_adv, optim_delta
34
+
35
+ def _init_optimizer(self, model: BaseModel, delta: nevergrad.p.Array) -> Optimizer:
36
+ self.optimizer = self.optimizer_cls(
37
+ parametrization=nevergrad.p.Array(
38
+ shape=delta.value.shape, lower=0.0, upper=255.0
39
+ )
40
+ )
41
+ return self.optimizer
42
+
43
+ def __call__(self, model: BaseModel, data_loader: DataLoader) -> DataLoader:
44
+ adversarials = []
45
+ original_labels = []
46
+ for samples, labels in data_loader:
47
+ for sample, label in zip(samples, labels):
48
+ sample = sample.unsqueeze(0)
49
+ label = label.unsqueeze(0)
50
+ x_adv, _ = self._run(model, sample, label)
51
+ adversarials.append(x_adv)
52
+ original_labels.append(label)
53
+ adversarials = (
54
+ torch.nn.utils.rnn.pad_sequence(adversarials, padding_value=256)
55
+ .squeeze()
56
+ .long()
57
+ )
58
+ original_labels = torch.vstack(original_labels)
59
+ adversarial_dataset = TensorDataset(adversarials, original_labels)
60
+ return DataLoader(
61
+ adversarial_dataset,
62
+ batch_size=data_loader.batch_size,
63
+ )
64
+
65
+ def _init_best_tracking(self, delta: torch.Tensor): ...
66
+
67
+ def _track_best(self, loss: torch.Tensor, delta: torch.Tensor): ...
68
+
69
+ def _get_best_delta(self):
70
+ return self.optimizer.provide_recommendation()
@@ -0,0 +1,39 @@
1
+ import torch
2
+ from secmlt.models.base_model import BaseModel
3
+
4
+ from maltorch.adv.evasion.backend_attack import BackendAttack
5
+ from maltorch.optim.base import BaseByteOptimizer
6
+
7
+
8
+ class GradientBackendAttack(BackendAttack):
9
+ def _init_attack_manipulation(
10
+ self, samples: torch.Tensor
11
+ ) -> (torch.Tensor, torch.Tensor):
12
+ x_adv, delta = self.manipulation_function.initialize(samples.data)
13
+ delta = delta.to(samples.device)
14
+ delta.requires_grad = True
15
+ return x_adv, delta
16
+
17
+ def _apply_manipulation(
18
+ self, x: torch.Tensor, delta: torch.Tensor
19
+ ) -> (torch.Tensor, torch.Tensor):
20
+ x.data, delta.data = self.manipulation_function(x.data, delta.data)
21
+ return x, delta
22
+
23
+ def _init_optimizer(
24
+ self, model: BaseModel, delta: torch.Tensor
25
+ ) -> BaseByteOptimizer:
26
+ self.optimizer = self.optimizer_cls(
27
+ [delta],
28
+ indexes_to_perturb=self.manipulation_function.indexes_to_perturb,
29
+ model=model,
30
+ )
31
+ return self.optimizer
32
+
33
+ def _optimizer_step(self, delta: torch.Tensor, loss: torch.Tensor) -> torch.Tensor:
34
+ loss.sum().backward()
35
+ self.optimizer.step()
36
+ return delta
37
+
38
+ def _consumed_budget(self):
39
+ return 2