From 35a67869be24c1dd0b423f452d60703fc788669e Mon Sep 17 00:00:00 2001 From: Melissa Eckardt Date: Tue, 16 Dec 2025 11:00:21 +0100 Subject: [PATCH 1/2] Add missing __init__.py to tests dir --- tests/__init__.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 tests/__init__.py diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 From df1b5e34fba6720df999a59eb4b00b240b7ed56c Mon Sep 17 00:00:00 2001 From: Melissa Eckardt Date: Tue, 16 Dec 2025 11:01:03 +0100 Subject: [PATCH 2/2] Add support for percent vars inside delayed expansion --- batch_deobfuscator/batch_interpreter.py | 25 ++++++++++++++++--------- tests/test_unittests.py | 1 + 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/batch_deobfuscator/batch_interpreter.py b/batch_deobfuscator/batch_interpreter.py index 89a4df8..d67429a 100644 --- a/batch_deobfuscator/batch_interpreter.py +++ b/batch_deobfuscator/batch_interpreter.py @@ -980,7 +980,7 @@ def normalize_command(self, command): stack.append(state) state = "var_s" elif char == "!": - variable_start = len(normalized_com) + variable_start_ex = len(normalized_com) normalized_com += char stack.append(state) state = "var_s_2" @@ -996,7 +996,7 @@ def normalize_command(self, command): stack.append("str_s") state = "var_s" # seen % elif char == "!": - variable_start = len(normalized_com) + variable_start_ex = len(normalized_com) normalized_com += char stack.append("str_s") state = "var_s_2" # seen ! @@ -1043,8 +1043,8 @@ def normalize_command(self, command): elif state == "var_s_2": if char == "!" and normalized_com[-1] != char: normalized_com += char - value = self.get_value(normalized_com[variable_start:]) - normalized_com = normalized_com[:variable_start] + value = self.get_value(normalized_com[variable_start_ex:]) + normalized_com = normalized_com[:variable_start_ex] if len(normalized_com) == 0: traits["start_with_var"] = True normalized_com += self.normalize_command(value) @@ -1052,6 +1052,11 @@ def normalize_command(self, command): state = stack.pop() elif char == "!": normalized_com += char + elif char == "%": + variable_start = len(normalized_com) + normalized_com += char + state = "var_s" + stack.append("var_s_2") elif char == "^": state = "escape" stack.append("var_s_2") @@ -1077,20 +1082,22 @@ def normalize_command(self, command): state = "var_s" elif char == "!": if state == "var_s_2": - value = self.get_value(normalized_com[variable_start:]) - normalized_com = normalized_com[:variable_start] + value = self.get_value(normalized_com[variable_start_ex:]) + normalized_com = normalized_com[:variable_start_ex] if len(normalized_com) == 0: traits["start_with_var"] = True normalized_com += self.normalize_command(value) traits["var_used"] += 1 state = stack.pop() else: - variable_start = len(normalized_com) - 1 + variable_start_ex = len(normalized_com) - 1 stack.append(state) state = "var_s_2" - if state in ["var_s", "var_s_2"]: - normalized_com = normalized_com[:variable_start] + normalized_com[variable_start + 1 :] + if state == "var_s": + normalized_com = normalized_com[:variable_start] + normalized_com[variable_start + 1:] + elif state == "var_s_2": + normalized_com = normalized_com[:variable_start_ex] + normalized_com[variable_start_ex + 1:] elif state == "escape": normalized_com += "^" diff --git a/tests/test_unittests.py b/tests/test_unittests.py index 07cfdfc..8ee2d62 100644 --- a/tests/test_unittests.py +++ b/tests/test_unittests.py @@ -234,6 +234,7 @@ def test_simple_set_a(): ("set EXP=43", "echo ^!EX^P!", "echo 43"), # ("set EXP=43", "echo ^%EXP^%", "echo 43"), # That's wrong... it actually prints the next line. Ignoring. ("set EXP=43", "echo ^!EXP^!", "echo 43"), + ("set EXP=43", "echo !EX%nothing%P!", "echo 43"), ], ) def test_set_command(var, echo, result):