Module refinery.lib.scripts.au3.deobfuscation.helpers
Shared utilities for AutoIt3 deobfuscation transforms.
Expand source code Browse git
"""
Shared utilities for AutoIt3 deobfuscation transforms.
"""
from __future__ import annotations
from collections.abc import Callable, Sequence
from refinery.lib.scripts import Node, Statement, set_child_list
from refinery.lib.scripts.au3 import ast
from refinery.lib.scripts.au3.model import Au3FunctionDeclaration
#: What a statement-list rebuild asks per statement, given the scope it stands in: `None` keeps
#: the statement, and a sequence is what stands in its place.
Replacement = Callable[[Statement, Au3FunctionDeclaration | None], Sequence[Statement] | None]
def rebuild_statements(
parent: Node,
attr: str,
scope: Au3FunctionDeclaration | None,
replace: Replacement,
) -> bool:
"""
The statement list *attr* of *parent*, which stands in *scope*, rebuilt through *replace*:
a statement it keeps has its nested lists and any function body it holds rebuilt the same
way, and a sequence it answers takes the statement's place unvisited — the statement itself
among them when *replace* edited it where it stands. A list is written back only when one of
its statements changed, and the answer is whether any list was.
"""
surviving: list[Statement] = []
changed = False
for statement in getattr(parent, attr):
replacement = replace(statement, scope)
if replacement is not None:
surviving.extend(replacement)
changed = True
continue
surviving.append(statement)
if rebuild_nested(statement, scope, replace):
changed = True
if changed:
set_child_list(parent, attr, surviving)
return changed
def rebuild_nested(
statement: Statement,
scope: Au3FunctionDeclaration | None,
replace: Replacement,
) -> bool:
"""
Every statement list *statement* holds, rebuilt through *replace* by `rebuild_statements`:
its nested lists in *scope*, and the body of a function declaration in the function's own.
"""
changed = False
for owner, nested in ast.statement_lists(statement):
if rebuild_statements(owner, nested, scope, replace):
changed = True
if isinstance(statement, Au3FunctionDeclaration):
if rebuild_statements(statement, 'body', statement, replace):
changed = True
return changed
Global variables
var Replacement-
What a statement-list rebuild asks per statement, given the scope it stands in:
Nonekeeps the statement, and a sequence is what stands in its place.
Functions
def rebuild_statements(parent, attr, scope, replace)-
The statement list attr of parent, which stands in scope, rebuilt through replace: a statement it keeps has its nested lists and any function body it holds rebuilt the same way, and a sequence it answers takes the statement's place unvisited — the statement itself among them when replace edited it where it stands. A list is written back only when one of its statements changed, and the answer is whether any list was.
Expand source code Browse git
def rebuild_statements( parent: Node, attr: str, scope: Au3FunctionDeclaration | None, replace: Replacement, ) -> bool: """ The statement list *attr* of *parent*, which stands in *scope*, rebuilt through *replace*: a statement it keeps has its nested lists and any function body it holds rebuilt the same way, and a sequence it answers takes the statement's place unvisited — the statement itself among them when *replace* edited it where it stands. A list is written back only when one of its statements changed, and the answer is whether any list was. """ surviving: list[Statement] = [] changed = False for statement in getattr(parent, attr): replacement = replace(statement, scope) if replacement is not None: surviving.extend(replacement) changed = True continue surviving.append(statement) if rebuild_nested(statement, scope, replace): changed = True if changed: set_child_list(parent, attr, surviving) return changed def rebuild_nested(statement, scope, replace)-
Every statement list statement holds, rebuilt through replace by
rebuild_statements(): its nested lists in scope, and the body of a function declaration in the function's own.Expand source code Browse git
def rebuild_nested( statement: Statement, scope: Au3FunctionDeclaration | None, replace: Replacement, ) -> bool: """ Every statement list *statement* holds, rebuilt through *replace* by `rebuild_statements`: its nested lists in *scope*, and the body of a function declaration in the function's own. """ changed = False for owner, nested in ast.statement_lists(statement): if rebuild_statements(owner, nested, scope, replace): changed = True if isinstance(statement, Au3FunctionDeclaration): if rebuild_statements(statement, 'body', statement, replace): changed = True return changed