dnfile
Parse .NET executable files.
Free software: MIT license
Features
Parse as much as we can, even if the file is partially malformed.
Easy to use. Developed with IDE autocompletion in mind.
Quick Start
pip install dnfile
Then create a simple program that loads a .NET binary, parses it, and displays information about the streams and Metadata Tables.
import sys
import dnfile
filepath = sys.argv[1]
pe = dnfile.dnPE(filepath)
pe.print_info()
Everything is an object, and raw structure values are stored in an object’s “struct” attribute. The CLR directory entry object is accessible from the “net” attribute of a dnPE object.
import dnfile
import hashlib
pe = dnfile.dnPE(FILEPATH)
# access the directory entry raw structure values
pe.net.struct
# access the metadata raw structure values
pe.net.metadata.struct
# access the streams
for s in pe.net.metadata.streams_list:
if isinstance(s, dnfile.stream.MetaDataTables):
# how many Metadata tables are defined in the binary?
num_of_tables = len(s.tables_list)
# the last Metadata tables stream can also be accessed by a shortcut
num_of_tables = len(pe.net.mdtables.tables_list)
# create a set to hold the hashes of all resources
res_hash = set()
# access the resources
for r in pe.net.resources:
# if resource data is a simple byte stream
if isinstance(r.data, bytes):
# hash it and add the hash to the set
res_hash.add(hashlib.sha256(r.data).hexdigest())
# if resource data is a ResourceSet, a dotnet-specific datatype
elif isinstance(r.data, dnfile.resource.ResourceSet):
# if there are no entries
if not r.data.entries:
# skip it
continue
# for each entry in the ResourceSet
for entry in r.data.entries:
# if it has data
if entry.data:
# hash it and add the hash to the set
res_hash.add(hashlib.sha256(entry.data).hexdigest())
TODO
more tests
Documentation on readthedocs
Credits
This package was created with Cookiecutter and the audreyr/cookiecutter-pypackage project template.
History
0.18.0 (2026)
BUGFIX: sanity check value of mdtable num_rows value; do not process if larger than stream size
FEATURE: UserString objects, add ability to set string decode error option
add py 3.10 and 3.11 to supported versions list
minor example changes
0.17.0 (2025)
BUGFIX: DateTime object creation error.
0.16.0 (2025)
BREAKING CHANGE: resource type DateTime is parsed into an object that exposes Kind value
FEATURE: access GUIDS stream like a 0-based sequence. GuidHeap subclasses abc.Sequence
0.15.1 (2024)
BUGFIX: read_compressed_int() now returns None on invalid data len instead of IndexError
BUGFIX: when parsing resources, ignore DateTimeKind bits of a serialized System.DateTime
EXAMPLE: Iterate guids
0.15.0 (2024)
BREAKING CHANGE: each heap stream’s .get() returns a HeapItem instead of bytes
FEATURE: All HeapItem objects include the RVA of where they were retrieved
FEATURE: HeapItemBinary objects allow easy access to interpreted item size (CompressedInt)
FEATURE: HeapItemString and UserString allow easy access to raw bytes and interpreted value
improvements to pypi publishing and tox testing
0.14.1 (2023)
fix github workflow
0.14.0 (2023)
BREAKING CHANGE: Minimum required Python version is now 3.8
BUGFIX: ValueError fired before UnicodeDecodeError when parsing assembly resources
BUGFIX: mdtable row run-lists of size one were being ignored
BUGFIX: some struct file offsets were RVA values
FEATURE: Add clr_lazy_load option for lazy loading Metadata tables and assembly resources
move from legacy setup.py to pyproject.toml and tox
bump dev dependencies: mypy and isort
update tests and examples
update README badge to use download statistics from pypistats
0.13.0 (2022)
BREAKING CHANGE: rename GenericMethod mdtable to MethodSpec per ECMA 335
parse more resources, even if there are exceptions
0.12.0 (2022)
FEATURE: parse #Schema stream as MetaDataTables
BUGFIX: MDTableRow off-by-one for end of run
BUGFIX: MethodSemanticsRow typo list of tables for the Method Index
more test data
0.11.0 (2022)
FEATURE: access .NET resources (not same as PE resources!) by a shortcut
BUGFIX: dnstrings example
more attributes default to None
update dev dependencies
remove some warnings
0.10.0 (2022)
BREAKING CHANGE: structure attributes no longer exist by default
BREAKING CHANGE: objects’ attributes always exist, but may be None
BUGFIX: use last stream if multiple of same name
CI: added mypy type checking
when duplicate stream names, behave like runtime and use last one for shortcuts
add user_strings shortcut
able to access MetaDataTables like a 0-based list, with square brackets
added use of logging module for warnings
better type hints for IDEs
more better source comments
more tests
0.9.0 (2021)
bugfix: row indices parsed in structures are one-based, not zero-based
bugfix: TypeDefRow was not parsing Extends coded index
bugfix: incorrect BLOBS_MASK and add EXTRA_DATA skip if flag set
added CI using github workflow
added tests and submodule dnfile-testfiles
added style consistency using pycodestyle and isort
added more examples
parse MetaData tables’ list-type indexes into lists of MDTableRow objects
0.8.0 (2021)
bugfix: Metadata Table indexes (i.e. indexes into other tables) were off by one
0.7.1 (2021)
bugfix: coded index always None
0.7.0 (2021)
bugfix: improper data length check
0.6.0 (2021)
bugfix: referenced wrong object
parse utf-16 strings in #US stream
0.5.0 (2021-01-29)
First release.
Metadata
Release files for dnfile 0.18.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| dnfile-0.18.0.tar.gz | 51.5 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| dnfile-0.18.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 99.6 kB
Release files / dnfile-0.18.0.tar.gz
| Download URL | dnfile-0.18.0.tar.gz |
|---|---|
| Size | 51.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
24eec63d65535b702236001e648bbf2fa139d1a7bea191fdca17c3be337eb4db
|
|
BLAKE2b-256 checksum How to use checksums |
01c389dbe3a48dfa303060d59b74b97b8401cc70b9b4d4c24982202861fd82e9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / dnfile-0.18.0-py3-none-any.whl
| Download URL | dnfile-0.18.0-py3-none-any.whl |
|---|---|
| Size | 48.0 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
7579fe2d6bb1d854aa154929c309fbf34e70b622053a043a51d42f079fad1772
|
|
BLAKE2b-256 checksum How to use checksums |
39ad4f945155a78800cea02cb258bc0b7704c43cf94f50f75c808f0618694153
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for dnfile 0.18.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.