Memento-RTLO is a PowerShell tool that demonstrates file extension spoofing
using the Right-to-Left Override Unicode control character (U+202E). It renames
or copies executable files (.exe, .hta, .bat,
.vbs, .ps1) so that their displayed extension appears benign
(e.g. .pdf, .jpeg, .csv, .docx) while
the underlying filesystem entry and operating-system behavior remain unchanged. The visual
deception is produced entirely at the Unicode rendering layer, without modifying file
content or metadata.
The Unicode Standard defines the Bidirectional Algorithm (UAX #9) to handle
mixed-direction text. Code point U+202E RIGHT-TO-LEFT OVERRIDE is a zero-width
format character that forces all subsequent characters to render right-to-left, regardless
of their intrinsic directionality. Because it is non-printing, it is invisible in GUI
contexts — Windows Explorer, Outlook, messaging apps and web browsers render the reversed
characters without exposing the control character.
<DisplayName> + U+202E + reverse(.<SpoofExt>) + <RealExt>
Step by step — payload.exe spoofed to appear as Annexe.jpeg:
Annexe.jpeg, reversed: gepj.gepj..exeU+202E: Annexe[U+202E]gepj..exegepj. via RTLO as .jpeg, giving Annexe.jpeg
Without the leading dot: reverse('jpeg') = gepj, giving Annexejpeg with no separator.
With it: reverse('.jpeg') = gepj. — the dot lands at position 0 after RTLO, producing Annexe.jpeg.
Logical: A n n e x e [U+202E] . g e p j . . e x e ^-- RTL rendering starts here Visual (extensions hidden): Annexe.jpeg OS executes: .exe
| Property | Value |
|---|---|
| Code Point | U+202E |
| Name | RIGHT-TO-LEFT OVERRIDE |
| Block | General Punctuation (U+2000 - U+206F) |
| Category | Cf (Format character) |
| Bidi Class | RLO (Right-to-Left Override) |
| UTF-8 | E2 80 AE (3 bytes) |
| UTF-16LE | 2E 20 (2 bytes, BMP) |
| Category | Name | Description |
|---|---|---|
L | Left-to-Right | Standard Latin characters |
RLO | Right-to-Left Override | U+202E: forces all following characters RTL |
RLE | Right-to-Left Embedding | U+202B: opens an RTL embedding level |
LRO | Left-to-Right Override | U+202D: forces all following characters LTR |
PDF | Pop Directional Formatting | U+202C: terminates the innermost embedding |
| Layer | Behavior |
|---|---|
| NTFS | Stores the exact logical byte sequence including U+202E. No sanitization at the filesystem layer. |
| Windows Shell | Explorer's ListView (comctl32 v6) delegates filename layout to DirectWrite (IDWriteTextLayout), which applies UAX #9. GDI has no bidi logic; this is a DirectWrite-only path on Windows 10/11. |
| Process execution | The kernel resolves filenames by logical byte sequence. The loader reads the real extension and executes accordingly. |
| Extensions visibility | The technique relies on Windows hiding known file extensions (the default setting). When extensions are shown, the real extension appears reversed in the visual name. |
| Option | Required | Description |
|---|---|---|
--file <path> | Yes* | Source file (.exe / .hta / .bat / .vbs / .ps1) |
--choice <N> | No | Predefined pattern index from --show-list |
--name <basename> | No | Custom basename, bypasses predefined patterns |
--fake-ext <ext> | No | Fake extension to display, e.g. pdf, jpg (requires --name) |
--replace | No | Rename in-place instead of creating a copy |
--dry-run | No | Preview output filename, no file written |
--show-list | No | List all patterns; combine with --file to filter by extension |
--bidi-char <mode> | No | rlo (default, U+202E) / rli (U+2067) / rle (U+202B) |
--help | No | Print usage and exit |
* --file optional when using --show-list without extension filter. --name and --choice are mutually exclusive.
| Real Ext | Index | Predefined Patterns |
|---|---|---|
.exe | 1-7 | Rapport_trimestriel.pdf, Annexe_contrat.pdf, Devis_client.pdf, Photo_reunion.jpeg, Scan_document.jpg, Logo_societe.png, Note_interne.txt |
.hta | 8-11 | Info_reunion.jpg, Bilan_annuel.pdf, Fichier_partage.txt, Capture_ecran.png |
.bat | 12-15 | Liste_contacts.csv, Note_reunion.txt, Instructions_setup.txt, Export_donnees.csv |
.vbs | 16-18 | Script_backup.txt, Email_client.eml, Rapport_audit.pdf |
.ps1 | 19-22 | Config_systeme.txt, Rapport_securite.pdf, Donnees_export.csv, Document_interne.docx |
| Field | Value |
|---|---|
| Tactic | Defense Evasion |
| Technique | T1036 - Masquerading |
| Sub-technique | T1036.002 - Right-to-Left Override |
| Platforms | Windows, Linux, macOS |
| Data Sources | File Metadata, File Creation, Process Creation |
| ID | Name | Relationship |
|---|---|---|
| T1566.001 | Spearphishing Attachment | Common delivery vector |
| T1204.002 | User Execution: Malicious File | Requires user click |
| T1027 | Obfuscated Files or Information | Conceptual overlap |
Scan filenames for Unicode bidirectional control characters. Key code points:
U+202A-U+202E and U+2066-U+2069.
GNU Affero General Public License v3.0 — full terms.