From a32e9a7d0bd200e07e1912289dfe683089603bc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20J=2E=20Rodr=C3=ADguez?= Date: Wed, 12 Aug 2026 06:36:13 +0200 Subject: [PATCH] Support hyphenated operations and negative constants in ROPChain parser (#38) REGEX_OP restricted operation names to [a-zA-Z]+ and operands to [a-zA-Z0-9]+, so it rejected operations with a hyphen in the name (e.g. jmp-rel) and a minus sign before a constant operand (e.g. -1), failing with "Unable to parse operation". Allow '-' in both the operation name and the operands. Co-Authored-By: Claude Opus 4.8 --- rop3/ropchain.py | 4 ++-- tests/test_ropchain.py | 29 +++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/rop3/ropchain.py b/rop3/ropchain.py index 890e65d..7d1f601 100644 --- a/rop3/ropchain.py +++ b/rop3/ropchain.py @@ -39,8 +39,8 @@ mov(reg3, reg2) -> OP: mov, DST: reg3, SRC: reg2 ''' REGEX_OP = re.compile( - r'^(?P[a-zA-Z]+)' + \ - r'\((?P[a-zA-Z0-9]+)?(, ?(?P[a-zA-Z0-9]+))?\)' + \ + r'^(?P[a-zA-Z0-9-]+)' + \ + r'\((?P[a-zA-Z0-9-]+)?(, ?(?P[a-zA-Z0-9-]+))?\)' + \ r'(?:\s*;.*)?$' ) COMMENT = re.compile(r'^(?:\s*;.*)?$') diff --git a/tests/test_ropchain.py b/tests/test_ropchain.py index 9d532c8..8dca6af 100644 --- a/tests/test_ropchain.py +++ b/tests/test_ropchain.py @@ -96,6 +96,35 @@ def test_explicit_dst_clears_clobbered_register(x64): ] +def test_parse_negative_constant_source(x64, tmp_path): + ''' + Regression (#38): a minus sign before a constant (e.g. -1) must be parsed + as the source operand. Before the fix REGEX_OP did not allow '-' in an + operand and the line failed with "Unable to parse operation". + ''' + ropfile = tmp_path / 'chain.txt' + ropfile.write_text('sub(rax, -1)\n') + parsed = RopChain(None)._parse_ropfile(str(ropfile)) + assert len(parsed) == 1 + assert parsed[0]['op'] == 'sub' + assert parsed[0]['dst'] == 'rax' + assert parsed[0]['src'] == '-1' + + +def test_parse_hyphenated_operation_name(x64, tmp_path): + ''' + Regression (#38): an operation whose name contains a hyphen (e.g. jmp-rel) + must be parsed. Before the fix REGEX_OP did not allow '-' in the operation + name and the line failed with "Unable to parse operation". jmp-rel is a + composite operation, so it expands into its concrete steps. + ''' + ropfile = tmp_path / 'chain.txt' + ropfile.write_text('jmp-rel(rax)\n') + parsed = RopChain(None)._parse_ropfile(str(ropfile)) + assert parsed + assert all(op['op'] != 'jmp-rel' for op in parsed) + + def test_store_dst_does_not_clear_clobbered_address_register(x64): ''' Regression (#36): a store `st(rbx, rax)` is `mov [rbx], rax`, where rbx is