exeplot 0.5.2__tar.gz → 0.5.5__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. exeplot-0.5.5/.github/dependabot.yml +15 -0
  2. exeplot-0.5.5/.github/workflows/python-package.yml +142 -0
  3. exeplot-0.5.5/.github/workflows/security.yml +31 -0
  4. exeplot-0.5.2/.readthedocs.yml → exeplot-0.5.5/.readthedocs.yaml +1 -1
  5. {exeplot-0.5.2 → exeplot-0.5.5}/PKG-INFO +8 -4
  6. {exeplot-0.5.2 → exeplot-0.5.5}/README.md +4 -3
  7. exeplot-0.5.5/SECURITY.md +17 -0
  8. {exeplot-0.5.2 → exeplot-0.5.5}/docs/coverage.svg +1 -1
  9. {exeplot-0.5.2 → exeplot-0.5.5}/docs/mkdocs.yml +28 -9
  10. exeplot-0.5.5/docs/pages/api.md +190 -0
  11. exeplot-0.5.5/docs/pages/cli/exeplot.md +191 -0
  12. exeplot-0.5.5/docs/pages/contributing.md +86 -0
  13. exeplot-0.5.5/docs/pages/index.md +65 -0
  14. exeplot-0.5.5/docs/pages/installation.md +73 -0
  15. exeplot-0.5.5/docs/pages/internals.md +105 -0
  16. {exeplot-0.5.2 → exeplot-0.5.5}/docs/requirements.txt +1 -1
  17. {exeplot-0.5.2 → exeplot-0.5.5}/pyproject.toml +4 -0
  18. exeplot-0.5.5/requirements.txt +11 -0
  19. exeplot-0.5.5/src/exeplot/VERSION.txt +1 -0
  20. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/__conf__.py +14 -8
  21. exeplot-0.5.5/src/exeplot/__init__.py +9 -0
  22. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/__main__.py +4 -1
  23. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/plots/__common__.py +11 -8
  24. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/plots/diff.py +1 -1
  25. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/plots/entropy.py +4 -4
  26. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/plots/graph.py +5 -3
  27. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/utils.py +16 -12
  28. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot.egg-info/PKG-INFO +8 -4
  29. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot.egg-info/SOURCES.txt +9 -2
  30. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot.egg-info/requires.txt +5 -0
  31. {exeplot-0.5.2 → exeplot-0.5.5}/tests/test_others.py +4 -5
  32. exeplot-0.5.2/.github/workflows/python-package.yml +0 -109
  33. exeplot-0.5.2/docs/pages/css/extra.css +0 -26
  34. exeplot-0.5.2/docs/pages/index.md +0 -12
  35. exeplot-0.5.2/requirements.txt +0 -2
  36. exeplot-0.5.2/src/exeplot/VERSION.txt +0 -1
  37. exeplot-0.5.2/src/exeplot/__init__.py +0 -5
  38. {exeplot-0.5.2 → exeplot-0.5.5}/.coveragerc +0 -0
  39. {exeplot-0.5.2 → exeplot-0.5.5}/.gitignore +0 -0
  40. {exeplot-0.5.2 → exeplot-0.5.5}/LICENSE +0 -0
  41. {exeplot-0.5.2 → exeplot-0.5.5}/_config.yml +0 -0
  42. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/calc_orig_entropy.png +0 -0
  43. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/calc_packed_byte.png +0 -0
  44. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/calc_packed_byte2.png +0 -0
  45. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/calc_packed_entropy.png +0 -0
  46. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/calc_packed_nested_pie.png +0 -0
  47. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/calc_packed_pie.png +0 -0
  48. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/icon.png +0 -0
  49. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/logo.png +0 -0
  50. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/upx_calc_byte.png +0 -0
  51. {exeplot-0.5.2 → exeplot-0.5.5}/docs/pages/img/upx_calc_entropy.png +0 -0
  52. {exeplot-0.5.2 → exeplot-0.5.5}/pytest.ini +0 -0
  53. {exeplot-0.5.2 → exeplot-0.5.5}/setup.cfg +0 -0
  54. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/__info__.py +0 -0
  55. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/plots/__init__.py +0 -0
  56. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/plots/byte.py +0 -0
  57. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/plots/nested_pie.py +0 -0
  58. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot/plots/pie.py +0 -0
  59. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot.egg-info/dependency_links.txt +0 -0
  60. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot.egg-info/entry_points.txt +0 -0
  61. {exeplot-0.5.2 → exeplot-0.5.5}/src/exeplot.egg-info/top_level.txt +0 -0
  62. {exeplot-0.5.2 → exeplot-0.5.5}/tests/__init__.py +0 -0
  63. {exeplot-0.5.2 → exeplot-0.5.5}/tests/hello.elf +0 -0
  64. {exeplot-0.5.2 → exeplot-0.5.5}/tests/hello.exe +0 -0
  65. {exeplot-0.5.2 → exeplot-0.5.5}/tests/hello.macho +0 -0
  66. {exeplot-0.5.2 → exeplot-0.5.5}/tests/test_plots.py +0 -0
@@ -0,0 +1,15 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: github-actions
4
+ directory: /
5
+ schedule:
6
+ interval: monthly
7
+ groups:
8
+ actions:
9
+ patterns: ["*"]
10
+ - package-ecosystem: pip
11
+ directory: /
12
+ schedule:
13
+ interval: monthly
14
+ # dependencies are minimum versions (>=) ; only open security updates, not routine upgrades
15
+ open-pull-requests-limit: 0
@@ -0,0 +1,142 @@
1
+ # This workflow will install Python dependencies, run tests and lint with a variety of Python versions
2
+ # For more information see: https://docs.github.com/en/actions/automating-builds-and-tests/building-and-testing-python
3
+
4
+ name: build
5
+
6
+ on:
7
+ push:
8
+ branches: [ "main" ]
9
+ pull_request:
10
+ branches: [ "main" ]
11
+
12
+ permissions:
13
+ contents: read
14
+
15
+ jobs:
16
+ prepare:
17
+ runs-on: ubuntu-latest
18
+ outputs:
19
+ package: ${{ steps.pkg.outputs.package }}
20
+ pypi_url: ${{ steps.pkg.outputs.pypi_url }}
21
+ steps:
22
+ - name: Compute package name from the repository's
23
+ id: pkg
24
+ run: |
25
+ name="${GITHUB_REPOSITORY##*/}"
26
+ echo "package=${name#python-}" >> $GITHUB_OUTPUT
27
+ echo "pypi_url=https://pypi.org/p/${name#python-}" >> $GITHUB_OUTPUT
28
+ build:
29
+ needs: prepare
30
+ runs-on: ${{ matrix.os }}
31
+ strategy:
32
+ fail-fast: false
33
+ matrix:
34
+ os: [ubuntu-latest]
35
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
36
+ env:
37
+ package: ${{ needs.prepare.outputs.package }}
38
+ cov_python_version: "3.13"
39
+ steps:
40
+ - uses: actions/checkout@v5
41
+ - name: Set up Python ${{ matrix.python-version }}
42
+ uses: actions/setup-python@v6
43
+ with:
44
+ python-version: ${{ matrix.python-version }}
45
+ - name: Install ${{ env.package }}
46
+ run: |
47
+ sudo apt-get update
48
+ sudo apt-get install -y graphviz libgraphviz-dev
49
+ python -m pip install --upgrade pip
50
+ python -m pip install pytest pytest-cov
51
+ pip install -r requirements.txt
52
+ pip install .
53
+ - name: Test ${{ env.package }} with pytest
54
+ run: |
55
+ pytest --cov=$package --cov-report=xml
56
+ - name: Upload coverage report
57
+ if: matrix.python-version == env.cov_python_version
58
+ uses: actions/upload-artifact@v7
59
+ with:
60
+ name: coverage-report
61
+ path: coverage.xml
62
+ coverage:
63
+ # only publish the badge for commits on main (not for pull requests)
64
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
65
+ needs: build
66
+ permissions:
67
+ contents: write
68
+ runs-on: ubuntu-latest
69
+ env:
70
+ cov_badge_path: docs/coverage.svg
71
+ steps:
72
+ - uses: actions/checkout@v5
73
+ - name: Set up Python
74
+ uses: actions/setup-python@v6
75
+ with:
76
+ python-version: "3.13"
77
+ - name: Download coverage report
78
+ uses: actions/download-artifact@v8
79
+ with:
80
+ name: coverage-report
81
+ - name: Make coverage badge
82
+ run: |
83
+ pip install genbadge[coverage]
84
+ genbadge coverage -i coverage.xml -o $cov_badge_path
85
+ - name: Push coverage badge
86
+ run: |
87
+ # keep the badge alone on an orphan branch so that main is never modified by the workflow
88
+ git config --local user.email "github-actions[bot]@users.noreply.github.com"
89
+ git config --local user.name "github-actions[bot]"
90
+ if git fetch --depth=1 origin coverage-badge 2>/dev/null && \
91
+ git show FETCH_HEAD:$cov_badge_path | cmp -s - $cov_badge_path; then
92
+ echo "Coverage badge unchanged"
93
+ exit 0
94
+ fi
95
+ git checkout --orphan coverage-badge
96
+ git rm -rqf --cached .
97
+ git add $cov_badge_path
98
+ git commit -m "Update coverage badge"
99
+ git push origin coverage-badge --force
100
+ deploy:
101
+ # only release from main, never from pull requests
102
+ if: github.event_name == 'push' && github.ref == 'refs/heads/main'
103
+ environment:
104
+ name: pypi
105
+ url: ${{ needs.prepare.outputs.pypi_url }}
106
+ permissions:
107
+ contents: read
108
+ id-token: write # for PyPI trusted publishing (OIDC)
109
+ runs-on: ubuntu-latest
110
+ needs: [prepare, build]
111
+ env:
112
+ package: ${{ needs.prepare.outputs.package }}
113
+ steps:
114
+ - uses: actions/checkout@v5
115
+ - name: Check whether the version is already on PyPI
116
+ # comparing with PyPI (not with the previous commit) also releases a version whose push did not trigger a deploy
117
+ id: version
118
+ run: |
119
+ version=$(tr -d '[:space:]' < src/$package/VERSION.txt)
120
+ status=$(curl -s -o /dev/null -w '%{http_code}' --retry 3 "https://pypi.org/pypi/$package/$version/json")
121
+ case "$status" in
122
+ 200) echo "Version $version is already on PyPI" ; echo "new=false" >> "$GITHUB_OUTPUT" ;;
123
+ 404) echo "Version $version is not on PyPI yet" ; echo "new=true" >> "$GITHUB_OUTPUT" ;;
124
+ *) echo "::error::Unexpected HTTP status $status from PyPI" ; exit 1 ;;
125
+ esac
126
+ - if: steps.version.outputs.new == 'true'
127
+ name: Set up Python
128
+ uses: actions/setup-python@v6
129
+ with:
130
+ python-version: "3.13"
131
+ - if: steps.version.outputs.new == 'true'
132
+ name: Cleanup README
133
+ run: |
134
+ sed -ri 's/^(##*)\s*:.*:\s*/\1 /g' README.md
135
+ awk '{if (match($0,"## Supporters")) exit; print}' README.md > README
136
+ mv -f README README.md
137
+ - if: steps.version.outputs.new == 'true'
138
+ name: Build ${{ needs.prepare.outputs.package }} package
139
+ run: python -m pip install --upgrade build && python -m build
140
+ - if: steps.version.outputs.new == 'true'
141
+ name: Publish to PyPI
142
+ uses: pypa/gh-action-pypi-publish@release/v1
@@ -0,0 +1,31 @@
1
+ # This workflow audits the package dependencies for known vulnerabilities
2
+ # It is separate from python-package.yml so that a new advisory never blocks a release
3
+
4
+ name: security
5
+
6
+ on:
7
+ push:
8
+ branches: [ "main" ]
9
+ pull_request:
10
+ branches: [ "main" ]
11
+ schedule:
12
+ - cron: "0 6 * * 1" # weekly, catches new advisories between pushes
13
+ workflow_dispatch:
14
+
15
+ permissions:
16
+ contents: read
17
+
18
+ jobs:
19
+ pip-audit:
20
+ runs-on: ubuntu-latest
21
+ steps:
22
+ - uses: actions/checkout@v7
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v7
25
+ with:
26
+ python-version: "3.13"
27
+ - name: Install pip-audit
28
+ run: python -m pip install --upgrade pip pip-audit
29
+ - name: Audit dependencies
30
+ # resolves the dependencies of pyproject.toml in an isolated environment, so only these are audited
31
+ run: pip-audit .
@@ -1,7 +1,7 @@
1
1
  version: 2
2
2
 
3
3
  build:
4
- os: "ubuntu-24.04"
4
+ os: ubuntu-24.04
5
5
  tools:
6
6
  python: "3.13"
7
7
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: exeplot
3
- Version: 0.5.2
3
+ Version: 0.5.5
4
4
  Summary: Library for plotting executable samples supporting multiple formats
5
5
  Author-email: Alexandre D'Hondt <alexandre.dhondt@gmail.com>
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -696,22 +696,25 @@ Requires-Dist: lief>=0.16.1
696
696
  Requires-Dist: matplotlib
697
697
  Provides-Extra: graph
698
698
  Requires-Dist: angr>=9.2; extra == "graph"
699
+ Requires-Dist: bitstring<5; python_version < "3.12" and extra == "graph"
700
+ Requires-Dist: pycparser<3.12; python_version < "3.12" and extra == "graph"
699
701
  Requires-Dist: networkx>=3.4.2; extra == "graph"
700
702
  Requires-Dist: numpy; extra == "graph"
701
703
  Requires-Dist: pygraphviz>=1.14; extra == "graph"
704
+ Requires-Dist: scipy; extra == "graph"
702
705
  Requires-Dist: unicorn>2; extra == "graph"
703
706
  Dynamic: license-file
704
707
 
705
708
  <p align="center" id="top"><img src="https://github.com/packing-box/python-exeplot/raw/main/docs/pages/img/logo.png"></p>
706
709
  <h1 align="center">ExePlot <a href="https://twitter.com/intent/tweet?text=ExePlot%20-%20Plot%20executable%20samples%20easy.%0D%0ALibrary%20for%20plotting%20executable%20samples%20supporting%20multiple%20formats.%0D%0Ahttps%3a%2f%2fgithub%2ecom%2fpacking-box%2fpython-exeplot%0D%0A&hashtags=python,programming,executable-samples,plot"><img src="https://img.shields.io/badge/Tweet--lightgrey?logo=twitter&style=social" alt="Tweet" height="20"/></a></h1>
707
- <h3 align="center">Search for samples from various malware databases.</h3>
710
+ <h3 align="center">Plot executable samples easy.</h3>
708
711
 
709
712
  [![PyPi](https://img.shields.io/pypi/v/exeplot.svg)](https://pypi.python.org/pypi/exeplot/)
710
713
  [![Read The Docs](https://readthedocs.org/projects/python-exeplot/badge/?version=latest)](https://python-exeplot.readthedocs.io/en/latest/?badge=latest)
711
714
  [![Build Status](https://github.com/packing-box/python-exeplot/actions/workflows/python-package.yml/badge.svg)](https://github.com/packing-box/python-exeplot/actions/workflows/python-package.yml)
712
- [![Coverage Status](https://raw.githubusercontent.com/packing-box/python-exeplot/main/docs/coverage.svg)](#)
715
+ [![Security](https://github.com/packing-box/python-exeplot/actions/workflows/security.yml/badge.svg)](https://github.com/packing-box/python-exeplot/actions/workflows/security.yml)
716
+ [![Coverage Status](https://raw.githubusercontent.com/packing-box/python-exeplot/coverage-badge/docs/coverage.svg)](#)
713
717
  [![Python Versions](https://img.shields.io/pypi/pyversions/exeplot.svg)](https://pypi.python.org/pypi/exeplot/)
714
- [![Known Vulnerabilities](https://snyk.io/test/github/packing-box/python-exeplot/badge.svg?targetFile=requirements.txt)](https://snyk.io/test/github/packing-box/python-exeplot?targetFile=requirements.txt)
715
718
  [![License](https://img.shields.io/pypi/l/exeplot.svg)](https://pypi.python.org/pypi/exeplot/)
716
719
 
717
720
  This library implements multiple plot types for illustrating executable samples. It currently supports the PE, ELF and Mach-O formats, relying on [`lief`](https://github.com/lief-project/LIEF) for abstracting them.
@@ -771,3 +774,4 @@ $ exeplot entropy calc_packed.exe --no-title --no-legend --no-label --no-entrypo
771
774
  ![Simplified entropy plot of `calc_packed.exe`](https://github.com/packing-box/python-exeplot/blob/main/docs/pages/img/calc_packed_entropy.png?raw=true)
772
775
 
773
776
 
777
+ <p align="center"><a href="#top"><img src="https://img.shields.io/badge/Back%20to%20top--lightgrey?style=social" alt="Back to top" height="20"/></a></p>
@@ -1,13 +1,13 @@
1
1
  <p align="center" id="top"><img src="https://github.com/packing-box/python-exeplot/raw/main/docs/pages/img/logo.png"></p>
2
2
  <h1 align="center">ExePlot <a href="https://twitter.com/intent/tweet?text=ExePlot%20-%20Plot%20executable%20samples%20easy.%0D%0ALibrary%20for%20plotting%20executable%20samples%20supporting%20multiple%20formats.%0D%0Ahttps%3a%2f%2fgithub%2ecom%2fpacking-box%2fpython-exeplot%0D%0A&hashtags=python,programming,executable-samples,plot"><img src="https://img.shields.io/badge/Tweet--lightgrey?logo=twitter&style=social" alt="Tweet" height="20"/></a></h1>
3
- <h3 align="center">Search for samples from various malware databases.</h3>
3
+ <h3 align="center">Plot executable samples easy.</h3>
4
4
 
5
5
  [![PyPi](https://img.shields.io/pypi/v/exeplot.svg)](https://pypi.python.org/pypi/exeplot/)
6
6
  [![Read The Docs](https://readthedocs.org/projects/python-exeplot/badge/?version=latest)](https://python-exeplot.readthedocs.io/en/latest/?badge=latest)
7
7
  [![Build Status](https://github.com/packing-box/python-exeplot/actions/workflows/python-package.yml/badge.svg)](https://github.com/packing-box/python-exeplot/actions/workflows/python-package.yml)
8
- [![Coverage Status](https://raw.githubusercontent.com/packing-box/python-exeplot/main/docs/coverage.svg)](#)
8
+ [![Security](https://github.com/packing-box/python-exeplot/actions/workflows/security.yml/badge.svg)](https://github.com/packing-box/python-exeplot/actions/workflows/security.yml)
9
+ [![Coverage Status](https://raw.githubusercontent.com/packing-box/python-exeplot/coverage-badge/docs/coverage.svg)](#)
9
10
  [![Python Versions](https://img.shields.io/pypi/pyversions/exeplot.svg)](https://pypi.python.org/pypi/exeplot/)
10
- [![Known Vulnerabilities](https://snyk.io/test/github/packing-box/python-exeplot/badge.svg?targetFile=requirements.txt)](https://snyk.io/test/github/packing-box/python-exeplot?targetFile=requirements.txt)
11
11
  [![License](https://img.shields.io/pypi/l/exeplot.svg)](https://pypi.python.org/pypi/exeplot/)
12
12
 
13
13
  This library implements multiple plot types for illustrating executable samples. It currently supports the PE, ELF and Mach-O formats, relying on [`lief`](https://github.com/lief-project/LIEF) for abstracting them.
@@ -67,3 +67,4 @@ $ exeplot entropy calc_packed.exe --no-title --no-legend --no-label --no-entrypo
67
67
  ![Simplified entropy plot of `calc_packed.exe`](https://github.com/packing-box/python-exeplot/blob/main/docs/pages/img/calc_packed_entropy.png?raw=true)
68
68
 
69
69
 
70
+ <p align="center"><a href="#top"><img src="https://img.shields.io/badge/Back%20to%20top--lightgrey?style=social" alt="Back to top" height="20"/></a></p>
@@ -0,0 +1,17 @@
1
+ # Security Policy
2
+
3
+ ## Supported Versions
4
+
5
+ Only the latest release of ExePlot (`exeplot` on [PyPI](https://pypi.org/project/exeplot/)) receives security fixes.
6
+
7
+ ## Reporting a Vulnerability
8
+
9
+ Please do **not** report security vulnerabilities through public GitHub issues.
10
+
11
+ Instead, report them privately through [GitHub's private vulnerability reporting](https://github.com/packing-box/python-exeplot/security/advisories/new) (the repository's *Security* tab, then *Report a vulnerability*). Please include:
12
+
13
+ - the ExePlot version (`exeplot --help` prints it);
14
+ - the steps to reproduce the issue, and a sample (or its hash) if relevant;
15
+ - the impact you expect.
16
+
17
+ You will get an answer as soon as possible. Once the issue is confirmed, a fix is released and the advisory is published.
@@ -1 +1 @@
1
- <svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage: 96.54%"><title>coverage: 96.54%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="114" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="53" height="20" fill="#4c1"/><rect width="114" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="865" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">96.54%</text><text x="865" y="140" transform="scale(.1)" fill="#fff" textLength="430">96.54%</text></g></svg>
1
+ <svg xmlns="http://www.w3.org/2000/svg" width="114" height="20" role="img" aria-label="coverage: 96.64%"><title>coverage: 96.64%</title><linearGradient id="s" x2="0" y2="100%"><stop offset="0" stop-color="#bbb" stop-opacity=".1"/><stop offset="1" stop-opacity=".1"/></linearGradient><clipPath id="r"><rect width="114" height="20" rx="3" fill="#fff"/></clipPath><g clip-path="url(#r)"><rect width="61" height="20" fill="#555"/><rect x="61" width="53" height="20" fill="#4c1"/><rect width="114" height="20" fill="url(#s)"/></g><g fill="#fff" text-anchor="middle" font-family="Verdana,Geneva,DejaVu Sans,sans-serif" text-rendering="geometricPrecision" font-size="110"><text aria-hidden="true" x="315" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="510">coverage</text><text x="315" y="140" transform="scale(.1)" fill="#fff" textLength="510">coverage</text><text aria-hidden="true" x="865" y="150" fill="#010101" fill-opacity=".3" transform="scale(.1)" textLength="430">96.64%</text><text x="865" y="140" transform="scale(.1)" fill="#fff" textLength="430">96.64%</text></g></svg>
@@ -1,10 +1,19 @@
1
1
  site_author: dhondta
2
- site_name: "MalSearch - A library for getting samples from multiple malware databases"
3
- repo_url: https://github.com/packing-box/python-malsearch
2
+ site_name: ExePlot
3
+ site_description: Library for plotting executable samples supporting multiple formats
4
+ site_url: https://python-exeplot.readthedocs.io
5
+ repo_url: https://github.com/packing-box/python-exeplot
6
+ edit_uri: edit/main/docs/pages/
4
7
  copyright: Copyright &copy; 2024 Alexandre D'Hondt
5
8
  docs_dir: pages
6
9
  nav:
7
- - Introduction: index.md
10
+ - Home: index.md
11
+ - Installation: installation.md
12
+ - Command-line tool:
13
+ - exeplot: cli/exeplot.md
14
+ - Python API: api.md
15
+ - How it works: internals.md
16
+ - Contributing: contributing.md
8
17
  extra:
9
18
  generator: false
10
19
  social:
@@ -20,23 +29,33 @@ extra:
20
29
  - icon: fontawesome/brands/twitter
21
30
  link: https://twitter.com/alex_dhondt
22
31
  name: Alex on Twitter
23
- extra_css:
24
- - css/extra.css
25
32
  theme:
26
33
  name: material
34
+ logo: img/logo.png
35
+ favicon: img/icon.png
27
36
  palette:
28
37
  - scheme: default
29
38
  toggle:
30
- icon: material/brightness-7
39
+ icon: material/brightness-7
31
40
  name: Switch to dark mode
32
41
  - scheme: slate
33
42
  toggle:
34
43
  icon: material/brightness-4
35
44
  name: Switch to light mode
36
- logo: img/logo.png
37
- favicon: img/icon.png
45
+ features:
46
+ - content.code.copy
47
+ - navigation.sections
48
+ - navigation.top
49
+ - toc.follow
38
50
  use_directory_urls: false
39
51
  markdown_extensions:
52
+ - admonition
53
+ - attr_list
54
+ - def_list
55
+ - pymdownx.details
56
+ - pymdownx.highlight
57
+ - pymdownx.inlinehilite
58
+ - pymdownx.superfences
59
+ - tables
40
60
  - toc:
41
61
  permalink: true
42
- - admonition
@@ -0,0 +1,190 @@
1
+ # Python API
2
+
3
+ The `exeplot` package exposes one function per plot type:
4
+
5
+ ```python
6
+ from exeplot import byte, diff, entropy, graph, nested_pie, pie
7
+ ```
8
+
9
+ `exeplot.__all__` lists the plot types that are available. `graph` is only
10
+ there when its [extra](installation.md#the-graph-extra) is installed.
11
+
12
+ Every function draws the plot, saves it and returns the **list of saved
13
+ image paths**:
14
+
15
+ ```python
16
+ >>> from exeplot import pie
17
+ >>> pie("calc_packed.exe", donut=True, img_format="svg")
18
+ ['calc_packed_pie.svg']
19
+ ```
20
+
21
+ ---
22
+
23
+ ## Common keyword arguments
24
+
25
+ All plot functions accept these keyword arguments, on top of their own:
26
+
27
+ | Argument | Default | Description |
28
+ |---|---|---|
29
+ | `no_title` | `False` | Do not display the title. |
30
+ | `no_legend` | `False` | Do not display the legend. |
31
+ | `img_name` | `<name>_<plot>` | Path of the image, with or without its extension. Missing folders are created. |
32
+ | `img_format` | `png` | Image format and file extension. |
33
+ | `dpi` | `300` | Resolution of the image. |
34
+ | `transparent` | `False` | Save with a transparent background. |
35
+ | `bbox_inches` | `"tight"` | Bounding box of the saved figure. |
36
+ | `grayscale` | `False` | Use the `gray` colormap instead of `colormap_main`. |
37
+ | `interactive_mode` | `False` | Open a Python console before saving (see [Interactive mode](cli/exeplot.md#common-options)). |
38
+
39
+ The defaults come from the [configuration file](cli/exeplot.md#configuration-file)
40
+ when it sets them.
41
+
42
+ ### Fonts
43
+
44
+ `font_family` and `font_size` set the base font. Each text element can then
45
+ be changed with `<element>_font_family`, `<element>_font_size` and
46
+ `<element>_font_weight`, where `<element>` is one of:
47
+
48
+ | Element | Default size | Default weight | Used for |
49
+ |---|---|---|---|
50
+ | `title` | 1.6 × `font_size` | `bold` | The title. |
51
+ | `suptitle` | 1.2 × `font_size` | `normal` | The subtitle. |
52
+ | `annotation` | 0.5 × `font_size` | `normal` | The hash under the title. |
53
+ | `xlabel`, `ylabel` | `font_size` | `normal` | Axis labels and pie percentages. |
54
+
55
+ ```python
56
+ entropy("a.exe", title_font_size=20, title_font_weight="normal")
57
+ ```
58
+
59
+ ---
60
+
61
+ ## `byte`
62
+
63
+ ```python
64
+ byte(executable, height=600, grayscale=False, **kwargs)
65
+ ```
66
+
67
+ | Parameter | Description |
68
+ |---|---|
69
+ | `executable` | Path to the executable. |
70
+ | `height` | Height of the image, in pixels. |
71
+ | `grayscale` | One byte per gray pixel, instead of three bytes per RGB pixel. |
72
+
73
+ ---
74
+
75
+ ## `entropy`
76
+
77
+ ```python
78
+ entropy(*filenames, labels=None, sublabel=None, scale=False, target=None, **kwargs)
79
+ ```
80
+
81
+ | Parameter | Description |
82
+ |---|---|
83
+ | `*filenames` | Paths to one or more executables. At least one is required (`ValueError` otherwise). |
84
+ | `labels` | One label per file. Each item is a string, or a function that takes the [data dictionary](#entropy-data) of the file and returns a string. |
85
+ | `sublabel` | Text under each label: a key of `exeplot.plots.__common__.SUBLABELS` (`"ep"`, `"size"`, `"size-ep"`, `"size-ent"`, `"size-ep-ent"`), or a function of the data dictionary. `None` (the default here, unlike the CLI) shows no sublabel. Sublabels that mention the entry point are skipped for files without one. |
86
+ | `scale` | Draw every file on the scale of the first one. |
87
+ | `target` | Name shown in the title, instead of the first file name. |
88
+ | `n_samples` | Number of entropy samples per file (default `2048`). |
89
+ | `legend_location` | Matplotlib location of the legend (default `"lower center"`). A location ending with `left` or `right` puts the legend on one column, beside the plot. |
90
+ | `no_entrypoint` | Do not display the entry point. |
91
+ | `no_label` | Do not display the labels, sublabels and section names. |
92
+
93
+ ```python
94
+ entropy("calc_orig.exe", "calc_packed.exe", scale=True,
95
+ labels=["Original", lambda d: f"Packed ({d['type']})"], sublabel="size-ent")
96
+ ```
97
+
98
+ ### Entropy data
99
+
100
+ `labels` and `sublabel` functions receive the dictionary returned by
101
+ `exeplot.plots.entropy.data(executable)`:
102
+
103
+ | Key | Description |
104
+ |---|---|
105
+ | `name`, `hash`, `size`, `type` | File name, SHA-256, size in bytes and format (`PE`, `ELF` or `MachO`). |
106
+ | `entropy` | The entropy samples, divided by 8 (so from 0 to 1). |
107
+ | `entropy*` | The entropy of the whole file, in bits per byte. |
108
+ | `ep` | `(position on the plot, file offset, section name)` of the entry point, or `None`. |
109
+ | `sections` | `(start, end, name, average entropy)` tuples, in samples. |
110
+
111
+ ---
112
+
113
+ ## `pie`
114
+
115
+ ```python
116
+ pie(executable, donut=False, **kwargs)
117
+ ```
118
+
119
+ | Parameter | Description |
120
+ |---|---|
121
+ | `executable` | Path to the executable. |
122
+ | `donut` | Draw a donut instead of a pie. |
123
+ | `no_label` | Do not display the percentages. |
124
+
125
+ ---
126
+
127
+ ## `nested_pie`
128
+
129
+ ```python
130
+ nested_pie(executable, **kwargs)
131
+ ```
132
+
133
+ | Parameter | Description |
134
+ |---|---|
135
+ | `executable` | Path to the executable. |
136
+
137
+ ---
138
+
139
+ ## `diff`
140
+
141
+ ```python
142
+ diff(executable, executable2, legend1="", legend2="", **kwargs)
143
+ ```
144
+
145
+ | Parameter | Description |
146
+ |---|---|
147
+ | `executable` | Path to the reference executable. |
148
+ | `executable2` | Path to the modified executable. Both must have the same format (`ValueError` otherwise). |
149
+ | `legend1`, `legend2` | Labels of the two bars. The file names are used when empty. |
150
+ | `no_colormap` | Do not display the color bar. `no_colorbar` is accepted too. |
151
+
152
+ ---
153
+
154
+ ## `graph`
155
+
156
+ ```python
157
+ graph(executable, algorithm="fast", engine="default", **kwargs)
158
+ ```
159
+
160
+ | Parameter | Description |
161
+ |---|---|
162
+ | `executable` | Path to the executable. |
163
+ | `algorithm` | `"fast"` (`CFGFast`) or `"emulated"` (`CFGEmulated`). |
164
+ | `engine` | `"default"`, `"pcode"` or `"vex"`. |
165
+
166
+ ---
167
+
168
+ ## Utilities: `exeplot.utils`
169
+
170
+ ```python
171
+ from exeplot.utils import ensure_str, human_readable_size, ngrams_counts, ngrams_distribution, shannon_entropy
172
+ ```
173
+
174
+ | Function | Description |
175
+ |---|---|
176
+ | `shannon_entropy(data)` | Shannon entropy of a byte string, in bits per byte (0 to 8). |
177
+ | `human_readable_size(size, precision=0)` | Formats a size in bytes, for example `human_readable_size(1536, 1)` gives `"1.5KB"`. |
178
+ | `ensure_str(s, encoding="utf-8", errors="strict")` | Decodes `bytes`, falling back to Latin-1. Raises `TypeError` for other types. |
179
+ | `ngrams_counts(byte_obj, n=1, step=1)` | Sorted list of `(n-gram, count)` pairs, for `n` from 1 to 3. `byte_obj` is a byte string, or an object with a `bytes` attribute, whose result is then cached on the object. |
180
+ | `ngrams_distribution(byte_obj, n=1, step=1, n_most_common=None, n_exclude_top=0, exclude=None)` | Like `ngrams_counts`, keeping the `n_most_common` n-grams after leaving out the `n_exclude_top` most common ones and the n-grams in `exclude`. |
181
+
182
+ ---
183
+
184
+ ## Constants
185
+
186
+ | Name | Description |
187
+ |---|---|
188
+ | `exeplot.__version__` | Package version, read from `VERSION.txt`. |
189
+ | `exeplot.config` | The plot style options (see the [configuration file](cli/exeplot.md#configuration-file)). It is updated from `~/.exeplot.conf` before each plot. |
190
+ | `exeplot.logger` | The `exeplot` logger. |