![dncil](./.github/dncil.png)
[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/dncil)](https://pypi.org/project/dncil)
[![Last release](https://img.shields.io/github/v/release/mandiant/dncil)](https://github.com/mandiant/dncil/releases)
[![CI](https://github.com/mandiant/dncil/actions/workflows/tests.yml/badge.svg)](https://github.com/mandiant/dncil/actions/workflows/tests.yml)
[![Downloads](https://pepy.tech/badge/dncil)](https://pepy.tech/project/dncil)
[![License](https://img.shields.io/badge/license-Apache--2.0-green.svg)](LICENSE.txt)
`dncil` is a Common Intermediate Language (`CIL`) disassembly library written in Python that supports parsing the header, instructions, and exception handlers of `.NET` managed methods. Parsed data is exposed through an object-oriented API to help you quickly develop `CIL` analysis tools using `dncil`.
Why `Python`? Existing libraries that support `CIL` disassembly, like [`dnLib`](https://github.com/0xd4d/dnlib), are written in `C#`. To leverage these tools, you must build `C#` applications which requires `C#` development experience. Using `dncil`, a pure `Python` alternative, you:
1. Do not need `C#` experience to analyze `CIL` programmatically.
2. Can quickly develop and test your `CIL` analysis tools.
3. Can easily integrate your `CIL` analysis tools with existing `Python` projects.
## Example
The example script [`print_cil_from_dn_file.py`](scripts/print_cil_from_dn_file.py) uses `dncil` together with `.NET` analysis library [`dnfile`](https://github.com/malwarefrank/dnfile) to disassemble the managed methods found in a `.NET` executable. Let's see what it can do.
First, we compile the following `C#` source code:
```C#
using System;
public class HelloWorld
{
public static void Main(string[] args)
{
Console.WriteLine ("Hello World!");
}
}
```
Compilation results in a `PE` executable containing `.NET` metadata which informs the `Common Language Runtime` (`CLR`) how to execute our code. We use `dnfile` to parse this metadata which gives us the offset of our managed method `Main`. We then use `dncil` to disassemble and display the `CIL` instructions stored at this location.
Let's see the above in action:
```
$ python scripts/print_cil_from_dn_file.py hello-world.exe
Method: Main
0000 00 nop
0001 72 01 00 00 70 ldstr "Hello World!"
0006 28 04 00 00 0a call System.Console::WriteLine
000B 00 nop
000C 2a ret
```
Our method `Main` is represented by the [`CilMethodBody`](dncil/cil/body/__init__.py) class. This class holds data that includes the header, `CIL` instructions, and exception handlers of a given managed method. It also exposes various helper functions:
```Python
> main_method_body.flags
SmallFormat : false
TinyFormat : false
FatFormat : false
TinyFormat1 : true
MoreSects : false
InitLocals : false
CompressedIL : false
> main_method_body.size
14
> hexdump.hexdump(main_method_body.get_bytes())
00000000: 36 00 72 01 00 00 70 28 04 00 00 0A 00 2A 6.r...p(.....*
> hexdump.hexdump(main_method_body.get_header_bytes())
00000000: 36 6
> hexdump.hexdump(main_method_body.get_instruction_bytes())
00000000: 00 72 01 00 00 70 28 04 00 00 0A 00 2A .r...p(.....*
```
Each `CIL` instruction found in our managed method `Main` is represented by the [`Instruction`](dncil/cil/instruction.py) class. This class holds data that includes the offset, mnemonic, opcode, and operand of a given `CIL` instruction. It also exposes various helper functions:
```Python
> len(main_method_body.instructions)
5
> insn = main_method_body.instructions[1]
> insn.offset
1
> insn.mnemonic
'ldstr'
> insn.operand
token(0x70000001)
> insn.is_ldstr()
True
> insn.size
5
> hexdump.hexdump(insn.get_bytes())
00000000: 72 01 00 00 70 r...p
> hexdump.hexdump(insn.get_opcode_bytes())
00000000: 72 r
> hexdump.hexdump(insn.get_operand_bytes())
00000000: 01 00 00 70 ...p
```
## Installing
To install `dncil` use `pip` to fetch the `dncil` module:
```
$ pip install dncil
```
To execute the example scripts be sure to install [`dnfile`](https://github.com/malwarefrank/dnfile). Alternatively, install `dncil` with the development dependencies as described in the `Development` section below.
See [print_cil_from_bytes.py](scripts/print_cil_from_bytes.py) for a quick example of using `dncil`to print the `CIL` instructions found in a byte stream containing a `.NET` managed method.
## Development
If you'd like to review and modify `dncil` source code, you'll need to download it from GitHub and install it locally.
Use the following command to install `dncil` locally with development dependencies:
```
$ pip install /local/path/to/src[dev]
```
You'll need `dncil`'s development dependencies to run tests and linting as described below.
### Testing
Use the following command to run tests:
```
$ pytest /local/path/to/src/tests
```
### Linting
Use the following commands to identify format errors:
```
$ black -l 120 -c /local/path/to/src
$ isort --profile black --length-sort --line-width 120 -c /local/path/to/src
$ mypy --config-file /local/path/to/src/.github/mypy/mypy.ini /local/path/to/src/dncil/ /local/path/to/src/scripts/ /local/path/to/src/tests/
```
## Credits
`dncil` is based on the `CIL` parsing code found in [`dnLib`](https://github.com/0xd4d/dnlib).
Raw data
{
"_id": null,
"home_page": "https://www.github.com/mandiant/dncil",
"name": "dncil",
"maintainer": "",
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": "",
"keywords": ".net dotnet cil il disassembly FLARE",
"author": "Mike Hunhoff",
"author_email": "michael.hunhoff@mandiant.com",
"download_url": "https://files.pythonhosted.org/packages/53/79/498fc2e7e7e132bb7930a28cd075f3b3e77de3b4be5f38a9340a866f9802/dncil-1.0.2.tar.gz",
"platform": null,
"description": "![dncil](./.github/dncil.png)\n\n[![PyPI - Python Version](https://img.shields.io/pypi/pyversions/dncil)](https://pypi.org/project/dncil)\n[![Last release](https://img.shields.io/github/v/release/mandiant/dncil)](https://github.com/mandiant/dncil/releases)\n[![CI](https://github.com/mandiant/dncil/actions/workflows/tests.yml/badge.svg)](https://github.com/mandiant/dncil/actions/workflows/tests.yml)\n[![Downloads](https://pepy.tech/badge/dncil)](https://pepy.tech/project/dncil)\n[![License](https://img.shields.io/badge/license-Apache--2.0-green.svg)](LICENSE.txt)\n\n`dncil` is a Common Intermediate Language (`CIL`) disassembly library written in Python that supports parsing the header, instructions, and exception handlers of `.NET` managed methods. Parsed data is exposed through an object-oriented API to help you quickly develop `CIL` analysis tools using `dncil`.\n\nWhy `Python`? Existing libraries that support `CIL` disassembly, like [`dnLib`](https://github.com/0xd4d/dnlib), are written in `C#`. To leverage these tools, you must build `C#` applications which requires `C#` development experience. Using `dncil`, a pure `Python` alternative, you:\n\n1. Do not need `C#` experience to analyze `CIL` programmatically.\n2. Can quickly develop and test your `CIL` analysis tools.\n3. Can easily integrate your `CIL` analysis tools with existing `Python` projects.\n\n## Example\n\nThe example script [`print_cil_from_dn_file.py`](scripts/print_cil_from_dn_file.py) uses `dncil` together with `.NET` analysis library [`dnfile`](https://github.com/malwarefrank/dnfile) to disassemble the managed methods found in a `.NET` executable. Let's see what it can do.\n\nFirst, we compile the following `C#` source code:\n\n```C#\nusing System;\t\n\npublic class HelloWorld\n{\n public static void Main(string[] args)\n {\n Console.WriteLine (\"Hello World!\");\n }\n}\n```\n\nCompilation results in a `PE` executable containing `.NET` metadata which informs the `Common Language Runtime` (`CLR`) how to execute our code. We use `dnfile` to parse this metadata which gives us the offset of our managed method `Main`. We then use `dncil` to disassemble and display the `CIL` instructions stored at this location.\n\nLet's see the above in action:\n\n```\n$ python scripts/print_cil_from_dn_file.py hello-world.exe \n\nMethod: Main\n0000 00 nop \n0001 72 01 00 00 70 ldstr \"Hello World!\"\n0006 28 04 00 00 0a call System.Console::WriteLine\n000B 00 nop \n000C 2a ret \n```\n\nOur method `Main` is represented by the [`CilMethodBody`](dncil/cil/body/__init__.py) class. This class holds data that includes the header, `CIL` instructions, and exception handlers of a given managed method. It also exposes various helper functions:\n\n```Python\n> main_method_body.flags\nSmallFormat : false\nTinyFormat : false\nFatFormat : false\nTinyFormat1 : true\nMoreSects : false\nInitLocals : false\nCompressedIL : false\n> main_method_body.size\n14\n> hexdump.hexdump(main_method_body.get_bytes())\n00000000: 36 00 72 01 00 00 70 28 04 00 00 0A 00 2A 6.r...p(.....*\n> hexdump.hexdump(main_method_body.get_header_bytes())\n00000000: 36 6\n> hexdump.hexdump(main_method_body.get_instruction_bytes())\n00000000: 00 72 01 00 00 70 28 04 00 00 0A 00 2A .r...p(.....*\n```\n\nEach `CIL` instruction found in our managed method `Main` is represented by the [`Instruction`](dncil/cil/instruction.py) class. This class holds data that includes the offset, mnemonic, opcode, and operand of a given `CIL` instruction. It also exposes various helper functions:\n\n```Python\n> len(main_method_body.instructions)\n5\n> insn = main_method_body.instructions[1]\n> insn.offset\n1\n> insn.mnemonic\n'ldstr'\n> insn.operand\ntoken(0x70000001)\n> insn.is_ldstr()\nTrue\n> insn.size\n5\n> hexdump.hexdump(insn.get_bytes())\n00000000: 72 01 00 00 70 r...p\n> hexdump.hexdump(insn.get_opcode_bytes())\n00000000: 72 r\n> hexdump.hexdump(insn.get_operand_bytes())\n00000000: 01 00 00 70 ...p\n```\n\n## Installing\n\nTo install `dncil` use `pip` to fetch the `dncil` module:\n\n```\n$ pip install dncil\n```\n\nTo execute the example scripts be sure to install [`dnfile`](https://github.com/malwarefrank/dnfile). Alternatively, install `dncil` with the development dependencies as described in the `Development` section below.\n\nSee [print_cil_from_bytes.py](scripts/print_cil_from_bytes.py) for a quick example of using `dncil`to print the `CIL` instructions found in a byte stream containing a `.NET` managed method.\n\n## Development\n\nIf you'd like to review and modify `dncil` source code, you'll need to download it from GitHub and install it locally. \n\nUse the following command to install `dncil` locally with development dependencies:\n\n```\n$ pip install /local/path/to/src[dev]\n```\n\nYou'll need `dncil`'s development dependencies to run tests and linting as described below.\n\n### Testing\n\nUse the following command to run tests:\n\n```\n$ pytest /local/path/to/src/tests\n```\n\n### Linting\n\nUse the following commands to identify format errors:\n\n```\n$ black -l 120 -c /local/path/to/src\n$ isort --profile black --length-sort --line-width 120 -c /local/path/to/src\n$ mypy --config-file /local/path/to/src/.github/mypy/mypy.ini /local/path/to/src/dncil/ /local/path/to/src/scripts/ /local/path/to/src/tests/\n```\n\n## Credits\n\n`dncil` is based on the `CIL` parsing code found in [`dnLib`](https://github.com/0xd4d/dnlib).\n\n\n",
"bugtrack_url": null,
"license": "",
"summary": "The FLARE team's open-source library to disassemble Common Intermediate Language (CIL) instructions.",
"version": "1.0.2",
"split_keywords": [
".net",
"dotnet",
"cil",
"il",
"disassembly",
"flare"
],
"urls": [
{
"comment_text": "",
"digests": {
"md5": "4d614f4cf521c9ad86f871ddbe9b4e6b",
"sha256": "69d389e9b850fa9afa2e37ca252b01476379991eee88fd33ab76f924d36dd68d"
},
"downloads": -1,
"filename": "dncil-1.0.2-py3-none-any.whl",
"has_sig": false,
"md5_digest": "4d614f4cf521c9ad86f871ddbe9b4e6b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 27010,
"upload_time": "2022-12-12T19:09:27",
"upload_time_iso_8601": "2022-12-12T19:09:27.582794Z",
"url": "https://files.pythonhosted.org/packages/5b/2d/f6e3fa0832ce1d934a851757058235c9ec5741cff0129cfcf205a9359489/dncil-1.0.2-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"md5": "393f458a96ec17aee0b497ff9ab5ffbe",
"sha256": "1557675c2d1351d3260509881cff0383309f81cda4944ed2c3f5cc352953aa15"
},
"downloads": -1,
"filename": "dncil-1.0.2.tar.gz",
"has_sig": false,
"md5_digest": "393f458a96ec17aee0b497ff9ab5ffbe",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 19318,
"upload_time": "2022-12-12T19:09:29",
"upload_time_iso_8601": "2022-12-12T19:09:29.322462Z",
"url": "https://files.pythonhosted.org/packages/53/79/498fc2e7e7e132bb7930a28cd075f3b3e77de3b4be5f38a9340a866f9802/dncil-1.0.2.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2022-12-12 19:09:29",
"github": true,
"gitlab": false,
"bitbucket": false,
"github_user": "mandiant",
"github_project": "dncil",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "dncil"
}