Name | dnfile JSON |
Version |
0.15.1
JSON |
| download |
home_page | None |
Summary | Parse .NET executable files. |
upload_time | 2024-10-19 02:26:26 |
maintainer | None |
docs_url | None |
author | MalwareFrank |
requires_python | >=3.8 |
license | MIT License |
keywords |
dnfile
|
VCS |
|
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
======
dnfile
======
.. image:: https://github.com/malwarefrank/dnfile/actions/workflows/lint.yml/badge.svg
:target: https://github.com/malwarefrank/dnfile/actions/workflows/lint.yml
.. image:: https://img.shields.io/pypi/v/dnfile.svg
:target: https://pypi.python.org/pypi/dnfile
.. image:: https://img.shields.io/pypi/dm/dnfile
:target: https://pypistats.org/packages/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
-----------
.. code-block:: shell
pip install dnfile
Then create a simple program that loads a .NET binary, parses it, and displays
information about the streams and Metadata Tables.
.. code-block:: python
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.
.. code-block:: python
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.
.. _Cookiecutter: https://github.com/audreyr/cookiecutter
.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage
=======
History
=======
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.
Raw data
{
"_id": null,
"home_page": null,
"name": "dnfile",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.8",
"maintainer_email": null,
"keywords": "dnfile",
"author": "MalwareFrank",
"author_email": null,
"download_url": "https://files.pythonhosted.org/packages/8f/89/6781fe5a1d623b9235f12a10cd76d7eba8458f950a83e861974d103a896d/dnfile-0.15.1.tar.gz",
"platform": null,
"description": "======\ndnfile\n======\n\n\n.. image:: https://github.com/malwarefrank/dnfile/actions/workflows/lint.yml/badge.svg\n :target: https://github.com/malwarefrank/dnfile/actions/workflows/lint.yml\n.. image:: https://img.shields.io/pypi/v/dnfile.svg\n :target: https://pypi.python.org/pypi/dnfile\n.. image:: https://img.shields.io/pypi/dm/dnfile\n :target: https://pypistats.org/packages/dnfile\n\n\nParse .NET executable files.\n\n\n* Free software: MIT license\n\n\nFeatures\n--------\n\n* Parse as much as we can, even if the file is partially malformed.\n* Easy to use. Developed with IDE autocompletion in mind.\n\n\nQuick Start\n-----------\n\n.. code-block:: shell\n\n pip install dnfile\n\nThen create a simple program that loads a .NET binary, parses it, and displays\ninformation about the streams and Metadata Tables.\n\n.. code-block:: python\n\n import sys\n import dnfile\n\n filepath = sys.argv[1]\n\n pe = dnfile.dnPE(filepath)\n pe.print_info()\n\n\nEverything is an object, and raw structure values are stored in an object's \"struct\"\nattribute. The CLR directory entry object is accessible from the \"net\"\nattribute of a dnPE object.\n\n.. code-block:: python\n\n import dnfile\n import hashlib\n\n pe = dnfile.dnPE(FILEPATH)\n\n # access the directory entry raw structure values\n pe.net.struct\n\n # access the metadata raw structure values\n pe.net.metadata.struct\n\n # access the streams\n for s in pe.net.metadata.streams_list:\n if isinstance(s, dnfile.stream.MetaDataTables):\n # how many Metadata tables are defined in the binary?\n num_of_tables = len(s.tables_list)\n\n # the last Metadata tables stream can also be accessed by a shortcut\n num_of_tables = len(pe.net.mdtables.tables_list)\n\n # create a set to hold the hashes of all resources\n res_hash = set()\n # access the resources\n for r in pe.net.resources:\n # if resource data is a simple byte stream\n if isinstance(r.data, bytes):\n # hash it and add the hash to the set\n res_hash.add(hashlib.sha256(r.data).hexdigest())\n # if resource data is a ResourceSet, a dotnet-specific datatype\n elif isinstance(r.data, dnfile.resource.ResourceSet):\n # if there are no entries\n if not r.data.entries:\n # skip it\n continue\n # for each entry in the ResourceSet\n for entry in r.data.entries:\n # if it has data\n if entry.data:\n # hash it and add the hash to the set\n res_hash.add(hashlib.sha256(entry.data).hexdigest())\n\n\nTODO\n----\n\n* more tests\n* Documentation on readthedocs\n\n\nCredits\n-------\n\nThis package was created with Cookiecutter_ and the `audreyr/cookiecutter-pypackage`_ project template.\n\n.. _Cookiecutter: https://github.com/audreyr/cookiecutter\n.. _`audreyr/cookiecutter-pypackage`: https://github.com/audreyr/cookiecutter-pypackage\n\n=======\nHistory\n=======\n\n0.15.1 (2024)\n-------------\n\n* BUGFIX: read_compressed_int() now returns None on invalid data len instead of IndexError\n* BUGFIX: when parsing resources, ignore DateTimeKind bits of a serialized System.DateTime\n* EXAMPLE: Iterate guids\n\n0.15.0 (2024)\n-------------\n* BREAKING CHANGE: each heap stream's .get() returns a HeapItem instead of bytes\n* FEATURE: All HeapItem objects include the RVA of where they were retrieved\n* FEATURE: HeapItemBinary objects allow easy access to interpreted item size (CompressedInt)\n* FEATURE: HeapItemString and UserString allow easy access to raw bytes and interpreted value\n* improvements to pypi publishing and tox testing\n\n0.14.1 (2023)\n-------------\n* fix github workflow\n\n0.14.0 (2023)\n-------------\n* BREAKING CHANGE: Minimum required Python version is now 3.8\n* BUGFIX: ValueError fired before UnicodeDecodeError when parsing assembly resources\n* BUGFIX: mdtable row run-lists of size one were being ignored\n* BUGFIX: some struct file offsets were RVA values\n* FEATURE: Add ``clr_lazy_load`` option for lazy loading Metadata tables and assembly resources\n* move from legacy setup.py to pyproject.toml and tox\n* bump dev dependencies: mypy and isort\n* update tests and examples\n* update README badge to use download statistics from pypistats\n\n0.13.0 (2022)\n-------------\n* BREAKING CHANGE: rename GenericMethod mdtable to MethodSpec per ECMA 335\n* parse more resources, even if there are exceptions\n\n0.12.0 (2022)\n-------------\n* FEATURE: parse ``#Schema`` stream as MetaDataTables\n* BUGFIX: MDTableRow off-by-one for end of run\n* BUGFIX: MethodSemanticsRow typo list of tables for the Method Index\n* more test data\n\n0.11.0 (2022)\n-------------\n* FEATURE: access .NET resources (not same as PE resources!) by a shortcut\n* BUGFIX: dnstrings example\n* more attributes default to None\n* update dev dependencies\n* remove some warnings\n\n0.10.0 (2022)\n-------------\n\n* BREAKING CHANGE: structure attributes no longer exist by default\n* BREAKING CHANGE: objects' attributes always exist, but may be None\n* BUGFIX: use last stream if multiple of same name\n* CI: added mypy type checking\n* when duplicate stream names, behave like runtime and use last one for shortcuts\n* add user_strings shortcut\n* able to access MetaDataTables like a 0-based list, with square brackets\n* added use of logging module for warnings\n* better type hints for IDEs\n* more better source comments\n* more tests\n\n0.9.0 (2021)\n------------\n\n* bugfix: row indices parsed in structures are one-based, not zero-based\n* bugfix: TypeDefRow was not parsing Extends coded index\n* bugfix: incorrect BLOBS_MASK and add EXTRA_DATA skip if flag set\n* added CI using github workflow\n* added tests and submodule dnfile-testfiles\n* added style consistency using pycodestyle and isort\n* added more examples\n* parse MetaData tables' list-type indexes into lists of MDTableRow objects\n\n0.8.0 (2021)\n------------\n\n* bugfix: Metadata Table indexes (i.e. indexes into other tables) were off by one\n\n0.7.1 (2021)\n------------\n\n* bugfix: coded index always None\n\n0.7.0 (2021)\n------------\n\n* bugfix: improper data length check\n\n0.6.0 (2021)\n------------\n\n* bugfix: referenced wrong object\n* parse utf-16 strings in #US stream\n\n0.5.0 (2021-01-29)\n------------------\n\n* First release.\n",
"bugtrack_url": null,
"license": "MIT License",
"summary": "Parse .NET executable files.",
"version": "0.15.1",
"project_urls": {
"repository": "https://github.com/malwarefrank/dnfile"
},
"split_keywords": [
"dnfile"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "698280b8c2111eb37b59871d4df2ef826a7aaa8046f1dc021c56ebeaf7d98906",
"md5": "14c75b999577e51bd41edbde29132e5f",
"sha256": "585c8e3e4a29824402430a0a8b7e7ae82c040fc17eeb3a06758fdceebe2d923e"
},
"downloads": -1,
"filename": "dnfile-0.15.1-py3-none-any.whl",
"has_sig": false,
"md5_digest": "14c75b999577e51bd41edbde29132e5f",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.8",
"size": 46602,
"upload_time": "2024-10-19T02:26:25",
"upload_time_iso_8601": "2024-10-19T02:26:25.055998Z",
"url": "https://files.pythonhosted.org/packages/69/82/80b8c2111eb37b59871d4df2ef826a7aaa8046f1dc021c56ebeaf7d98906/dnfile-0.15.1-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "8f896781fe5a1d623b9235f12a10cd76d7eba8458f950a83e861974d103a896d",
"md5": "a515f67c92c1d2ab537be7db94bb7ebc",
"sha256": "1529cf0f976b1382f60a3c56b2e0def90f3486e41193ffd34677e74563c8426c"
},
"downloads": -1,
"filename": "dnfile-0.15.1.tar.gz",
"has_sig": false,
"md5_digest": "a515f67c92c1d2ab537be7db94bb7ebc",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.8",
"size": 49703,
"upload_time": "2024-10-19T02:26:26",
"upload_time_iso_8601": "2024-10-19T02:26:26.821789Z",
"url": "https://files.pythonhosted.org/packages/8f/89/6781fe5a1d623b9235f12a10cd76d7eba8458f950a83e861974d103a896d/dnfile-0.15.1.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-10-19 02:26:26",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "malwarefrank",
"github_project": "dnfile",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"tox": true,
"lcname": "dnfile"
}