Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into unblob-2
Browse files Browse the repository at this point in the history
  • Loading branch information
jstucke committed Jan 31, 2025
2 parents deff5d8 + 6833cdf commit cdcda4b
Show file tree
Hide file tree
Showing 137 changed files with 1,236 additions and 728 deletions.
30 changes: 21 additions & 9 deletions extract.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,15 +43,23 @@ def setup_logging(verbose):


def container_exists(container):
return subprocess.run(f'docker history {container}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).returncode == 0
return (
subprocess.run(
f'docker history {container}', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, check=False
).returncode
== 0
)


def default_container_status():
format_parameter = '{{.Tag}},{{.CreatedAt}}'
try:
process_result = subprocess.run(
f'docker image ls {DEFAULT_CONTAINER} --format "{format_parameter}"',
shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT
shell=True,
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT,
check=False,
)
tag, creation_time = process_result.stdout.decode().strip().split(',')
except ValueError:
Expand Down Expand Up @@ -83,7 +91,7 @@ def call_docker(input_file, container, target, report_file, memory_limit, tmpdir
shutil.copy(input_file, str(Path(tmpdir.name, 'input', Path(input_file).name)))

command = f'docker run --rm --ulimit nofile=20000:50000 -m {memory_limit}m -v {tmpdir.name}:/tmp/extractor -v /dev:/dev --privileged {container} {arguments}'
subprocess.run(command, shell=True)
subprocess.run(command, shell=True, check=False)

with suppress(shutil.Error):
shutil.copytree(str(Path(tmpdir.name, 'files')), target)
Expand All @@ -98,25 +106,29 @@ def handle_report(report_file, tmp):
if report_file:
Path(report_file).write_text(indented_report)
else:
print(indented_report)
print(indented_report) # noqa: T201


def main():
arguments = parse_arguments()
setup_logging(arguments.verbose)

output_directory = arguments.output_directory if arguments.output_directory else str(Path('.') / 'extracted_files')
output_directory = arguments.output_directory if arguments.output_directory else str(Path() / 'extracted_files')
if Path(output_directory).exists():
logging.error(f'Target directory exists ({output_directory}). Please choose a non-existing directory with -o option.')
logging.error(
f'Target directory exists ({output_directory}). Please choose a non-existing directory with -o option.'
)
return 1

if not container_exists(arguments.container):
logging.error(f'Container {arguments.container} doesn\'t exist. Please specify an existing container with the -c option.')
logging.error(
f"Container {arguments.container} doesn't exist. Please specify an existing container with the -c option."
)
logging.info(f'You can download the default container with "docker pull {DEFAULT_CONTAINER}"')
return 1

if not Path(arguments.FILE[0]).is_file():
logging.error(f'Given input file {arguments.FILE[0]} doesn\'t exist. Please give an existing path.')
logging.error(f"Given input file {arguments.FILE[0]} doesn't exist. Please give an existing path.")
return 1

if arguments.report_file and not Path(arguments.report_file).parent.is_dir():
Expand All @@ -132,7 +144,7 @@ def main():
target=output_directory,
report_file=arguments.report_file,
memory_limit=arguments.memory,
extract_everything=arguments.extract_everything
extract_everything=arguments.extract_everything,
)

return 0
Expand Down
37 changes: 19 additions & 18 deletions fact_extractor/docker_extraction.py
Original file line number Diff line number Diff line change
@@ -1,24 +1,25 @@
#!/usr/bin/env python3
'''
fact_extractor
Copyright (C) 2015-2019 Fraunhofer FKIE
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
"""
fact_extractor
Copyright (C) 2015-2019 Fraunhofer FKIE
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import argparse
from pathlib import Path
import sys
from pathlib import Path

from helperFunctions.config import get_config_dir
from helperFunctions.file_system import change_owner_of_output_files
Expand Down
32 changes: 16 additions & 16 deletions fact_extractor/fact_extract.py
Original file line number Diff line number Diff line change
@@ -1,26 +1,26 @@
#!/usr/bin/env python3
'''
fact_extractor
Copyright (C) 2015-2019 Fraunhofer FKIE
"""
fact_extractor
Copyright (C) 2015-2019 Fraunhofer FKIE
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
'''
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
"""

import sys
from pathlib import Path

from helperFunctions.program_setup import setup_argparser, setup_logging, load_config
from helperFunctions.program_setup import load_config, setup_argparser, setup_logging
from unpacker.unpack import unpack


Expand All @@ -38,4 +38,4 @@ def main():


if __name__ == '__main__':
exit(main())
sys.exit(main())
12 changes: 6 additions & 6 deletions fact_extractor/helperFunctions/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,23 +5,23 @@


def load_config(config_file_name):
'''
"""
loads config of CONFIG_DIR/config_file_name
Returns config object
'''
"""
config = ConfigParser()
config_path = '{}/{}'.format(get_config_dir(), config_file_name)
config_path = f'{get_config_dir()}/{config_file_name}'
if os.path.exists(config_path):
config.read(config_path)
return config
raise RuntimeError('Cannot load config')


def get_config_dir():
'''
"""
Returns the absolute path of the config directory
'''
return '{}/config'.format(get_src_dir())
"""
return f'{get_src_dir()}/config'


def read_list_from_config(config_file: ConfigParser, section: str, key: str, default=None):
Expand Down
5 changes: 2 additions & 3 deletions fact_extractor/helperFunctions/dataConversion.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import binascii
import json
import types
import binascii


class ReportEncoder(json.JSONEncoder):
Expand Down Expand Up @@ -34,5 +34,4 @@ def make_unicode_string(code):

def remove_uneccessary_spaces(input_string):
tmp = input_string.split()
tmp = ' '.join(tmp)
return tmp
return ' '.join(tmp)
20 changes: 10 additions & 10 deletions fact_extractor/helperFunctions/file_system.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,41 +11,41 @@


def get_src_dir() -> str:
'''
"""
Returns the absolute path of the src directory
'''
"""
return str(SRC_DIR_PATH)


def get_test_data_dir() -> str:
'''
"""
Returns the absolute path of the test data directory
'''
"""
return str(SRC_DIR_PATH / 'test' / 'data')


def get_fact_bin_dir() -> str:
'''
"""
Returns the absolute path of the bin directory
'''
"""
return str(SRC_DIR_PATH / 'bin')


def file_is_empty(file_path) -> bool:
'''
"""
Returns True if file in file_path has 0 Bytes
Returns False otherwise
'''
"""
try:
return Path(file_path).stat().st_size == 0
except (FileNotFoundError, PermissionError, OSError, RuntimeError):
return False


def file_name_sanitize(file_path) -> str:
'''
"""
Returns file path without directory traversal
'''
"""
return file_path.replace('../', '')


Expand Down
3 changes: 1 addition & 2 deletions fact_extractor/helperFunctions/hash.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,7 @@ def get_hash(hash_function, binary):
binary = make_bytes(binary)
raw_hash = new(hash_function)
raw_hash.update(binary)
string_hash = raw_hash.hexdigest()
return string_hash
return raw_hash.hexdigest()


def get_sha256(code):
Expand Down
13 changes: 3 additions & 10 deletions fact_extractor/helperFunctions/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -106,9 +106,7 @@ def pip_install_packages(*packages):
for packet in packages:
try:
run_shell_command_raise_on_return_code(
f'{pip_command} install --upgrade "{packet}"',
f'Error in installation of python package {packet}',
True
f'{pip_command} install --upgrade "{packet}"', f'Error in installation of python package {packet}', True
)
except InstallationError as installation_error:
if 'is a distutils installed project' in str(installation_error):
Expand All @@ -118,17 +116,12 @@ def pip_install_packages(*packages):


def load_requirements_file(path: Path) -> list[str]:
return [
line for line in path.read_text().splitlines()
if line and not line.startswith('#')
]
return [line for line in path.read_text().splitlines() if line and not line.startswith('#')]


def check_if_command_in_path(command):
_, return_code = execute_shell_command_get_return_code(f'command -v {command}')
if return_code != 0:
return False
return True
return return_code == 0


def install_github_project(project_path: str, commands: List[str]):
Expand Down
2 changes: 1 addition & 1 deletion fact_extractor/helperFunctions/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,5 @@ def _get_plugin_src_dirs(base_dir):
if plugin_code_dir.is_dir():
plugins.append(str(plugin_code_dir))
else:
logging.warning('Plugin has no code directory: {}'.format(plugin_path))
logging.warning(f'Plugin has no code directory: {plugin_path}')
return plugins
14 changes: 9 additions & 5 deletions fact_extractor/helperFunctions/program_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,23 @@


def setup_argparser(name, description, command_line_options, version=__VERSION__):
parser = argparse.ArgumentParser(description='{} - {}'.format(name, description))
parser.add_argument('-V', '--version', action='version', version='{} {}'.format(name, version))
parser = argparse.ArgumentParser(description=f'{name} - {description}')
parser.add_argument('-V', '--version', action='version', version=f'{name} {version}')
parser.add_argument('-l', '--log_file', help='path to log file', default=None)
parser.add_argument('-L', '--log_level', help='define the log level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default=None)
parser.add_argument(
'-L', '--log_level', help='define the log level', choices=['DEBUG', 'INFO', 'WARNING', 'ERROR'], default=None
)
parser.add_argument('-d', '--debug', action='store_true', default=False, help='print debug messages')
parser.add_argument('-C', '--config_file', help='set path to config File', default='{}/main.cfg'.format(get_config_dir()))
parser.add_argument('-C', '--config_file', help='set path to config File', default=f'{get_config_dir()}/main.cfg')
parser.add_argument('FILE_PATH', type=str, help='Path to file that should be extracted')
return parser.parse_args(command_line_options[1:])


def setup_logging(debug, log_file=None, log_level=None):
log_level = log_level if log_level else logging.WARNING
log_format = logging.Formatter(fmt='[%(asctime)s][%(module)s][%(levelname)s]: %(message)s', datefmt='%Y-%m-%d %H:%M:%S')
log_format = logging.Formatter(
fmt='[%(asctime)s][%(module)s][%(levelname)s]: %(message)s', datefmt='%Y-%m-%d %H:%M:%S'
)
logger = logging.getLogger('')
logger.setLevel(logging.DEBUG)

Expand Down
Loading

0 comments on commit cdcda4b

Please sign in to comment.