Created
August 9, 2024 16:24
-
-
Save joshfinley/b2e121768b86ad6f270b466854d5da0f to your computer and use it in GitHub Desktop.
🥱
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# 🥱 https://www.elastic.co/security-labs/get-injectedthreadex-detection-thread-creation-trampolines | |
import os | |
import pefile | |
import re | |
# Define the flag for CFG in DLL characteristics | |
IMAGE_DLLCHARACTERISTICS_GUARD_CF = 0x4000 | |
# Define the flag for executable sections | |
IMAGE_SCN_MEM_EXECUTE = 0x20000000 | |
def check_cfg_and_text_section(dll_path): | |
try: | |
pe = pefile.PE(dll_path) | |
# Check for valid text section | |
text_section = next((s for s in pe.sections if s.Name.decode().strip('\x00') == '.text'), None) | |
if not text_section: | |
return None, None, None | |
# Check if text section is executable | |
is_executable = text_section.Characteristics & IMAGE_SCN_MEM_EXECUTE != 0 | |
# Check CFG | |
cfg_enabled = False | |
if hasattr(pe.OPTIONAL_HEADER, 'DllCharacteristics'): | |
if pe.OPTIONAL_HEADER.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_GUARD_CF: | |
cfg_enabled = True | |
return cfg_enabled, is_executable, text_section.get_data() | |
except pefile.PEFormatError: | |
return None, None, None | |
def find_pattern_in_text_section(data, pattern): | |
return [hex(m.start()) for m in re.finditer(pattern, data)] | |
def check_dlls_in_folder(folder_path): | |
no_cfg_count = 0 | |
pattern_match_count = 0 | |
for root, dirs, files in os.walk(folder_path): | |
for file in files: | |
if file.lower().endswith('.dll'): | |
dll_path = os.path.join(root, file) | |
try: | |
cfg_enabled, is_executable, text_section_data = check_cfg_and_text_section(dll_path) | |
if cfg_enabled is None or not is_executable: | |
continue # Skip DLLs without a valid executable text section | |
if not cfg_enabled: | |
no_cfg_count += 1 | |
if text_section_data: | |
pattern = b'\xff\xe1' | |
matches = find_pattern_in_text_section(text_section_data, pattern) | |
if matches: | |
pattern_match_count += 1 | |
print(f'{dll_path}: No CFG, "ff e1" pattern at offsets: {", ".join(matches)}') | |
except PermissionError: | |
pass # Silently skip access denied files | |
except Exception as e: | |
pass # Silently skip other errors | |
return no_cfg_count, pattern_match_count | |
# Specify the folder to check | |
folder_to_check = r'C:\\' | |
no_cfg_count, pattern_match_count = check_dlls_in_folder(folder_to_check) | |
print(f'Found {no_cfg_count} DLLs without CFG in {folder_to_check}') | |
print(f'Of these, {pattern_match_count} DLLs also contain the "ff e1" pattern in an executable text section') |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment