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.
Files changed (17) hide show
  1. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/PKG-INFO +7 -2
  2. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/pyproject.toml +9 -2
  3. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/assembly.py +16 -4
  4. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/lifter.py +32 -6
  5. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/plugin.py +2 -0
  6. unidecompiler_plugin_dotnet_cli-0.1.2/src/unidecompiler_plugin_dotnet_cli/simulation.py +53 -0
  7. {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
  8. {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
  9. unidecompiler_plugin_dotnet_cli-0.1.2/src/unidecompiler_plugin_dotnet_cli.egg-info/requires.txt +2 -0
  10. unidecompiler_plugin_dotnet_cli-0.1.0/src/unidecompiler_plugin_dotnet_cli.egg-info/requires.txt +0 -2
  11. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/README.md +0 -0
  12. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/setup.cfg +0 -0
  13. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/__init__.py +0 -0
  14. {unidecompiler_plugin_dotnet_cli-0.1.0 → unidecompiler_plugin_dotnet_cli-0.1.2}/src/unidecompiler_plugin_dotnet_cli/support.py +0 -0
  15. {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
  16. {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
  17. {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.0
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.0
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,11 +4,18 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "unidecompiler-plugin-dotnet-cli"
7
- version = "0.1.0"
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.0,<0.2.0", "dnfile>=0.15,<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 _decode_il(pe, code: bytes) -> tuple[DotNetInstruction, ...]:
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 _dotnet_binary(op: str):
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
- return (Binary(source=source, op=op, semantics="static"),)
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
- return (Binary(source=source, op=op, semantics="static"),)
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.0
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.0
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
@@ -0,0 +1,2 @@
1
+ unidecompiler<0.2.0,>=0.1.2
2
+ dnfile<1,>=0.15
@@ -1,2 +0,0 @@
1
- unidecompiler<0.2.0,>=0.1.0
2
- dnfile<1,>=0.15