forked from p15670423/monkey
Merge pull request #1938 from guardicore/1781-rework-windows-agent-deletion
Mark monkey agent for deletion on boot
This commit is contained in:
commit
e0cec77ec6
|
@ -12,8 +12,8 @@ class ScanStatus(Enum):
|
||||||
|
|
||||||
class UsageEnum(Enum):
|
class UsageEnum(Enum):
|
||||||
SMB = {
|
SMB = {
|
||||||
ScanStatus.USED.value: "SMB exploiter ran the monkey by creating a service via MS-SCMR.",
|
ScanStatus.USED.value: "SMB exploiter ran the agent by creating a service via MS-SCMR.",
|
||||||
ScanStatus.SCANNED.value: "SMB exploiter failed to run the monkey by creating a service "
|
ScanStatus.SCANNED.value: "SMB exploiter failed to run the agent by creating a service "
|
||||||
"via MS-SCMR.",
|
"via MS-SCMR.",
|
||||||
}
|
}
|
||||||
MIMIKATZ = {
|
MIMIKATZ = {
|
||||||
|
@ -24,19 +24,19 @@ class UsageEnum(Enum):
|
||||||
ScanStatus.USED.value: "WinAPI was called to load mimikatz.",
|
ScanStatus.USED.value: "WinAPI was called to load mimikatz.",
|
||||||
ScanStatus.SCANNED.value: "Monkey tried to call WinAPI to load mimikatz.",
|
ScanStatus.SCANNED.value: "Monkey tried to call WinAPI to load mimikatz.",
|
||||||
}
|
}
|
||||||
DROPPER = {
|
AGENT_WINAPI = {
|
||||||
ScanStatus.USED.value: "WinAPI was used to mark monkey files for deletion on next boot."
|
ScanStatus.USED.value: "WinAPI was used to mark agent's files for deletion on next boot."
|
||||||
}
|
}
|
||||||
SINGLETON_WINAPI = {
|
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.",
|
"process.",
|
||||||
ScanStatus.SCANNED.value: "WinAPI call to acquire system singleton"
|
ScanStatus.SCANNED.value: "WinAPI call to acquire system singleton"
|
||||||
" for monkey process wasn't successful.",
|
" for agent's process wasn't successful.",
|
||||||
}
|
}
|
||||||
DROPPER_WINAPI = {
|
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
|
# 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."
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import argparse
|
import argparse
|
||||||
import ctypes
|
|
||||||
import filecmp
|
import filecmp
|
||||||
import logging
|
import logging
|
||||||
import os
|
import os
|
||||||
|
@ -8,17 +7,17 @@ import shutil
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
import time
|
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.config import WormConfiguration
|
||||||
from infection_monkey.telemetry.attack.t1106_telem import T1106Telem
|
|
||||||
from infection_monkey.utils.commands import (
|
from infection_monkey.utils.commands import (
|
||||||
build_monkey_commandline_explicitly,
|
build_monkey_commandline_explicitly,
|
||||||
get_monkey_commandline_linux,
|
get_monkey_commandline_linux,
|
||||||
get_monkey_commandline_windows,
|
get_monkey_commandline_windows,
|
||||||
)
|
)
|
||||||
from infection_monkey.utils.environment import is_windows_os
|
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:
|
if "win32" == sys.platform:
|
||||||
from win32process import DETACHED_PROCESS
|
from win32process import DETACHED_PROCESS
|
||||||
|
@ -198,23 +197,9 @@ class MonkeyDrops(object):
|
||||||
)
|
)
|
||||||
|
|
||||||
# mark the file for removal on next boot
|
# mark the file for removal on next boot
|
||||||
dropper_source_path_ctypes = c_char_p(self._config["source_path"].encode())
|
mark_file_for_deletion_on_windows(
|
||||||
if 0 == ctypes.windll.kernel32.MoveFileExA(
|
WindowsPath(self._config["source_path"]), UsageEnum.DROPPER_WINAPI
|
||||||
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()
|
|
||||||
|
|
||||||
logger.info("Dropper cleanup complete")
|
logger.info("Dropper cleanup complete")
|
||||||
except AttributeError:
|
except AttributeError:
|
||||||
logger.error("Invalid configuration options. Failing")
|
logger.error("Invalid configuration options. Failing")
|
||||||
|
|
|
@ -3,7 +3,7 @@ import logging
|
||||||
import os
|
import os
|
||||||
import subprocess
|
import subprocess
|
||||||
import sys
|
import sys
|
||||||
from pathlib import Path
|
from pathlib import Path, WindowsPath
|
||||||
from typing import List
|
from typing import List
|
||||||
|
|
||||||
import infection_monkey.tunnel as tunnel
|
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.telemetry.tunnel_telem import TunnelTelem
|
||||||
from infection_monkey.utils.aws_environment_check import run_aws_environment_check
|
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.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 (
|
from infection_monkey.utils.monkey_dir import (
|
||||||
create_monkey_dir,
|
create_monkey_dir,
|
||||||
get_monkey_dir_path,
|
get_monkey_dir_path,
|
||||||
|
@ -410,6 +411,9 @@ class InfectionMonkey:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
if "win32" == sys.platform:
|
if "win32" == sys.platform:
|
||||||
|
mark_file_for_deletion_on_windows(
|
||||||
|
WindowsPath(sys.executable), UsageEnum.AGENT_WINAPI
|
||||||
|
)
|
||||||
InfectionMonkey._self_delete_windows()
|
InfectionMonkey._self_delete_windows()
|
||||||
else:
|
else:
|
||||||
InfectionMonkey._self_delete_linux()
|
InfectionMonkey._self_delete_linux()
|
||||||
|
|
|
@ -3,7 +3,7 @@ from pathlib import Path
|
||||||
from typing import Iterable, Set
|
from typing import Iterable, Set
|
||||||
|
|
||||||
from common.utils.file_utils import get_all_regular_files_in_directory
|
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,
|
file_extension_filter,
|
||||||
filter_files,
|
filter_files,
|
||||||
is_not_shortcut_filter,
|
is_not_shortcut_filter,
|
||||||
|
|
|
@ -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"
|
|
|
@ -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()
|
|
@ -4,7 +4,7 @@ import pytest
|
||||||
from tests.utils import add_files_to_dir, is_user_admin
|
from tests.utils import add_files_to_dir, is_user_admin
|
||||||
|
|
||||||
from common.utils.file_utils import get_all_regular_files_in_directory
|
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,
|
file_extension_filter,
|
||||||
filter_files,
|
filter_files,
|
||||||
is_not_shortcut_filter,
|
is_not_shortcut_filter,
|
Loading…
Reference in New Issue