Imphash: fingerprinting malware by its imports

A Windows PE doesn’t just contain code - it declares, up front, every external function it intends to call. That list lives in the Import Address Table, and it turns out to be a surprisingly durable fingerprint. The import hash, or imphash, is simply a hash of that list, and it’s one of the cheapest ways to group related binaries.

How it’s computed

The recipe (originally described by Mandiant) is deterministic:

  1. Walk the import directory in the order the entries appear.
  2. For each imported symbol, build the string library.function, lowercased. The library name has its extension stripped (kernel32.dllkernel32).
  3. Ordinal-only imports are rendered as ordNNN, except for a few special libraries (ws2_32, wsock32, oleaut32) whose well-known ordinals resolve back to real names.
  4. Join everything with commas and take the MD5.
Get-OffsetPEInfo .\sample.exe |
    Select-Object Machine, ImpHash, ImportedDllCount

Because the hash is driven by which functions are imported and in what order, two samples built from the same source with the same toolchain tend to share an imphash even when their bytes differ - different strings, different resources, recompiled with a new campaign ID.

Why it works, and where it breaks

The import order is largely a property of the linker and the source, not of the payload, so imphash clusters build lineage rather than behavior. That’s the strength: it survives cosmetic change. It’s also the weakness - collisions are common for anything built with the same packer or framework, so a shared imphash is a lead, not proof. Delay-loaded imports and pure dynamic resolution (LoadLibrary + GetProcAddress) don’t appear in the static table at all, so malware that resolves APIs at runtime has a nearly empty imphash that says little.

Treat it as one signal among several: pair it with the Rich-header toolchain fingerprint (build environment), a fuzzy hash like TLSH (byte-level similarity), and the Authenticode signer. When three independent axes agree, the attribution is a lot harder to argue with than any one hash alone.