unidecompiler-plugin-dotnet-cli 0.1.0__tar.gz → 0.1.2__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.
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/PKG-INFO +7 -2
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/pyproject.toml +9 -2
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/assembly.py +16 -4
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/lifter.py +32 -6
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/plugin.py +2 -0
- unidecompiler_plugin_dotnet_cli-0.1.2/src/unidecompiler_plugin_dotnet_cli/simulation.py +53 -0
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli.egg-info/PKG-INFO +7 -2
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli.egg-info/SOURCES.txt +1 -0
- unidecompiler_plugin_dotnet_cli-0.1.2/src/unidecompiler_plugin_dotnet_cli.egg-info/requires.txt +2 -0
- unidecompiler_plugin_dotnet_cli-0.1.0/src/unidecompiler_plugin_dotnet_cli.egg-info/requires.txt +0 -2
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/README.md +0 -0
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/setup.cfg +0 -0
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/__init__.py +0 -0
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/support.py +0 -0
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli.egg-info/dependency_links.txt +0 -0
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli.egg-info/entry_points.txt +0 -0
- {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli.egg-info/top_level.txt +0 -0
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unidecompiler-plugin-dotnet-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: .NET CLI assembly frontend plugin for unidecompiler
|
|
5
|
+
Author-email: Wker <1670133844@qq.com>
|
|
6
|
+
License-Expression: AGPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://github.com/Wker666/unidecompiler
|
|
8
|
+
Project-URL: Repository, https://github.com/Wker666/unidecompiler
|
|
9
|
+
Project-URL: Issues, https://github.com/Wker666/unidecompiler/issues
|
|
5
10
|
Requires-Python: >=3.11
|
|
6
11
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: unidecompiler<0.2.0,>=0.1.
|
|
12
|
+
Requires-Dist: unidecompiler<0.2.0,>=0.1.2
|
|
8
13
|
Requires-Dist: dnfile<1,>=0.15
|
|
9
14
|
|
|
10
15
|
# unidecompiler-plugin-dotnet-cli
|
{unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/pyproject.toml
RENAMED
|
@@ -4,11 +4,18 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "unidecompiler-plugin-dotnet-cli"
|
|
7
|
-
version = "0.1.
|
|
7
|
+
version = "0.1.2"
|
|
8
8
|
description = ".NET CLI assembly frontend plugin for unidecompiler"
|
|
9
9
|
readme = "README.md"
|
|
10
|
+
license = "AGPL-3.0-or-later"
|
|
11
|
+
authors = [{ name = "Wker", email = "1670133844@qq.com" }]
|
|
10
12
|
requires-python = ">=3.11"
|
|
11
|
-
dependencies = ["unidecompiler>=0.1.
|
|
13
|
+
dependencies = ["unidecompiler>=0.1.2,<0.2.0", "dnfile>=0.15,<1"]
|
|
14
|
+
|
|
15
|
+
[project.urls]
|
|
16
|
+
Homepage = "https://github.com/Wker666/unidecompiler"
|
|
17
|
+
Repository = "https://github.com/Wker666/unidecompiler"
|
|
18
|
+
Issues = "https://github.com/Wker666/unidecompiler/issues"
|
|
12
19
|
|
|
13
20
|
[project.entry-points."unidecompiler.frontends"]
|
|
14
21
|
dotnet-cli = "unidecompiler_plugin_dotnet_cli.plugin:DotNetFrontendPlugin"
|
|
@@ -26,6 +26,8 @@ class DotNetInstruction:
|
|
|
26
26
|
arg_count: int | None = None
|
|
27
27
|
returns_void: bool | None = None
|
|
28
28
|
is_static: bool | None = None
|
|
29
|
+
artifact_offset: int | None = None
|
|
30
|
+
size: int | None = None
|
|
29
31
|
|
|
30
32
|
|
|
31
33
|
@dataclass(frozen=True)
|
|
@@ -132,7 +134,7 @@ def _method_listing(pe, row_index: int, row) -> DotNetMethodListing:
|
|
|
132
134
|
param_count=_signature_param_count(row.Signature),
|
|
133
135
|
max_stack=None if body is None else body.max_stack,
|
|
134
136
|
code_size=0 if body is None else len(body.code),
|
|
135
|
-
instructions=() if body is None else _decode_il(pe, body.code),
|
|
137
|
+
instructions=() if body is None else _decode_il(pe, body.code, body.artifact_offset),
|
|
136
138
|
)
|
|
137
139
|
|
|
138
140
|
|
|
@@ -140,6 +142,7 @@ def _method_listing(pe, row_index: int, row) -> DotNetMethodListing:
|
|
|
140
142
|
class _MethodBody:
|
|
141
143
|
max_stack: int
|
|
142
144
|
code: bytes
|
|
145
|
+
artifact_offset: int | None
|
|
143
146
|
|
|
144
147
|
|
|
145
148
|
def _read_method_body(pe, rva: int) -> _MethodBody | None:
|
|
@@ -150,7 +153,7 @@ def _read_method_body(pe, rva: int) -> _MethodBody | None:
|
|
|
150
153
|
kind = first & 0x3
|
|
151
154
|
if kind == 0x2:
|
|
152
155
|
code_size = first >> 2
|
|
153
|
-
return _MethodBody(max_stack=8, code=pe.get_data(rva + 1, code_size))
|
|
156
|
+
return _MethodBody(max_stack=8, code=pe.get_data(rva + 1, code_size), artifact_offset=_artifact_offset(pe, rva + 1))
|
|
154
157
|
if kind == 0x3:
|
|
155
158
|
header = pe.get_data(rva, 12)
|
|
156
159
|
if len(header) < 12:
|
|
@@ -159,7 +162,7 @@ def _read_method_body(pe, rva: int) -> _MethodBody | None:
|
|
|
159
162
|
header_size = (_flags_size >> 12) * 4
|
|
160
163
|
if header_size < 12:
|
|
161
164
|
return None
|
|
162
|
-
return _MethodBody(max_stack=max_stack, code=pe.get_data(rva + header_size, code_size))
|
|
165
|
+
return _MethodBody(max_stack=max_stack, code=pe.get_data(rva + header_size, code_size), artifact_offset=_artifact_offset(pe, rva + header_size))
|
|
163
166
|
return None
|
|
164
167
|
|
|
165
168
|
|
|
@@ -428,7 +431,14 @@ _TWO_BYTE_OPCODES = {
|
|
|
428
431
|
}
|
|
429
432
|
|
|
430
433
|
|
|
431
|
-
def
|
|
434
|
+
def _artifact_offset(pe, rva: int) -> int | None:
|
|
435
|
+
try:
|
|
436
|
+
return int(pe.get_offset_from_rva(rva))
|
|
437
|
+
except Exception:
|
|
438
|
+
return None
|
|
439
|
+
|
|
440
|
+
|
|
441
|
+
def _decode_il(pe, code: bytes, artifact_offset: int | None = None) -> tuple[DotNetInstruction, ...]:
|
|
432
442
|
instructions: list[DotNetInstruction] = []
|
|
433
443
|
offset = 0
|
|
434
444
|
while offset < len(code):
|
|
@@ -454,6 +464,8 @@ def _decode_il(pe, code: bytes) -> tuple[DotNetInstruction, ...]:
|
|
|
454
464
|
arg_count=operand.arg_count,
|
|
455
465
|
returns_void=operand.returns_void,
|
|
456
466
|
is_static=operand.is_static,
|
|
467
|
+
artifact_offset=None if artifact_offset is None else artifact_offset + start,
|
|
468
|
+
size=offset - start,
|
|
457
469
|
)
|
|
458
470
|
)
|
|
459
471
|
return tuple(instructions)
|
|
@@ -30,6 +30,7 @@ from unidecompiler.core.vm_function import VMFunctionSpec, lift_steps, lift_vm_s
|
|
|
30
30
|
from unidecompiler.core.vm_hints import VMHint
|
|
31
31
|
from unidecompiler.core.vm_module import assemble_vm_module
|
|
32
32
|
from unidecompiler.core.vm_operands import VMDecodedInstruction, VMOperand
|
|
33
|
+
from unidecompiler.provenance import ByteRange
|
|
33
34
|
from unidecompiler.core.vm_region import (
|
|
34
35
|
VMLinearState,
|
|
35
36
|
VMRegionOpcodeClasses,
|
|
@@ -199,16 +200,40 @@ def _dotnet_unknown_opcode_effect(
|
|
|
199
200
|
return (UnknownOpcode(source=source, opcode=instruction.opcode, raw=_dotnet_raw_instruction_line(instruction)),)
|
|
200
201
|
|
|
201
202
|
|
|
202
|
-
def
|
|
203
|
+
def _dotnet_numeric_facts(opcode: str) -> tuple[str, int | None]:
|
|
204
|
+
if opcode.endswith(".un") or opcode == "shr.un":
|
|
205
|
+
return "unsigned", 32
|
|
206
|
+
return "default", None
|
|
207
|
+
|
|
208
|
+
|
|
209
|
+
def _dotnet_binary(opcode: str, op: str):
|
|
203
210
|
def factory(_method: DotNetMethodListing, _instruction: DotNetInstruction, source: SourceRef) -> tuple:
|
|
204
|
-
|
|
211
|
+
numeric_domain, bit_width = _dotnet_numeric_facts(opcode)
|
|
212
|
+
return (
|
|
213
|
+
Binary(
|
|
214
|
+
source=source,
|
|
215
|
+
op=op,
|
|
216
|
+
semantics="static",
|
|
217
|
+
numeric_domain=numeric_domain,
|
|
218
|
+
bit_width=bit_width,
|
|
219
|
+
),
|
|
220
|
+
)
|
|
205
221
|
|
|
206
222
|
return factory
|
|
207
223
|
|
|
208
224
|
|
|
209
|
-
def _dotnet_compare(op: str):
|
|
225
|
+
def _dotnet_compare(opcode: str, op: str):
|
|
210
226
|
def factory(_method: DotNetMethodListing, _instruction: DotNetInstruction, source: SourceRef) -> tuple:
|
|
211
|
-
|
|
227
|
+
numeric_domain, bit_width = _dotnet_numeric_facts(opcode)
|
|
228
|
+
return (
|
|
229
|
+
Binary(
|
|
230
|
+
source=source,
|
|
231
|
+
op=op,
|
|
232
|
+
semantics="static",
|
|
233
|
+
numeric_domain=numeric_domain,
|
|
234
|
+
bit_width=bit_width,
|
|
235
|
+
),
|
|
236
|
+
)
|
|
212
237
|
|
|
213
238
|
return factory
|
|
214
239
|
|
|
@@ -304,8 +329,8 @@ DOTNET_EFFECT_TABLE = VMEffectTable(
|
|
|
304
329
|
opcode_attr="opcode",
|
|
305
330
|
ignored=frozenset(IGNORED_OPS),
|
|
306
331
|
exact={
|
|
307
|
-
**{opcode: _dotnet_binary(op) for opcode, op in BINARY_OPS.items()},
|
|
308
|
-
**{opcode: _dotnet_compare(op) for opcode, op in COMPARE_OPS.items()},
|
|
332
|
+
**{opcode: _dotnet_binary(opcode, op) for opcode, op in BINARY_OPS.items()},
|
|
333
|
+
**{opcode: _dotnet_compare(opcode, op) for opcode, op in COMPARE_OPS.items()},
|
|
309
334
|
"ldnull": lambda _method, _instruction, source: (Push(source=source, value=Const(value=None, source=source)),),
|
|
310
335
|
"dup": lambda _method, instruction, source: (DuplicateTop(source=source, materialized_name=f"local_stack_{instruction.offset}"),),
|
|
311
336
|
"pop": lambda _method, _instruction, source: (Pop(source=source, count=1, emit_calls=True),),
|
|
@@ -527,6 +552,7 @@ def _dotnet_decoded_instruction(instruction: DotNetInstruction, source: SourceRe
|
|
|
527
552
|
source=source,
|
|
528
553
|
operands=operands,
|
|
529
554
|
raw=_dotnet_raw_instruction_line(instruction),
|
|
555
|
+
artifact_range=(None if instruction.artifact_offset is None or instruction.size is None else ByteRange(instruction.artifact_offset, instruction.size)),
|
|
530
556
|
)
|
|
531
557
|
|
|
532
558
|
|
|
@@ -8,6 +8,7 @@ from unidecompiler_plugin_dotnet_cli.assembly import (
|
|
|
8
8
|
looks_like_dotnet,
|
|
9
9
|
)
|
|
10
10
|
from unidecompiler_plugin_dotnet_cli.lifter import lift_dotnet_assembly
|
|
11
|
+
from unidecompiler_plugin_dotnet_cli.simulation import DotNetSimulationAdapter
|
|
11
12
|
from unidecompiler_plugin_dotnet_cli.support import DOTNET_CLI_VERSION_SUPPORT
|
|
12
13
|
|
|
13
14
|
|
|
@@ -16,6 +17,7 @@ class DotNetFrontendPlugin:
|
|
|
16
17
|
display_name = ".NET CLI assembly"
|
|
17
18
|
supported_inputs = (".dll", ".exe")
|
|
18
19
|
version_support = DOTNET_CLI_VERSION_SUPPORT
|
|
20
|
+
simulation_adapter = DotNetSimulationAdapter
|
|
19
21
|
|
|
20
22
|
def __init__(self, decoder: DotNetAssemblyDecoder | None = None) -> None:
|
|
21
23
|
self.decoder = decoder or DnfileAssemblyDecoder()
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Optional .NET method lookup for the decoupled generic IR simulator."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
class DotNetSimulationAdapter:
|
|
7
|
+
frontend_id = "dotnet-cli"
|
|
8
|
+
|
|
9
|
+
def resolve_function(self, query, decoded_module, lifted_module):
|
|
10
|
+
from unidecompiler_simulator import NotHandled, ResolvedFunction
|
|
11
|
+
|
|
12
|
+
if not isinstance(query, str):
|
|
13
|
+
return NotHandled
|
|
14
|
+
method_name = query.rsplit(".", 1)[-1]
|
|
15
|
+
context = self._function_context(lifted_module.functions)
|
|
16
|
+
matches = context.get(method_name, ())
|
|
17
|
+
if len(matches) != 1:
|
|
18
|
+
return NotHandled
|
|
19
|
+
return ResolvedFunction(matches[0], context=context, identifier=query)
|
|
20
|
+
|
|
21
|
+
def resolve_global(self, name, context):
|
|
22
|
+
from unidecompiler_simulator import NotHandled, ResolvedFunction
|
|
23
|
+
|
|
24
|
+
if not isinstance(context, dict):
|
|
25
|
+
return NotHandled
|
|
26
|
+
matches = context.get(name.rsplit(".", 1)[-1], ())
|
|
27
|
+
if len(matches) != 1:
|
|
28
|
+
return NotHandled
|
|
29
|
+
return ResolvedFunction(matches[0], context=context, identifier=name)
|
|
30
|
+
|
|
31
|
+
def list_simulation_targets(self, decoded_module, lifted_module):
|
|
32
|
+
from unidecompiler_simulator import SimulationTargetCandidate
|
|
33
|
+
|
|
34
|
+
context = self._function_context(lifted_module.functions)
|
|
35
|
+
return tuple(
|
|
36
|
+
SimulationTargetCandidate(name, name)
|
|
37
|
+
for name, matches in context.items()
|
|
38
|
+
if len(matches) == 1
|
|
39
|
+
)
|
|
40
|
+
|
|
41
|
+
def get_attr(self, obj, attr, context):
|
|
42
|
+
from unidecompiler_simulator import NotHandled
|
|
43
|
+
|
|
44
|
+
if attr == "length" and isinstance(obj, (list, tuple, str, bytes)):
|
|
45
|
+
return len(obj)
|
|
46
|
+
return NotHandled
|
|
47
|
+
|
|
48
|
+
@staticmethod
|
|
49
|
+
def _function_context(functions):
|
|
50
|
+
context = {}
|
|
51
|
+
for function in functions:
|
|
52
|
+
context.setdefault(function.name, []).append(function)
|
|
53
|
+
return {name: tuple(matches) for name, matches in context.items()}
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: unidecompiler-plugin-dotnet-cli
|
|
3
|
-
Version: 0.1.
|
|
3
|
+
Version: 0.1.2
|
|
4
4
|
Summary: .NET CLI assembly frontend plugin for unidecompiler
|
|
5
|
+
Author-email: Wker <1670133844@qq.com>
|
|
6
|
+
License-Expression: AGPL-3.0-or-later
|
|
7
|
+
Project-URL: Homepage, https://github.com/Wker666/unidecompiler
|
|
8
|
+
Project-URL: Repository, https://github.com/Wker666/unidecompiler
|
|
9
|
+
Project-URL: Issues, https://github.com/Wker666/unidecompiler/issues
|
|
5
10
|
Requires-Python: >=3.11
|
|
6
11
|
Description-Content-Type: text/markdown
|
|
7
|
-
Requires-Dist: unidecompiler<0.2.0,>=0.1.
|
|
12
|
+
Requires-Dist: unidecompiler<0.2.0,>=0.1.2
|
|
8
13
|
Requires-Dist: dnfile<1,>=0.15
|
|
9
14
|
|
|
10
15
|
# unidecompiler-plugin-dotnet-cli
|
|
@@ -4,6 +4,7 @@ src/unidecompiler_plugin_dotnet_cli/__init__.py
|
|
|
4
4
|
src/unidecompiler_plugin_dotnet_cli/assembly.py
|
|
5
5
|
src/unidecompiler_plugin_dotnet_cli/lifter.py
|
|
6
6
|
src/unidecompiler_plugin_dotnet_cli/plugin.py
|
|
7
|
+
src/unidecompiler_plugin_dotnet_cli/simulation.py
|
|
7
8
|
src/unidecompiler_plugin_dotnet_cli/support.py
|
|
8
9
|
src/unidecompiler_plugin_dotnet_cli.egg-info/PKG-INFO
|
|
9
10
|
src/unidecompiler_plugin_dotnet_cli.egg-info/SOURCES.txt
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|