Something arrived that you did not expect: an attachment called Invoice_2291.pdf with an odd icon, a download whose name you do not recognise, a file a colleague says came “from the portal”. Before anyone opens it, you want to know what it actually is. This guide shows how to find out with tools already on Windows 10 and 11, without running the file and without uploading it anywhere. You will end up with five facts: the file’s real name, its real type, its SHA-256 fingerprint, its signature status and where Windows thinks it came from, together with what each of them does and does not prove.
No step here needs administrator rights. The commands were checked in PowerShell 7.6 and, where noted, in Windows PowerShell 5.1 on Windows 11.
Important
Nothing in this guide tells you a file is safe. It tells you what the file is and what Windows can verify about it. If after these steps you still do not know why the file is on your computer, do not open it: ask the sender through a different channel, or ask someone you trust to look.
Before you start
Do not double-click the file, and do not preview it. Windows decides how to open a file from the last part of its name, so double-clicking Invoice_2291.pdf.exe runs a program. File Explorer’s preview pane renders documents and images with the same components that open them, so turn it off while you investigate: View > Show > Preview pane in Windows 11 (View > Preview pane in Windows 10). Keep the file where it is; copying it around only makes more copies to clean up.
Get the file’s full path. In File Explorer, select the file and press Ctrl+Shift+C (Windows 11) or Shift+right-click it and choose Copy as path. Then open PowerShell (no elevation) and store the path in a variable, using single quotes so that no character in the name is interpreted:
$path = 'C:\Users\you\Downloads\Invoice_2291.pdf.exe'
Copy as path puts double quotes around the path. Delete them before adding the single quotes, or every command fails with “Cannot find drive. A drive with the name ‘“C’ does not exist.”
Every command below uses -LiteralPath $path. The plain -Path parameter treats [ and ] in a name as wildcard characters, so -Path 'photo[1].jpg' would match a different file called photo1.jpg.
If the file lives in a OneDrive folder, check that it is really on disk first. Reading the content of an online-only file makes OneDrive download it:
(Get-Item -LiteralPath $path -Force).Attributes
Offline or RecallOnDataAccess in the list means the content is still in the cloud. That is harmless for inspection, but now you know the next step will download it.
Step 1: Read the real name
File Explorer hides “known” extensions by default, which is exactly how Invoice_2291.pdf.exe appears as Invoice_2291.pdf. Turn extensions on: View > Show > File name extensions in Windows 11, or tick File name extensions on the View tab in Windows 10. Then ask PowerShell, which never hides anything:
Get-Item -LiteralPath $path -Force |
Format-List Name, Extension, Length, CreationTime, LastWriteTime, Attributes
Name : Invoice_2291.pdf.exe
Extension : .exe
Length : 360448
CreationTime : 10/10/2026 1:12:46 AM
LastWriteTime : 10/10/2026 1:12:46 AM
Attributes : Archive
- Extension is the only part of the name Windows uses to decide how to open the file. Here it is
.exe: a program, whatever the rest of the name says. Other extensions that run code when opened include.scr,.com,.bat,.cmd,.ps1,.vbs,.js,.hta,.msi,.lnkand.url. - Length is the size in bytes. A two-page invoice is rarely several megabytes; a program pretending to be one often is.
- CreationTime is when the file was created on this drive, which for a download is usually the download time. It says nothing about when the document was written.
Names can also hide characters. A right-to-left override (U+202E) makes report + U+202E + fdp.exe display as reportexe.pdf. Long runs of spaces before the real extension push it out of view. List every character outside plain printable ASCII:
$name = (Get-Item -LiteralPath $path -Force).Name
$name.ToCharArray() | Where-Object { [int]$_ -lt 0x20 -or [int]$_ -gt 0x7E } |
ForEach-Object { 'U+{0:X4}' -f [int]$_ }
No output means the name is plain ASCII. U+202E (right-to-left override), U+200B (zero-width space) or U+00A0 (no-break space) in a file name you received is a strong reason for suspicion; accented letters and other scripts are normal in names written in other languages.
What this does not prove: a correct-looking name says nothing about the content. A file can be named .pdf and contain a program.
Step 2: Identify the type from its first bytes
Most file formats start with a fixed signature, sometimes called a magic number. Reading the first bytes shows what the file is regardless of its name, and reading is all it does:
Format-Hex -LiteralPath $path -Count 64
Offset Bytes Ascii
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
------ ----------------------------------------------- -----
0000000000000000 4D 5A 90 00 03 00 00 00 04 00 00 00 FF FF 00 00 MZ� � � ÿÿ
0000000000000010 B8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00 ¸ @
0000000000000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0000000000000030 00 00 00 00 00 00 00 00 00 00 00 00 F8 00 00 00 ø
In Windows PowerShell 5.1, Format-Hex has no -Count parameter. Use Get-Content -LiteralPath $path -Encoding Byte -TotalCount 64 | Format-Hex instead.
Compare the first bytes with this table:
| First bytes (hex) | Shown as | What the file is |
|---|---|---|
4D 5A |
MZ |
A Windows program or library (.exe, .dll, .scr, .sys) |
25 50 44 46 |
%PDF |
A PDF document |
50 4B 03 04 |
PK.. |
A ZIP container: .zip, but also .docx, .xlsx, .pptx, .jar, .msix |
D0 CF 11 E0 A1 B1 1A E1 |
An OLE compound file: legacy .doc, .xls, .ppt, but also .msi and .msg |
|
4C 00 00 00 01 14 02 00 |
L... |
A Windows shortcut (.lnk) |
7B 5C 72 74 66 |
{\rtf |
A Rich Text document |
37 7A BC AF 27 1C |
7z..'. |
A 7-Zip archive |
52 61 72 21 |
Rar! |
A RAR archive |
89 50 4E 47 |
.PNG |
A PNG image |
FF D8 FF |
A JPEG image |
MZ alone is not quite enough for a Windows program. The four bytes at offset 0x3C (here F8 00 00 00, read backwards because Windows stores numbers little-endian: 0x000000F8) point to the real header, which must read PE followed by two zero bytes:
Format-Hex -LiteralPath $path -Offset 0xF8 -Count 4
In Windows PowerShell 5.1, which has no -Offset: (Get-Content -LiteralPath $path -Encoding Byte -TotalCount 0xFC)[0xF8..0xFB] prints the same four bytes as decimal numbers (80 69 0 0).
00000000000000F8 50 45 00 00 PE
MZ plus PE means a Windows executable. If that file is named .pdf, .jpg or .docx, the name is lying about the content.
Scripts (.ps1, .vbs, .js, .bat, .hta) have no signature; they are plain text that an interpreter runs. To read the first lines without running anything:
Get-Content -LiteralPath $path -TotalCount 20
Reading a script in the terminal does not execute it. Long lines of random-looking characters, FromBase64String, -EncodedCommand, DownloadString or Invoke-Expression near the top are typical of scripts that download something else.
What this does not prove: the signature tells you the format, not the intent. A genuine PDF can carry an exploit for a PDF reader, and a genuine ZIP can contain anything. A file can also be two formats at once; tools that identify files from the first bytes only, including this method, will not notice content appended at the end.
Step 3: Calculate the SHA-256 fingerprint
A SHA-256 hash is a 64-character fingerprint of the file’s exact bytes. Change one byte and the hash changes completely.
Get-FileHash -LiteralPath $path -Algorithm SHA256
Algorithm Hash Path
--------- ---- ----
SHA256 468FFE129C395ABF6B21A09EFDF261910A95FB98AA982EAD73CAA7B2B684577E C:\Users\you\Downloads\Invoice_2291.pdf.exe
From Command Prompt, certutil -hashfile "C:\Users\you\Downloads\Invoice_2291.pdf.exe" SHA256 gives the same value in lowercase. Hashing reads the whole file, so a multi-gigabyte download takes a while.
Use the hash in two ways:
- Compare it with a published checksum. If the software’s official site lists a SHA-256 for this download, the values must match exactly (case does not matter). A match proves you have the same bytes the publisher listed; it does not prove the publisher’s file is harmless.
- Look it up instead of uploading the file. Security services let you search by hash. A search shares only the hash. Uploading the file shares its contents, so do not upload anything that may contain personal or company data.
What this does not prove: a hash identifies a file; it does not judge it. “No results” for a hash means nobody has submitted that exact file, which is normal for new downloads, personal documents and anything generated per recipient.
Step 4: Check the Authenticode signature
Programs, installers, drivers and PowerShell scripts can carry an Authenticode signature: a certificate that names the signer, and a cryptographic seal over the file’s content. Windows also signs most of its own files through separate catalog files. Get-AuthenticodeSignature checks both kinds:
$sig = Get-AuthenticodeSignature -LiteralPath $path
$sig | Format-List Status, SignatureType, StatusMessage
$sig.SignerCertificate | Format-List Subject, Issuer, NotBefore, NotAfter, Thumbprint
For a Windows tool it looks like this:
Status : Valid
SignatureType : Catalog
StatusMessage : Signature verified.
Subject : CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
Issuer : CN=Microsoft Windows Production PCA 2011, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
What the status means:
| Status | Meaning |
|---|---|
Valid |
The signature matches the content and chains to a certificate authority this computer trusts. Subject names the signer. |
NotSigned |
The format could carry a signature, but this file has none and no Windows catalog lists it. Windows cannot tell who published it. |
HashMismatch |
The file was changed after it was signed. Treat this as a serious warning: the seal is broken. |
NotTrusted |
The signer’s certificate has been explicitly distrusted on this computer. |
UnknownError |
Read StatusMessage. “The form specified for the subject is not one supported…” means a format that cannot be signed (text, images, archives). “…terminated in a root certificate which is not trusted…” means the signature is intact but self-signed or issued by an authority this computer does not trust. |
SignatureType says where the signature lives: Authenticode is embedded in the file, Catalog means a Windows catalog file lists the file’s hash, and None means no signature was found. For NotSigned files the message includes “You cannot run this script on the current system”; that is PowerShell’s wording for scripts and can be ignored for other file types.
In File Explorer, right-click the file, choose Properties and look for a Digital Signatures tab; Details should say “This digital signature is OK.” The tab appears only for embedded signatures, so a catalog-signed Windows file shows no tab even though it is signed.
Read the Subject. O= is the organisation the certificate was issued to. Ask whether it is the publisher you expected: an invoice from your energy supplier should not arrive as a program signed by an unrelated software company, and a lookalike name (Micros0ft, Adobe Systems Ltd) is a warning sign.
What a valid signature does not prove: that the file is safe, or that it is what its name says. A genuine, validly signed program can be renamed: a copy of Windows Notepad saved as Invoice_2291.pdf.exe still reports Valid, Catalog, signed by Microsoft Windows. Malware has been signed with stolen and with legitimately purchased certificates, and scammers often send real, signed remote-access tools. A signature answers “who signed this and has it changed since”; it never answers “should I run this”.
What a missing signature does not prove: that the file is malicious. Many legitimate programs, especially small open-source tools, are unsigned. It means you have no cryptographic evidence of who published it.
Step 5: Check the Mark-of-the-Web
When a browser, mail client or messaging app saves a file from the internet on an NTFS drive, it usually attaches a small hidden stream called Zone.Identifier. This Mark-of-the-Web is what makes Windows show a SmartScreen check before running a downloaded program and makes Office open downloaded documents in Protected View. List the file’s streams, then read the mark:
Get-Item -LiteralPath $path -Stream * | Select-Object Stream, Length
Get-Content -LiteralPath $path -Stream Zone.Identifier
Stream Length
------ ------
:$DATA 360448
Zone.Identifier 116
[ZoneTransfer]
ZoneId=3
ReferrerUrl=https://mail.example.com/
HostUrl=https://files.example.net/invoice.pdf.exe
:$DATA is the file’s normal content. The ZoneId says where Windows believes the file came from:
| ZoneId | Zone | Meaning |
|---|---|---|
| 0 | Local computer | Created on this PC |
| 1 | Local intranet | From a server inside your organisation |
| 2 | Trusted sites | From a site on your trusted-sites list |
| 3 | Internet | Downloaded from the internet: the usual value |
| 4 | Restricted sites | From a site explicitly marked as untrusted |
HostUrl is the address the file was downloaded from and ReferrerUrl the page that linked to it, when the saving program recorded them; they are often missing. A HostUrl on a domain that has nothing to do with the claimed sender is informative.
If there is no mark, Get-Content fails with “Could not open the alternate data stream ‘Zone.Identifier’ of the file”. From Command Prompt, dir /r lists streams as well. In File Explorer the mark shows on the file’s Properties > General tab as “This file came from another computer and might be blocked to help protect this computer”, next to an Unblock box.
Warning
Do not tick Unblock or run
Unblock-Filewhile you are still unsure about the file. Both delete the Mark-of-the-Web, which turns off the SmartScreen check and Office Protected View for this file. Unblocking does not make a file safer; it only removes a safety net.
What the mark does not prove: a mark only records origin. No mark does not mean the file is local or trustworthy: FAT32 and exFAT drives (most USB sticks) cannot store streams, so files copied from them lose the mark; many archive tools do not pass the mark on to extracted files; files synchronised by cloud clients, cloned with Git or downloaded with command-line tools such as curl.exe usually have none.
Step 6: Special cases worth a closer look
Shortcuts (.lnk). A shortcut is a small file that runs another program, often with arguments, and attackers ship them inside ZIP files with document icons. Read where it points without running it:
$shortcut = (New-Object -ComObject WScript.Shell).CreateShortcut($path)
$shortcut | Format-List TargetPath, Arguments, WorkingDirectory
A “document” shortcut whose TargetPath is powershell.exe, cmd.exe, mshta.exe or rundll32.exe with long arguments is not a document. Some shortcuts store their target in a form this method cannot read, in which case TargetPath is empty; that is not proof of anything either way.
Archives and Office documents. tar.exe, built into Windows 10 version 1803 and later, lists the contents of ZIP-based files without extracting anything:
tar -tf $path
word/document.xml
word/vbaProject.bin
For a ZIP, look for programs, scripts and shortcuts inside. For a Word, Excel or PowerPoint file (which are ZIP containers), a vbaProject.bin entry means the document contains macros. Macro-enabled documents are normally named .docm, .xlsm or .pptm; macros inside a file called .docx are a reason to stop.
Step 7: Scan with Microsoft Defender
Caution
The Explorer menu scan, and the command below without
-DisableRemediation, are not read-only. Defender acts on what it finds, and a detected file is quarantined or removed. That is usually what you want, but it is a change, and it may remove a file you still need as evidence.
A signature scan adds what none of the steps above can: comparison with known malware. In File Explorer, right-click the file and choose Scan with Microsoft Defender (in Windows 11 it may be under Show more options). From PowerShell, Defender’s command-line scanner can scan one file and report without acting on the result:
& "$env:ProgramFiles\Windows Defender\MpCmdRun.exe" -Scan -ScanType 3 -File $path -DisableRemediation
Scan starting...
Scan finished.
Scanning C:\Users\you\Downloads\Invoice_2291.pdf.exe found no threats.
-ScanType 3 is a custom scan of the given file and -DisableRemediation tells Defender to report only: it ignores scan exclusions and takes no action on a detection. A detection lists the threat name and the command exits with code 2.
Read the last line carefully. “was skipped” means Defender did not scan the file at all. Without -DisableRemediation, the usual reason is a scan exclusion covering that folder, which is why the command above includes it; skipped is never clean. And “found no threats” means the file matched nothing Defender knows today, not that it is harmless.
Verify: write down what you found
You have finished when you can fill in every line of this summary for the file. Collecting it in one object gives you a record to keep or send to someone helping you:
$item = Get-Item -LiteralPath $path -Force
$head = Get-Content -LiteralPath $path -AsByteStream -TotalCount 8
$sig = Get-AuthenticodeSignature -LiteralPath $path
$motw = (Get-Content -LiteralPath $path -Stream Zone.Identifier -ErrorAction SilentlyContinue) -join "`n"
[pscustomobject]@{
Name = $item.Name
Size = $item.Length
Modified = $item.LastWriteTime
FirstBytes = ($head | ForEach-Object { '{0:X2}' -f $_ }) -join ' '
SHA256 = (Get-FileHash -LiteralPath $path -Algorithm SHA256).Hash
Signature = "$($sig.Status) ($($sig.SignatureType))"
Signer = $sig.SignerCertificate.Subject
ZoneId = [regex]::Match($motw, '(?m)^ZoneId=(\d+)').Groups[1].Value
HostUrl = [regex]::Match($motw, '(?m)^HostUrl=(\S+)').Groups[1].Value
} | Format-List
Name : Invoice_2291.pdf.exe
Size : 360448
Modified : 10/10/2026 1:12:46 AM
FirstBytes : 4D 5A 90 00 03 00 00 00
SHA256 : 468FFE129C395ABF6B21A09EFDF261910A95FB98AA982EAD73CAA7B2B684577E
Signature : Valid (Catalog)
Signer : CN=Microsoft Windows, O=Microsoft Corporation, L=Redmond, S=Washington, C=US
ZoneId : 3
HostUrl : https://files.example.net/invoice.pdf.exe
In Windows PowerShell 5.1, replace -AsByteStream with -Encoding Byte. Empty Signer, ZoneId and HostUrl lines mean no signature and no Mark-of-the-Web.
This example is the trap described in Step 4: a program (MZ) named like a PDF, downloaded from the internet, carrying a perfectly valid Microsoft signature, because it is a renamed copy of Notepad. The signature is real; the name is a lie. Reading the five facts together, rather than any one of them, is what tells you something is wrong.
When something fails
| Message | Cause and fix |
|---|---|
Cannot find path ... because it does not exist |
A typo, or the name contains [ ] and you used -Path. Use -LiteralPath and paste the path in single quotes. |
Cannot find drive. A drive with the name '"C' does not exist. |
The path still has the double quotes that Copy as path adds. Delete them inside the single quotes. |
Access to the path ... is denied |
Your account cannot read the file, for example another user’s folder. Inspect a copy in your own folder instead. |
The process cannot access the file because it is being used by another process |
Another program has the file open exclusively (a download still running, an antivirus scan). Wait and retry. |
Could not open the alternate data stream 'Zone.Identifier' |
Not an error: the file has no Mark-of-the-Web. |
UnknownError from Get-AuthenticodeSignature |
Usually a format that cannot be signed (text, image, archive). Rely on Steps 2 and 3 for such files. |
What to do with the result
If the name, type, signer and origin all agree with what you expected (an installer from the vendor’s own site, signed by that vendor, with a matching published checksum), you have good evidence the file is what it claims to be. That is still a judgement about who made it, not about what it does.
If any of them disagree, especially a program disguised as a document, a broken signature (HashMismatch), a shortcut that launches PowerShell, or macros in a file named .docx, do not open the file. Confirm with the sender through a different channel than the one the file came by. If you have already opened it, run a full scan with Windows Security and ask for help from your IT department or someone you trust.
FileScope: the same inspection in one view
Each step above is a separate command with its own output to interpret. FileScope is a Utility Forge tool that does the same read-only inspection in one pass: drop a file on its window, or run filescope .\Invoice_2291.pdf.exe, and it identifies the content from its bytes (about a hundred formats, with the evidence it used), flags a mismatch with the extension, double extensions and hidden characters in the name, calculates SHA-256, verifies the Authenticode signature offline and reads the Mark-of-the-Web. Each finding comes with a plain-language explanation of what it means and what it does not, and FileScope never calls a file safe or dangerous.
It never runs, changes or uploads the file, and has no network code. FileScope is in development: the engine, command line and desktop app are implemented and tested internally, and there is no public download yet. The FileScope page tracks its status. Until it ships, the steps in this guide are the way to do it.
FAQ
Frequently asked
Is it safe to run these commands on a suspicious file?
Yes. Every command in this guide reads the file as data: Get-Item reads its properties, Format-Hex and Get-Content read bytes, Get-FileHash reads the whole file to hash it, and Get-AuthenticodeSignature asks Windows to check the signature. None of them runs the file or opens it in its associated program. The only command that changes anything is a Defender scan without -DisableRemediation, which can quarantine a detected file.
The signature is valid. Can I open the file now?
A valid signature tells you who signed the file and that it has not been changed since. It does not tell you what the program does or whether you should run it. Signed malware exists, certificates get stolen, and legitimate signed tools (remote access software, for example) are used in scams. Decide from the whole picture: where the file came from, whether you expected it, whether the publisher is the one you expected, and what the file claims to be.
Should I upload the file to an online scanner?
Search for its SHA-256 first; that reveals only the hash. Uploading shares the file's contents with the service, and often with its customers, so never upload documents that may contain personal or company information. A hash that no service knows is not evidence that the file is safe; it may simply be new or unique to you.
Why does File Explorer show no Digital Signatures tab for a signed Windows file?
Most Windows system files are catalog-signed: the signature is in a separate catalog file that lists the file's hash, not inside the file. Explorer's Digital Signatures tab only shows signatures embedded in the file. Get-AuthenticodeSignature checks both and reports Catalog or Authenticode in its SignatureType property.
Can I just remove the 'blocked' mark so the file opens normally?
Only once you are sure about the file. Unblock-File, or the Unblock box in the file's properties, deletes the Mark-of-the-Web, which turns off the SmartScreen check and Office's Protected View for that file. Removing it does not make the file any safer.