Agent: Mark monkey agent for deletion on reboot

Each windows agent which will be runned, we are going to
to mark it for deletion on boot and also try it to delete it using
delayed command.
This commit is contained in:
Ilija Lazoroski 2022-05-11 16:14:48 +02:00
parent 8fe9b32366
commit d9046b39a8
7 changed files with 76 additions and 59 deletions

View File

@ -12,8 +12,8 @@ class ScanStatus(Enum):
class UsageEnum(Enum):
SMB = {
ScanStatus.USED.value: "SMB exploiter ran the monkey by creating a service via MS-SCMR.",
ScanStatus.SCANNED.value: "SMB exploiter failed to run the monkey by creating a service "
ScanStatus.USED.value: "SMB exploiter ran the agent by creating a service via MS-SCMR.",
ScanStatus.SCANNED.value: "SMB exploiter failed to run the agent by creating a service "
"via MS-SCMR.",
}
MIMIKATZ = {
@ -24,19 +24,19 @@ class UsageEnum(Enum):
ScanStatus.USED.value: "WinAPI was called to load mimikatz.",
ScanStatus.SCANNED.value: "Monkey tried to call WinAPI to load mimikatz.",
}
DROPPER = {
ScanStatus.USED.value: "WinAPI was used to mark monkey files for deletion on next boot."
AGENT_WINAPI = {
ScanStatus.USED.value: "WinAPI was used to mark agent's files for deletion on next boot."
}
SINGLETON_WINAPI = {
ScanStatus.USED.value: "WinAPI was called to acquire system singleton for monkey's "
ScanStatus.USED.value: "WinAPI was called to acquire system singleton for agent's "
"process.",
ScanStatus.SCANNED.value: "WinAPI call to acquire system singleton"
" for monkey process wasn't successful.",
" for agent's process wasn't successful.",
}
DROPPER_WINAPI = {
ScanStatus.USED.value: "WinAPI was used to mark monkey files for deletion on next boot."
ScanStatus.USED.value: "WinAPI was used to mark dropper files for deletion on next boot."
}
# Dict that describes what BITS job was used for
BITS_UPLOAD_STRING = "BITS job was used to upload monkey to a remote system."
BITS_UPLOAD_STRING = "BITS job was used to upload agent to a remote system."

View File

@ -1,5 +1,4 @@
import argparse
import ctypes
import filecmp
import logging
import os
@ -8,17 +7,17 @@ import shutil
import subprocess
import sys
import time
from ctypes import c_char_p
from pathlib import WindowsPath
from common.utils.attack_utils import ScanStatus, UsageEnum
from common.utils.attack_utils import UsageEnum
from infection_monkey.config import WormConfiguration
from infection_monkey.telemetry.attack.t1106_telem import T1106Telem
from infection_monkey.utils.commands import (
build_monkey_commandline_explicitly,
get_monkey_commandline_linux,
get_monkey_commandline_windows,
)
from infection_monkey.utils.environment import is_windows_os
from infection_monkey.utils.file_utils import mark_file_for_deletion_on_windows
if "win32" == sys.platform:
from win32process import DETACHED_PROCESS
@ -198,23 +197,9 @@ class MonkeyDrops(object):
)
# mark the file for removal on next boot
dropper_source_path_ctypes = c_char_p(self._config["source_path"].encode())
if 0 == ctypes.windll.kernel32.MoveFileExA(
dropper_source_path_ctypes, None, MOVEFILE_DELAY_UNTIL_REBOOT
):
logger.debug(
"Error marking source file '%s' for deletion on next boot (error "
"%d)",
self._config["source_path"],
ctypes.windll.kernel32.GetLastError(),
)
else:
logger.debug(
"Dropper source file '%s' is marked for deletion on next boot",
self._config["source_path"],
)
T1106Telem(ScanStatus.USED, UsageEnum.DROPPER_WINAPI).send()
mark_file_for_deletion_on_windows(
WindowsPath(self._config["source_path"]), UsageEnum.DROPPER_WINAPI
)
logger.info("Dropper cleanup complete")
except AttributeError:
logger.error("Invalid configuration options. Failing")

View File

@ -3,7 +3,7 @@ import logging
import os
import subprocess
import sys
from pathlib import Path
from pathlib import Path, WindowsPath
from typing import List
import infection_monkey.tunnel as tunnel
@ -70,6 +70,7 @@ from infection_monkey.telemetry.state_telem import StateTelem
from infection_monkey.telemetry.tunnel_telem import TunnelTelem
from infection_monkey.utils.aws_environment_check import run_aws_environment_check
from infection_monkey.utils.environment import is_windows_os
from infection_monkey.utils.file_utils import mark_file_for_deletion_on_windows
from infection_monkey.utils.monkey_dir import (
create_monkey_dir,
get_monkey_dir_path,
@ -410,6 +411,9 @@ class InfectionMonkey:
try:
if "win32" == sys.platform:
mark_file_for_deletion_on_windows(
WindowsPath(sys.executable), UsageEnum.AGENT_WINAPI
)
InfectionMonkey._self_delete_windows()
else:
InfectionMonkey._self_delete_linux()

View File

@ -3,7 +3,7 @@ from pathlib import Path
from typing import Iterable, Set
from common.utils.file_utils import get_all_regular_files_in_directory
from infection_monkey.utils.dir_utils import (
from infection_monkey.utils.file_utils import (
file_extension_filter,
filter_files,
is_not_shortcut_filter,

View File

@ -1,27 +0,0 @@
from pathlib import Path
from typing import Callable, Iterable, Set
def filter_files(
files: Iterable[Path], file_filters: Iterable[Callable[[Path], bool]]
) -> Iterable[Path]:
filtered_files = files
for file_filter in file_filters:
filtered_files = filter(file_filter, filtered_files)
return filtered_files
def file_extension_filter(file_extensions: Set) -> Callable[[Path], bool]:
def inner_filter(f: Path) -> bool:
return f.suffix in file_extensions
return inner_filter
def is_not_symlink_filter(f: Path) -> bool:
return not f.is_symlink()
def is_not_shortcut_filter(f: Path) -> bool:
return f.suffix != ".lnk"

View File

@ -0,0 +1,55 @@
import ctypes
import logging
from pathlib import Path, WindowsPath
from typing import Callable, Iterable, Set
from common.utils.attack_utils import ScanStatus, UsageEnum
logger = logging.getLogger(__name__)
MOVEFILE_DELAY_UNTIL_REBOOT = 4
def filter_files(
files: Iterable[Path], file_filters: Iterable[Callable[[Path], bool]]
) -> Iterable[Path]:
filtered_files = files
for file_filter in file_filters:
filtered_files = filter(file_filter, filtered_files)
return filtered_files
def file_extension_filter(file_extensions: Set) -> Callable[[Path], bool]:
def inner_filter(f: Path) -> bool:
return f.suffix in file_extensions
return inner_filter
def is_not_symlink_filter(f: Path) -> bool:
return not f.is_symlink()
def is_not_shortcut_filter(f: Path) -> bool:
return f.suffix != ".lnk"
def mark_file_for_deletion_on_windows(file_path: WindowsPath, usage: UsageEnum):
from infection_monkey.telemetry.attack.t1106_telem import T1106Telem
file_source_path_ctypes = ctypes.c_char_p(str(file_path).encode())
mark_file_response = ctypes.windll.kernel32.MoveFileExA(
file_source_path_ctypes, None, MOVEFILE_DELAY_UNTIL_REBOOT
)
if mark_file_response == 0:
logger.debug(
f"Error marking file {file_path} for deletion on next boot:"
f"{ctypes.windll.kernel32.GetLastError()}"
)
return
logger.debug(f"File {file_path} is marked for deletion on next boot")
T1106Telem(ScanStatus.USED, usage).send()

View File

@ -4,7 +4,7 @@ import pytest
from tests.utils import add_files_to_dir, is_user_admin
from common.utils.file_utils import get_all_regular_files_in_directory
from infection_monkey.utils.dir_utils import (
from infection_monkey.utils.file_utils import (
file_extension_filter,
filter_files,
is_not_shortcut_filter,