Some Malicious PE Stats
During my last FOR610 session, a student asked me if I had some statistics in mind about the compilers used to generate malicious PE files? A couple of months ago, I shared some stats about the trend in 64bits VS. 32bits malware[1]. Can we go a bit further? I (vibe-)coded a Python script based on the pefile library[2] to extract some info from the PE headers. Indeed, the PE file format contains a lot of metadata! They can be accessed using a lot of tools, like Detect It Easy:

Note: When you assess a PE file, a gold rule to follow is to never trust what you see because these metadata can be tempered!
I tried to detect the compiler using three techniques:
- The "Rich Header" is a block of data containing useful information (but undocumented by Microsoft). It's an XOR-obfuscated block that the Microsoft linker embeds between the DOS stub and the NT headers of PE files built with the MSVC toolchain. It records the @comp.id (product id + build number) and use-count of every object file that went into the link, which lets you fingerprint the exact compiler/linker/assembler build used, as well as, even the count of source files. pefile is able to handle these data smoothly.
- The .NET CLR header (IMAGE_COR20_HEADER) + CLR metadata root, for managed (C#/VB.NET/F#) binaries. This gives the CLR runtime version and the embedded metadata version string (e.g. "v4.0.30319"). This is manually parsed per the public ECMA-335 spec (there's no MSVC Rich Header in managed-only PEs).
- A light heuristic string scan for common non-Microsoft compiler signatures (GCC/MinGW, Clang/LLVM, Delphi/Borland, Free Pascal, Go, Rust), since none of those toolchains write a Rich Header. Just because strings are always easy to process and may reveal juicy information!
As said above, there is no official Microsoft documentation for the Rich Header, and no single authoritative mapping of every product-id -> tool/version exists. But they are community references that helps! The well-known "comp_id.txt" is one of them and constantly updated[3].
Now that we have a tool, where can we find fresh meat? Malware Bazaar is a good candidate because it is pretty popular and get new samples daily. They allow (but don't abuse) to download their data set for free! The first step was to download all the archive they offer[4]. I downloaded a total of 1.3 TB of ZIP archives, one archive per day from 2020-02-24 to 2026-07-08.
Because PE files can be embedded into other files and to avoid using to much storage, I rewrote the script:
- To unzip files in memory and avoid touching the disk
- To perform a recursive scan up to 3 levels
Here are the stats I gathered after “a few days” of processing!
High level stats
| Total scanned files | 23.501.548 |
| Not PE | 22.580.068 |
| Valid PE | 690.689 |
| Encrypted or unreadable | 227.755 |
| Invalid PE | 1.508 |
| ZIP Bomb | 951 |
| Invalid ZIP | 519 |
| Error | 36 |
| Skipped Nested ZIP (> 3 levels) | 19 |
| File Too Large | 3 |
About the architecture:
| 32 Bits (or other architecture) | 565.179 |
| 64 Bits | 125.510 |
Interesting, this confirms my previous research: 32 bits PE file remain popular.
Rich Header:
| Rich Header Present | 371.103 |
| No Rich Header (Maybe stripping, a non-MSVC toolchain, tempeing,...) | 319.586 |
Top-10 linker versions:
| linker 48.0 | 102.307 |
| linker 6.0 | 91.788 |
| linker 9.0 | 62.070 |
| linker 8.0 | 47.829 |
| linker 2.25 | 36.673 |
| linker 10.0 | 36.549 |
| linker 14.0 | 29.786 |
| linker 11.0 | 25.784 |
| linker 14.29 | 24.655 |
| linker 80.0 | 22.691 |
Top MSVC Rich Header compiler builds (useful for clustering samples built in the same environment/campaign):
| build 26213 | 19.603 |
| build 24213 | 15.389 |
| build 30034 | 14.325 |
| build 26706 | 7.755 |
| build 24215 | 5.253 |
| build 32533 | 5.033 |
| build 33030 | 4.442 |
| build 31823 | 3.738 |
| build 25834 | 3.530 |
| build 27412 | 3.294 |
Finally, and the most interesting status, what tools are used by attackers?
|
Unidentified (no Rich Header, no signature match) |
272.439 |
39.4% |
| Microsoft toolchain (Rich Header present, no recognized C/C++ entry) | 216173 | 31.3% |
| Borland C++/Delphi | 20172 | 2.9% |
| Microsoft Visual C/C++ (Rich Header, compiler build 26213) | 19603 | 2.8% |
| GCC / MinGW | 13804 | 2.0% |
| Go | 6254 | 0.9% |
| Embarcadero/Borland Delphi | 6174 | 0.9% |
| Rust | 1329 | 0.2% |
| Clang/LLVM | 91 | 0.0% |
| Free Pascal (FPC) | 1 | 0.0% |
Interesting to see that arising programming languages like Go or Rust remain exotic in the data set! I expected more popularity!
[1] https://isc.sans.edu/diary/2026+64Bits+Malware+Trend/32718
[2] https://github.com/erocarrera/pefile
[3] https://github.com/dishather/richprint/blob/master/comp_id.txt
[4] https://bazaar.abuse.ch/export/
Xavier Mertens (@xme)
Senior ISC Handler | SANS Principal Instructor | Freelance Consultant
Xameco | PGP Key

Comments