Skip to content
New

DeepSeek V4.1 Flash free for 7 days: 10M tokens a day after any top-up. Until Nov 30.

How it works

File Hashes in DFIR and the Ethics of Uploading to VirusTotal

Learn how hashes identify files, why SHA-256 replaced MD5, how NSRL filters known software, and why uploading a file to VirusTotal shares it.

Beginner10 min readBy NotHoly

What a hash is

A cryptographic hash function takes an input of any length and returns a fixed-length value called a digest. SHA-256 always returns 256 bits, which you read as 64 hexadecimal characters. The same input always gives the same digest. Change one character and the digest changes completely. NIST defines the Secure Hash Standard in FIPS 180-4, which covers SHA-256 and the other SHA algorithms, and it says digests are used to detect whether a message has changed.

For an analyst, the useful idea is simple. A digest is a short, repeatable label for an exact sequence of bytes. Two people who hash the same file on two machines should get the same digest. That is why hashes show up in incident reports, threat intelligence feeds, and software download pages.

A hash identifies bytes, not a name. A file called invoice.pdf and a file called setup.exe have the same digest if their bytes are identical. Renaming a file changes nothing in its digest. The file name tells you what someone called the file. The digest tells you which bytes you actually have.

Why SHA-256 replaced MD5 for identification

MD5 produces a 128-bit digest and was widely used for checksums for many years. Researchers later showed that MD5 is vulnerable to collision attacks, which means someone can build two different inputs that produce the same MD5 digest. SHA-1 has a similar problem with a different construction.

For a file you downloaded yourself, an accidental collision is very unlikely. The concern is deliberate. An attacker who can craft a second file with the same digest can swap it in for a file you already trust, and the digest in your records will still match. Once collisions are practical, a match no longer proves that two files are the same, and that proof is the main thing you need from a hash.

The working rule is simple. Use SHA-256 for identification, for evidence records, and for anything you may need to defend later. You will still see MD5 and SHA-1 in old feeds, old tools, and old reports. Treat those values as lookup keys, and do not present them as proof that two files match.

Hash sets: filtering out what you already know

An investigator does not read every file on a disk. The first useful question is which files are already known. The National Software Reference Library (NSRL), maintained by NIST, collects software and creates file profiles that go into a Reference Data Set (RDS). The RDS is a collection of digital signatures of known, traceable software applications. It includes hashes of legitimate software, and also of some applications that may be malicious, such as steganography tools and hacking scripts. Investigators use it to match files on seized computers against known profiles, which separates routine software from files that might matter.

Hash sets are a filter, and they answer a narrow question: is this exact file in the set? A file that is not in the set may be a custom tool, a document, or malware. A file that is in the set is a known file, which is not the same as a safe file. A set built from one version of a program will not match a different version of the same program.

You can build a small version of the same idea for your own environment. Hash the files that ship on a clean laptop image, keep the list with the version and the date, and compare new machines against it. Anything that does not match gets a second look. Nothing is proven by that comparison, but the work shrinks to the files that differ.

A hash match says nothing about a modified file

Hash matching is exact. If one byte changes, the digest changes. That gives you three rules to keep in mind.

When a digest matches a known-good value, the bytes are identical to the file in that set. That is strong evidence for the bytes. It does not tell you what the program does at runtime, and the same bytes can behave differently with different configuration or inputs.

When a file has been modified, its digest will not match, even if the change is trivial. A rebuilt installer, a patched binary, a changed config value, or a text file saved with different line endings all produce a new digest. The mismatch tells you the bytes differ. It does not tell you whether the change is harmful or harmless. You need another method to decide that.

When a digest matches a known-bad value, you know this exact file was seen before. A new variant is a new file with a new digest, so a list of known-bad hashes misses it. A clean lookup for a new sample is not a verdict on that sample either.

The same program can also have different digests across versions. Windows Notepad is a good example. Its digest can change from one Windows build to another. A hash without a version next to it tells you very little, so record the version every time you record a digest.

Searching a hash versus uploading a file

VirusTotal lets you search for a file by its hash. You paste a SHA-256, MD5, or SHA-1 value into the search box, and VirusTotal shows a page for any file it already knows with that digest. A hash search sends the digest to the service. It does not send the file.

Uploading is a different action. VirusTotal's documentation says that any user can select a file from their computer and send it to VirusTotal. It also says that scanning reports are shared with the public VirusTotal community, that the contents of submitted files may be shared with premium VirusTotal customers, and that basic results are shared with the submitter and between the examining partners.

An upload is a publication decision. Once the file leaves your machine, you cannot take it back, and you do not control who receives it. For a sample of public malware, sharing can help other defenders. For a file that contains customer data, an unsigned contract, source code from a client, a password database, or personal records, sharing it can break a contract, breach privacy law, and expose someone who never agreed to it.

The rule for field work is short. Never upload confidential or customer files to VirusTotal or any other public scanner. Check your employer's or client's policy before you send any sample anywhere. If a digest is all you need, search the digest. If you need a verdict on a sample you cannot share, use a tool you control, such as a local sandbox or an internal service that your organization has approved.

A hash search is not free of consequences. The service receives the digest, and a digest of a customer's file can reveal what you are looking for. Check the policy for hash searches too, especially in an active case.

Hands-on lab: hash your own files

You need a computer with a terminal. You will hash system programs and a file you create, then search one known benign digest on VirusTotal. You will not upload anything. Use only files on your own machine.

Step 1: hash a system program

On Linux, run:

bash
sha256sum /bin/ls

On macOS, run:

bash
shasum -a 256 /bin/ls

On Windows, open PowerShell and run:

powershell
Get-FileHash C:\Windows\System32\notepad.exe -Algorithm SHA256

On Windows with Git Bash, you can also run the same check from the terminal:

bash
sha256sum /c/Windows/System32/notepad.exe

On the machine where we tested this article, Windows 11 with Git Bash, these were the observed results:

text
$ sha256sum /bin/ls
b45981580702029cfeeffc8ca69e2a4d1e9c68914009e94c31ffec9cbc544aa5 */bin/ls
text
Algorithm : SHA256
Hash      : 468FFE129C395ABF6B21A09EFDF261910A95FB98AA982EAD73CAA7B2B684577E
Path      : C:\Windows\System32\notepad.exe
text
$ sha256sum /c/Windows/System32/notepad.exe
468ffe129c395abf6b21a09efdf261910a95fb98aa982ead73caa7b2b684577e */c/Windows/System32/notepad.exe

The ls digest comes from Git Bash's own copy of ls, so it will not match the ls on your Linux or macOS machine. The notepad digest is the same in both shells because the hex case is the only difference. Compare digests case-insensitively. The same machine also reported the file version 10.0.26100.9949 and a length of 360448 bytes for notepad.exe. Write those down next to the digest, because a different Windows build will give a different digest for the same program name.

Step 2: see how one character changes the digest

Run this in Git Bash or any POSIX shell:

bash
echo 'lab' > a.txt && sha256sum a.txt && echo 'lab.' > a.txt && sha256sum a.txt

The observed output was:

text
b76025a9ca630b026d630d59a18cf414f5724d2bbf5dc4b11dd165c9c1ea8e01 *a.txt
d233123b7c71a1b7234066f700e03452959ce5bb0b4802f0cbd2c2437004a879 *a.txt

The only change was one period. Both digests are 64 characters long, and they share no visible pattern. The echo command also adds a newline, so the first file holds lab followed by a line break, and the second holds lab. followed by a line break. You can check the exact bytes with od -c a.txt. Line endings are a common reason two copies of "the same text" give different digests. A file saved on Windows with CRLF line endings produces a different digest from the same text saved with LF.

Step 3: search a known benign digest on VirusTotal

Open a browser and go to https://www.virustotal.com/gui/search/ followed by the Notepad SHA-256 digest from Step 1. You can also paste the digest into the search box on the VirusTotal site. Do not drop a file on the page and do not click any upload control.

In our run, the search address went to a file page for that digest, but the page first showed a reCAPTCHA check. We did not complete it, so the report results are not shown in this article. If you want to see the results, complete the check yourself. VirusTotal asks for this to stop automated traffic, and that is the site's decision to make, not ours.

When the page loads, write down four things in your notes:

  • The names and file types the page lists for that digest.
  • The number of engines that flagged the file, and the total number of engines.
  • The first-seen and last-seen dates.
  • Whether the digest on the page matches the digest you computed on your machine.

Then write down what the page does not tell you. A result with no detections means no engine flagged this digest at that time. It does not prove the file is safe. The page also says nothing about your copy unless the digests match, and it says nothing about what the program does when it runs.

Common mistakes

Hashing the wrong file. A download can be copied, renamed, or converted before you look at it. Hash the exact file you are investigating, record its path and the time you computed the digest, and check that any copy has the same digest as the original.

Treating MD5 or SHA-1 as proof. Use SHA-256 for identification. Keep older digests only as lookup keys.

Reading a clean result as safe. A digest with no detections can be new malware, targeted malware, or a file that no engine has seen yet. Clean means "not flagged," nothing more.

Trusting the file name. Names are easy to change. The digest is the identifier, and the name is only a label.

Uploading to see what a file is. This is the mistake that causes real incidents. A hash search answers the question for a known file. An upload publishes the file itself.

Forgetting the version. The same program name can produce many digests. Record the version and build next to every digest, or the digest will not mean much later.

How to go further

Compute digests for every file in a folder and save them as a manifest, so you can detect later changes. On Linux or macOS, run sha256sum * > manifest.txt inside the folder. Keep the manifest with the evidence and recompute the digests later to see what changed. This command is standard, but we have not run it in the lab for this article, so check its output on your own machine.

Read FIPS 180-4 for the exact definitions of the SHA algorithms and their output sizes. Read the NSRL page to see how a reference data set is built and used in practice. Read the VirusTotal documentation on how submissions are handled before you use any public scanner in your work.

The next step is to write detection logic against a file you control. The article Write a YARA rule against a benign test file shows how to match patterns rather than whole digests, which covers the cases an exact hash cannot.

Sources

Related reading: Encryption, encoding and hashing compared and the previous article in this series, First Ghidra analysis with a binary you compile.

Sources

  1. FIPS 180-4, Secure Hash Standard (NIST)
  2. National Software Reference Library (NIST)
  3. How VirusTotal works (VirusTotal documentation)

More in Malware and forensics

Malware and forensics

Write a YARA Rule Against a Benign Test File

Write a first YARA rule, match one harmless test file and not another, and learn why every rule needs positive and negative tests.

Beginner9 min read