ghidra-decomp 0.2.0__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.
- ghidra_decomp-0.2.0/.gitattributes +2 -0
- ghidra_decomp-0.2.0/.github/workflows/ci.yml +32 -0
- ghidra_decomp-0.2.0/.github/workflows/publish.yml +19 -0
- ghidra_decomp-0.2.0/.gitignore +15 -0
- ghidra_decomp-0.2.0/LICENSE +21 -0
- ghidra_decomp-0.2.0/PKG-INFO +124 -0
- ghidra_decomp-0.2.0/README.md +99 -0
- ghidra_decomp-0.2.0/pyproject.toml +42 -0
- ghidra_decomp-0.2.0/src/ghidra_decomp/__init__.py +3 -0
- ghidra_decomp-0.2.0/src/ghidra_decomp/__main__.py +5 -0
- ghidra_decomp-0.2.0/src/ghidra_decomp/cli.py +128 -0
- ghidra_decomp-0.2.0/src/ghidra_decomp/decompiler.py +781 -0
- ghidra_decomp-0.2.0/tests/fixtures/sample +0 -0
- ghidra_decomp-0.2.0/tests/fixtures/sample.c +89 -0
- ghidra_decomp-0.2.0/tests/test_e2e.py +369 -0
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
lint:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- uses: actions/setup-python@v5
|
|
15
|
+
with:
|
|
16
|
+
python-version: "3.12"
|
|
17
|
+
- run: pip install ruff
|
|
18
|
+
- run: ruff check src/ tests/
|
|
19
|
+
- run: ruff format --check src/ tests/
|
|
20
|
+
|
|
21
|
+
typecheck:
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v4
|
|
25
|
+
- uses: actions/setup-python@v5
|
|
26
|
+
with:
|
|
27
|
+
python-version: "3.12"
|
|
28
|
+
- run: pip install click mypy
|
|
29
|
+
- run: mypy src/ghidra_decomp/ --ignore-missing-imports
|
|
30
|
+
|
|
31
|
+
# Note: e2e tests require a Ghidra installation and are not run in CI.
|
|
32
|
+
# Run them locally with: pytest tests/
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: actions/setup-python@v5
|
|
13
|
+
with:
|
|
14
|
+
python-version: "3.12"
|
|
15
|
+
- run: pip install build
|
|
16
|
+
- run: python -m build
|
|
17
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
18
|
+
with:
|
|
19
|
+
password: ${{ secrets.PYPI_API_TOKEN }}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 totekuh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: ghidra-decomp
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Bulk-decompile binaries via Ghidra into a browsable source tree
|
|
5
|
+
Project-URL: Homepage, https://github.com/totekuh/ghidra-decomp
|
|
6
|
+
Project-URL: Repository, https://github.com/totekuh/ghidra-decomp
|
|
7
|
+
Project-URL: Issues, https://github.com/totekuh/ghidra-decomp/issues
|
|
8
|
+
Author-email: totekuh <totekuh@protonmail.com>
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Operating System :: OS Independent
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
19
|
+
Classifier: Topic :: Security
|
|
20
|
+
Classifier: Topic :: Software Development :: Disassemblers
|
|
21
|
+
Requires-Python: >=3.10
|
|
22
|
+
Requires-Dist: click
|
|
23
|
+
Requires-Dist: pyghidra
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# ghidra-decomp
|
|
27
|
+
|
|
28
|
+
Bulk-decompile binaries into browsable source trees using Ghidra.
|
|
29
|
+
|
|
30
|
+
Takes a binary, runs Ghidra's decompiler on every function, and produces a directory of `.c` files and JSON indexes — ready for grep, code review, or AI-assisted analysis.
|
|
31
|
+
|
|
32
|
+
## Why
|
|
33
|
+
|
|
34
|
+
Reverse engineering through Ghidra's GUI (or MCP) means looking at one function at a time. This tool dumps everything upfront so you can treat the binary like a normal codebase: grep for patterns, read call graphs, search strings — all without waiting for decompilation round-trips.
|
|
35
|
+
|
|
36
|
+
## Install
|
|
37
|
+
|
|
38
|
+
Requires [Ghidra](https://ghidra-sre.org/) 11.0+ (which bundles pyghidra).
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
pip install -e .
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Set `GHIDRA_INSTALL_DIR` to your Ghidra installation, or pass `--ghidra-path`.
|
|
45
|
+
|
|
46
|
+
## Usage
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
ghidra-decomp ./firmware.bin -o ./firmware_decomp
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
Options:
|
|
53
|
+
|
|
54
|
+
| Flag | Description | Default |
|
|
55
|
+
|------|-------------|---------|
|
|
56
|
+
| `-o, --output` | Output directory | `<binary>_decomp/` |
|
|
57
|
+
| `--timeout` | Per-function decompilation timeout (seconds) | 60 |
|
|
58
|
+
| `--ghidra-path` | Path to Ghidra install | `$GHIDRA_INSTALL_DIR` |
|
|
59
|
+
| `--base-addr` | Rebase binary to this address before analysis (e.g. `0x80000000`) | none |
|
|
60
|
+
| `--entry` | Mark this address as the entry point and disassemble from it before analysis (e.g. `0x31000`). Useful for raw binaries. | none |
|
|
61
|
+
| `--language` | Force Ghidra language ID (e.g. `ARM:LE:32:v7`). Use when auto-detect fails. | auto |
|
|
62
|
+
| `--compiler` | Force compiler spec ID (e.g. `gcc`, `default`, `windows`). Requires `--language`. | auto |
|
|
63
|
+
| `--list-languages` | List all available language IDs and compiler specs, then exit. | |
|
|
64
|
+
|
|
65
|
+
For raw binaries or unknown formats, Ghidra will refuse to auto-load. Discover the right spec then pass it:
|
|
66
|
+
|
|
67
|
+
```bash
|
|
68
|
+
ghidra-decomp --list-languages | grep -i arm
|
|
69
|
+
ghidra-decomp ./firmware.bin --language ARM:LE:32:v7 --compiler default
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Raw binaries typically also need a known image base and an entry point for auto-analysis to reach every function. Both are applied *before* analysis runs, so function boundaries, xrefs, and switch-table recovery all happen at the real addresses:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
ghidra-decomp ./dal_ivm.mod \
|
|
76
|
+
--language x86:LE:32:default \
|
|
77
|
+
--compiler gcc \
|
|
78
|
+
--base-addr 0x00031000 \
|
|
79
|
+
--entry 0x00031000
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
## Output
|
|
83
|
+
|
|
84
|
+
```
|
|
85
|
+
firmware_decomp/
|
|
86
|
+
├── functions/
|
|
87
|
+
│ ├── 00010000_main.c
|
|
88
|
+
│ ├── 00010234_parse_config.c
|
|
89
|
+
│ └── ...
|
|
90
|
+
├── all_functions.c # everything in one file
|
|
91
|
+
├── types.json # recovered structs, enums, unions, typedefs
|
|
92
|
+
├── functions.json # function index with address ranges + signatures
|
|
93
|
+
├── callgraph.json # who calls who
|
|
94
|
+
├── strings.json # strings + xrefs to functions
|
|
95
|
+
├── imports.json # external library functions
|
|
96
|
+
├── exports.json # exported entry points
|
|
97
|
+
├── symbols.json # globals, labels, data
|
|
98
|
+
├── sections.json # memory map with r/w/x permissions
|
|
99
|
+
└── metadata.json # binary info + stats
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Each `.c` file includes a metadata header:
|
|
103
|
+
|
|
104
|
+
```c
|
|
105
|
+
// Function: parse_config
|
|
106
|
+
// Address: 00010234
|
|
107
|
+
// Size: 284 bytes
|
|
108
|
+
// Calling: __stdcall
|
|
109
|
+
// Params: 3
|
|
110
|
+
|
|
111
|
+
void parse_config(char *param_1, int param_2, int param_3) {
|
|
112
|
+
...
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
|
|
116
|
+
## Intended workflow
|
|
117
|
+
|
|
118
|
+
1. **Dump** the binary with `ghidra-decomp`
|
|
119
|
+
2. **Analyze** the output like source code — grep, glob, read
|
|
120
|
+
3. **Write back** renames/annotations to Ghidra via MCP (separate tool)
|
|
121
|
+
|
|
122
|
+
## License
|
|
123
|
+
|
|
124
|
+
MIT
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
# ghidra-decomp
|
|
2
|
+
|
|
3
|
+
Bulk-decompile binaries into browsable source trees using Ghidra.
|
|
4
|
+
|
|
5
|
+
Takes a binary, runs Ghidra's decompiler on every function, and produces a directory of `.c` files and JSON indexes — ready for grep, code review, or AI-assisted analysis.
|
|
6
|
+
|
|
7
|
+
## Why
|
|
8
|
+
|
|
9
|
+
Reverse engineering through Ghidra's GUI (or MCP) means looking at one function at a time. This tool dumps everything upfront so you can treat the binary like a normal codebase: grep for patterns, read call graphs, search strings — all without waiting for decompilation round-trips.
|
|
10
|
+
|
|
11
|
+
## Install
|
|
12
|
+
|
|
13
|
+
Requires [Ghidra](https://ghidra-sre.org/) 11.0+ (which bundles pyghidra).
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
pip install -e .
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Set `GHIDRA_INSTALL_DIR` to your Ghidra installation, or pass `--ghidra-path`.
|
|
20
|
+
|
|
21
|
+
## Usage
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
ghidra-decomp ./firmware.bin -o ./firmware_decomp
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
Options:
|
|
28
|
+
|
|
29
|
+
| Flag | Description | Default |
|
|
30
|
+
|------|-------------|---------|
|
|
31
|
+
| `-o, --output` | Output directory | `<binary>_decomp/` |
|
|
32
|
+
| `--timeout` | Per-function decompilation timeout (seconds) | 60 |
|
|
33
|
+
| `--ghidra-path` | Path to Ghidra install | `$GHIDRA_INSTALL_DIR` |
|
|
34
|
+
| `--base-addr` | Rebase binary to this address before analysis (e.g. `0x80000000`) | none |
|
|
35
|
+
| `--entry` | Mark this address as the entry point and disassemble from it before analysis (e.g. `0x31000`). Useful for raw binaries. | none |
|
|
36
|
+
| `--language` | Force Ghidra language ID (e.g. `ARM:LE:32:v7`). Use when auto-detect fails. | auto |
|
|
37
|
+
| `--compiler` | Force compiler spec ID (e.g. `gcc`, `default`, `windows`). Requires `--language`. | auto |
|
|
38
|
+
| `--list-languages` | List all available language IDs and compiler specs, then exit. | |
|
|
39
|
+
|
|
40
|
+
For raw binaries or unknown formats, Ghidra will refuse to auto-load. Discover the right spec then pass it:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
ghidra-decomp --list-languages | grep -i arm
|
|
44
|
+
ghidra-decomp ./firmware.bin --language ARM:LE:32:v7 --compiler default
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Raw binaries typically also need a known image base and an entry point for auto-analysis to reach every function. Both are applied *before* analysis runs, so function boundaries, xrefs, and switch-table recovery all happen at the real addresses:
|
|
48
|
+
|
|
49
|
+
```bash
|
|
50
|
+
ghidra-decomp ./dal_ivm.mod \
|
|
51
|
+
--language x86:LE:32:default \
|
|
52
|
+
--compiler gcc \
|
|
53
|
+
--base-addr 0x00031000 \
|
|
54
|
+
--entry 0x00031000
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Output
|
|
58
|
+
|
|
59
|
+
```
|
|
60
|
+
firmware_decomp/
|
|
61
|
+
├── functions/
|
|
62
|
+
│ ├── 00010000_main.c
|
|
63
|
+
│ ├── 00010234_parse_config.c
|
|
64
|
+
│ └── ...
|
|
65
|
+
├── all_functions.c # everything in one file
|
|
66
|
+
├── types.json # recovered structs, enums, unions, typedefs
|
|
67
|
+
├── functions.json # function index with address ranges + signatures
|
|
68
|
+
├── callgraph.json # who calls who
|
|
69
|
+
├── strings.json # strings + xrefs to functions
|
|
70
|
+
├── imports.json # external library functions
|
|
71
|
+
├── exports.json # exported entry points
|
|
72
|
+
├── symbols.json # globals, labels, data
|
|
73
|
+
├── sections.json # memory map with r/w/x permissions
|
|
74
|
+
└── metadata.json # binary info + stats
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
Each `.c` file includes a metadata header:
|
|
78
|
+
|
|
79
|
+
```c
|
|
80
|
+
// Function: parse_config
|
|
81
|
+
// Address: 00010234
|
|
82
|
+
// Size: 284 bytes
|
|
83
|
+
// Calling: __stdcall
|
|
84
|
+
// Params: 3
|
|
85
|
+
|
|
86
|
+
void parse_config(char *param_1, int param_2, int param_3) {
|
|
87
|
+
...
|
|
88
|
+
}
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
## Intended workflow
|
|
92
|
+
|
|
93
|
+
1. **Dump** the binary with `ghidra-decomp`
|
|
94
|
+
2. **Analyze** the output like source code — grep, glob, read
|
|
95
|
+
3. **Write back** renames/annotations to Ghidra via MCP (separate tool)
|
|
96
|
+
|
|
97
|
+
## License
|
|
98
|
+
|
|
99
|
+
MIT
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "ghidra-decomp"
|
|
7
|
+
dynamic = ["version"]
|
|
8
|
+
description = "Bulk-decompile binaries via Ghidra into a browsable source tree"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
requires-python = ">=3.10"
|
|
12
|
+
authors = [{name = "totekuh", email = "totekuh@protonmail.com"}]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Intended Audience :: Developers",
|
|
16
|
+
"License :: OSI Approved :: MIT License",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
"Programming Language :: Python :: 3.10",
|
|
19
|
+
"Programming Language :: Python :: 3.11",
|
|
20
|
+
"Programming Language :: Python :: 3.12",
|
|
21
|
+
"Programming Language :: Python :: 3.13",
|
|
22
|
+
"Topic :: Security",
|
|
23
|
+
"Topic :: Software Development :: Disassemblers",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"pyghidra",
|
|
27
|
+
"click",
|
|
28
|
+
]
|
|
29
|
+
|
|
30
|
+
[project.scripts]
|
|
31
|
+
ghidra-decomp = "ghidra_decomp.cli:main"
|
|
32
|
+
|
|
33
|
+
[project.urls]
|
|
34
|
+
Homepage = "https://github.com/totekuh/ghidra-decomp"
|
|
35
|
+
Repository = "https://github.com/totekuh/ghidra-decomp"
|
|
36
|
+
Issues = "https://github.com/totekuh/ghidra-decomp/issues"
|
|
37
|
+
|
|
38
|
+
[tool.hatch.build.targets.wheel]
|
|
39
|
+
packages = ["src/ghidra_decomp"]
|
|
40
|
+
|
|
41
|
+
[tool.hatch.version]
|
|
42
|
+
path = "src/ghidra_decomp/__init__.py"
|
|
@@ -0,0 +1,128 @@
|
|
|
1
|
+
"""CLI entry point for ghidra-decomp."""
|
|
2
|
+
|
|
3
|
+
import click
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from .decompiler import decompile_binary, list_languages
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
@click.command()
|
|
10
|
+
@click.argument(
|
|
11
|
+
"binary",
|
|
12
|
+
type=click.Path(exists=True, dir_okay=False, path_type=Path),
|
|
13
|
+
required=False,
|
|
14
|
+
)
|
|
15
|
+
@click.option(
|
|
16
|
+
"-o",
|
|
17
|
+
"--output",
|
|
18
|
+
type=click.Path(path_type=Path),
|
|
19
|
+
default=None,
|
|
20
|
+
help="Output directory. Defaults to <binary_name>_decomp/",
|
|
21
|
+
)
|
|
22
|
+
@click.option(
|
|
23
|
+
"--timeout",
|
|
24
|
+
type=int,
|
|
25
|
+
default=60,
|
|
26
|
+
show_default=True,
|
|
27
|
+
help="Decompilation timeout per function (seconds).",
|
|
28
|
+
)
|
|
29
|
+
@click.option(
|
|
30
|
+
"--ghidra-path",
|
|
31
|
+
type=click.Path(exists=True, file_okay=False, path_type=Path),
|
|
32
|
+
envvar="GHIDRA_INSTALL_DIR",
|
|
33
|
+
default=None,
|
|
34
|
+
help="Path to Ghidra installation. Falls back to GHIDRA_INSTALL_DIR env var.",
|
|
35
|
+
)
|
|
36
|
+
@click.option(
|
|
37
|
+
"--base-addr",
|
|
38
|
+
type=str,
|
|
39
|
+
default=None,
|
|
40
|
+
help="Rebase the binary to this address before analysis (e.g. 0x80000000).",
|
|
41
|
+
)
|
|
42
|
+
@click.option(
|
|
43
|
+
"--entry",
|
|
44
|
+
type=str,
|
|
45
|
+
default=None,
|
|
46
|
+
help="Mark this address as the program entry point and disassemble from it "
|
|
47
|
+
"before analysis (e.g. 0x31000). Useful for raw binaries.",
|
|
48
|
+
)
|
|
49
|
+
@click.option(
|
|
50
|
+
"--language",
|
|
51
|
+
type=str,
|
|
52
|
+
default=None,
|
|
53
|
+
help="Force Ghidra language/processor ID (e.g. ARM:LE:32:v7). "
|
|
54
|
+
"Use when auto-detect fails. See --list-languages.",
|
|
55
|
+
)
|
|
56
|
+
@click.option(
|
|
57
|
+
"--compiler",
|
|
58
|
+
type=str,
|
|
59
|
+
default=None,
|
|
60
|
+
help="Force compiler spec ID (e.g. gcc, default, windows). "
|
|
61
|
+
"Requires --language. See --list-languages.",
|
|
62
|
+
)
|
|
63
|
+
@click.option(
|
|
64
|
+
"--list-languages",
|
|
65
|
+
"list_langs",
|
|
66
|
+
is_flag=True,
|
|
67
|
+
default=False,
|
|
68
|
+
help="List all available Ghidra language IDs and their compiler specs, then exit.",
|
|
69
|
+
)
|
|
70
|
+
def main(
|
|
71
|
+
binary: Path | None,
|
|
72
|
+
output: Path | None,
|
|
73
|
+
timeout: int,
|
|
74
|
+
ghidra_path: Path | None,
|
|
75
|
+
base_addr: str | None,
|
|
76
|
+
entry: str | None,
|
|
77
|
+
language: str | None,
|
|
78
|
+
compiler: str | None,
|
|
79
|
+
list_langs: bool,
|
|
80
|
+
):
|
|
81
|
+
"""Decompile BINARY into a browsable source tree.
|
|
82
|
+
|
|
83
|
+
Produces one .c file per function, plus JSON indexes for strings,
|
|
84
|
+
call graph, imports, and exports.
|
|
85
|
+
"""
|
|
86
|
+
if list_langs:
|
|
87
|
+
list_languages(ghidra_path=ghidra_path)
|
|
88
|
+
return
|
|
89
|
+
|
|
90
|
+
if binary is None:
|
|
91
|
+
raise click.UsageError("Missing argument 'BINARY'.")
|
|
92
|
+
|
|
93
|
+
if compiler is not None and language is None:
|
|
94
|
+
raise click.UsageError("--compiler requires --language.")
|
|
95
|
+
|
|
96
|
+
binary = binary.resolve()
|
|
97
|
+
if output is None:
|
|
98
|
+
output = Path.cwd() / f"{binary.stem}_decomp"
|
|
99
|
+
|
|
100
|
+
output = output.resolve()
|
|
101
|
+
|
|
102
|
+
click.echo(f"Binary: {binary}")
|
|
103
|
+
click.echo(f"Output: {output}")
|
|
104
|
+
if base_addr is not None:
|
|
105
|
+
click.echo(f"Base: {base_addr}")
|
|
106
|
+
if entry is not None:
|
|
107
|
+
click.echo(f"Entry: {entry}")
|
|
108
|
+
if language is not None:
|
|
109
|
+
click.echo(f"Lang: {language}")
|
|
110
|
+
if compiler is not None:
|
|
111
|
+
click.echo(f"CSpec: {compiler}")
|
|
112
|
+
|
|
113
|
+
decompile_binary(
|
|
114
|
+
binary,
|
|
115
|
+
output,
|
|
116
|
+
timeout=timeout,
|
|
117
|
+
ghidra_path=ghidra_path,
|
|
118
|
+
base_addr=base_addr,
|
|
119
|
+
entry=entry,
|
|
120
|
+
language=language,
|
|
121
|
+
compiler=compiler,
|
|
122
|
+
)
|
|
123
|
+
|
|
124
|
+
click.echo(f"\nDone. Output at: {output}")
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
if __name__ == "__main__":
|
|
128
|
+
main()
|