forked from fkie-cad/dewolf
-
Notifications
You must be signed in to change notification settings - Fork 0
/
decompile.py
executable file
·80 lines (66 loc) · 3.26 KB
/
decompile.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
#!/usr/bin/env python3
"""Main decompiler Interface."""
from __future__ import annotations
from typing import Dict, List, Optional, Tuple
from decompiler.backend.codegenerator import CodeGenerator
from decompiler.frontend import BinaryninjaFrontend, Frontend
from decompiler.pipeline.pipeline import DecompilerPipeline
from decompiler.task import DecompilerTask
from decompiler.util.options import Options
class Decompiler:
"""Main Interface to the decompiler."""
def __init__(self, frontend: Frontend):
"""
Initialize a new decompiler on the given view.
frontend -- The disassembler frontend to be used.
"""
self._frontend = frontend
self._backend = CodeGenerator()
@classmethod
def create_options(cls, extra_options: Optional[Dict] = None):
"""Create a dictionary holding user defined settings/options from both command line and default config files"""
# First retrieve default options
all_options = Options.load_default_options()
# Now retrieve the extra options passed via commandline
all_options.add_cmdline_options(extra_options)
return all_options
@classmethod
def from_path(cls, path: str, options: Optional[Options] = None, frontend: Frontend = BinaryninjaFrontend) -> Decompiler:
"""Create a decompiler instance by invoking the given frontend on the given sample."""
if not options:
options = Decompiler.create_options()
return cls(frontend.from_path(path, options))
@classmethod
def from_raw(cls, data, frontend: Frontend = BinaryninjaFrontend) -> Decompiler:
"""Create a decompiler instance from existing frontend instance (e.g. a binaryninja view)."""
return cls(frontend.from_raw(data))
def decompile(self, function: str, task_options: Optional[Options] = None) -> DecompilerTask:
"""Decompile the target function."""
# Sanity check to ensure task_options is populated
if task_options is None:
task_options = Decompiler.create_options()
# Start decompiling
pipeline = DecompilerPipeline.from_strings(task_options.getlist("pipeline.cfg_stages"), task_options.getlist("pipeline.ast_stages"))
task = self._frontend.create_task(function, task_options)
pipeline.run(task)
task.code = self._backend.generate([task])
return task
def decompile_all(self, task_options: Optional[Options] = None) -> str:
"""Decompile all functions in the binary"""
tasks = list()
# Sanity check to ensure task_options is populated
if task_options is None:
task_options = Decompiler.create_options()
# Start decompiling
pipeline = DecompilerPipeline.from_strings(task_options.getlist("pipeline.cfg_stages"), task_options.getlist("pipeline.ast_stages"))
functions = self._frontend.get_all_function_names()
for function in functions:
task = self._frontend.create_task(function, task_options)
pipeline.run(task)
tasks.append(task)
code = self._backend.generate(tasks)
return code
"""When invoked as a script, run the commandline interface."""
if __name__ == "__main__":
from decompiler.util.commandline import main
main(Decompiler)