Module refinery.lib.scripts.ps1.deobfuscation.rename
Rename obfuscated variable names to short sequential identifiers.
Expand source code Browse git
"""
Rename obfuscated variable names to short sequential identifiers.
"""
from __future__ import annotations
from refinery.lib.scripts import Node, Transformer
from refinery.lib.scripts.ps1.deobfuscation.constants import (
_PS1_SKIP_VARIABLES,
_assignment_target_variable,
)
from refinery.lib.scripts.ps1.model import (
Ps1AssignmentExpression,
Ps1ForEachLoop,
Ps1ParameterDeclaration,
Ps1ScopeModifier,
Ps1Variable,
)
def _is_obfuscated_name(name: str) -> bool:
return len(name) > 80
def _is_user_variable(var: Ps1Variable) -> bool:
if var.scope != Ps1ScopeModifier.NONE:
return False
return var.name.lower() not in _PS1_SKIP_VARIABLES
class Ps1VariableRenaming(Transformer):
"""
Rename obfuscated variable names to short sequential identifiers (var1, var2, ...).
Only activates when ALL user-defined variables in the script have obfuscated names,
preventing false positives on legitimate scripts.
"""
def visit(self, node: Node):
user_names: set[str] = set()
for n in node.walk():
if isinstance(n, Ps1Variable) and _is_user_variable(n):
user_names.add(n.name.lower())
if not user_names:
return None
if not all(_is_obfuscated_name(name) for name in user_names):
return None
mapping: dict[str, str] = {}
counter = 0
for n in node.walk_in_order():
key = None
if isinstance(n, Ps1AssignmentExpression):
var = _assignment_target_variable(n.target)
if var is not None and _is_user_variable(var):
key = var.name.lower()
elif isinstance(n, Ps1ForEachLoop):
if isinstance(n.variable, Ps1Variable) and _is_user_variable(n.variable):
key = n.variable.name.lower()
elif isinstance(n, Ps1ParameterDeclaration):
if isinstance(n.variable, Ps1Variable) and _is_user_variable(n.variable):
key = n.variable.name.lower()
if key is not None and key not in mapping:
counter += 1
mapping[key] = F'var{counter}'
for name in user_names:
if name not in mapping:
counter += 1
mapping[name] = F'var{counter}'
for n in node.walk():
if isinstance(n, Ps1Variable) and _is_user_variable(n):
key = n.name.lower()
if key in mapping:
n.name = mapping[key]
n.braced = False
self.mark_changed()
return None
Classes
class Ps1VariableRenaming-
Rename obfuscated variable names to short sequential identifiers (var1, var2, …). Only activates when ALL user-defined variables in the script have obfuscated names, preventing false positives on legitimate scripts.
Expand source code Browse git
class Ps1VariableRenaming(Transformer): """ Rename obfuscated variable names to short sequential identifiers (var1, var2, ...). Only activates when ALL user-defined variables in the script have obfuscated names, preventing false positives on legitimate scripts. """ def visit(self, node: Node): user_names: set[str] = set() for n in node.walk(): if isinstance(n, Ps1Variable) and _is_user_variable(n): user_names.add(n.name.lower()) if not user_names: return None if not all(_is_obfuscated_name(name) for name in user_names): return None mapping: dict[str, str] = {} counter = 0 for n in node.walk_in_order(): key = None if isinstance(n, Ps1AssignmentExpression): var = _assignment_target_variable(n.target) if var is not None and _is_user_variable(var): key = var.name.lower() elif isinstance(n, Ps1ForEachLoop): if isinstance(n.variable, Ps1Variable) and _is_user_variable(n.variable): key = n.variable.name.lower() elif isinstance(n, Ps1ParameterDeclaration): if isinstance(n.variable, Ps1Variable) and _is_user_variable(n.variable): key = n.variable.name.lower() if key is not None and key not in mapping: counter += 1 mapping[key] = F'var{counter}' for name in user_names: if name not in mapping: counter += 1 mapping[name] = F'var{counter}' for n in node.walk(): if isinstance(n, Ps1Variable) and _is_user_variable(n): key = n.name.lower() if key in mapping: n.name = mapping[key] n.braced = False self.mark_changed() return NoneAncestors
Methods
def visit(self, node)-
Expand source code Browse git
def visit(self, node: Node): user_names: set[str] = set() for n in node.walk(): if isinstance(n, Ps1Variable) and _is_user_variable(n): user_names.add(n.name.lower()) if not user_names: return None if not all(_is_obfuscated_name(name) for name in user_names): return None mapping: dict[str, str] = {} counter = 0 for n in node.walk_in_order(): key = None if isinstance(n, Ps1AssignmentExpression): var = _assignment_target_variable(n.target) if var is not None and _is_user_variable(var): key = var.name.lower() elif isinstance(n, Ps1ForEachLoop): if isinstance(n.variable, Ps1Variable) and _is_user_variable(n.variable): key = n.variable.name.lower() elif isinstance(n, Ps1ParameterDeclaration): if isinstance(n.variable, Ps1Variable) and _is_user_variable(n.variable): key = n.variable.name.lower() if key is not None and key not in mapping: counter += 1 mapping[key] = F'var{counter}' for name in user_names: if name not in mapping: counter += 1 mapping[name] = F'var{counter}' for n in node.walk(): if isinstance(n, Ps1Variable) and _is_user_variable(n): key = n.name.lower() if key in mapping: n.name = mapping[key] n.braced = False self.mark_changed() return None