From dbe41c6c21f96bc13fff3d7fb2b4053a237fafb6 Mon Sep 17 00:00:00 2001 From: doronz88 Date: Wed, 11 Sep 2024 15:41:21 +0300 Subject: [PATCH 1/3] verify-opcode: fix implementation --- fa/commands/verify_opcode.py | 11 ++++++----- fa/utils.py | 6 +++--- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/fa/commands/verify_opcode.py b/fa/commands/verify_opcode.py index 3babdb5..1519be1 100644 --- a/fa/commands/verify_opcode.py +++ b/fa/commands/verify_opcode.py @@ -1,5 +1,5 @@ from argparse import RawTextHelpFormatter -from typing import Generator, Iterable +from typing import Generator, List, Union from fa import context, utils @@ -41,10 +41,11 @@ def get_parser(): @context.ida_context @utils.yield_unique -def verify_opcode(addresses: Iterable[int], mnem: str, regs_description) -> Generator[int, None, None]: +def verify_opcode(addresses: List[int], mnems: Union[str, List[str]], regs_description) \ + -> Generator[int, None, None]: for ea in addresses: current_mnem = idc.print_insn_mnem(ea).lower() - if current_mnem == mnem: + if current_mnem in mnems: if not regs_description: yield ea continue @@ -57,6 +58,6 @@ def verify_opcode(addresses: Iterable[int], mnem: str, regs_description) -> Gene yield ea -def run(segments, args, addresses: Iterable[int], interpreter=None, **kwargs): - regs_description = utils.create_create_regs_description(args) +def run(segments, args, addresses: List[int], interpreter=None, **kwargs) -> List[int]: + regs_description = utils.create_regs_description_from_args(args) return list(verify_opcode(addresses, args.mnem, regs_description)) diff --git a/fa/utils.py b/fa/utils.py index 5b9b61d..2fd7949 100644 --- a/fa/utils.py +++ b/fa/utils.py @@ -122,7 +122,7 @@ def find_or_create_struct(name): return sid -def create_create_regs_description(*regs) -> List[Tuple[int, str]]: +def create_regs_description(*regs) -> List[Tuple[int, str]]: result = [] for i, r in enumerate(regs): if r is not None: @@ -142,7 +142,7 @@ def create_regs_description_from_args(*args) -> List[Tuple[int, str]]: if v is not None: v = [i.strip() for i in v.split(',')] regs.append(v) - return create_create_regs_description(*regs) + return create_regs_description(*regs) def size_of_operand(op: 'ida_ua.op_t') -> int: @@ -267,7 +267,7 @@ def compare_arm_coprocessor_operand(ea: int, index: int, values: Iterable[str]) operand = insn.ops[1] if index == 2: - op_val = operand.value + op_val = operand.reg return compare_reg_value(op_val, values) if index == 3: From 3c83a0587519b483861b8ec76c2517e410a893e5 Mon Sep 17 00:00:00 2001 From: doronz88 Date: Wed, 11 Sep 2024 15:47:44 +0300 Subject: [PATCH 2/3] set_name: restore old behavior --- fa/commands/set_name.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/fa/commands/set_name.py b/fa/commands/set_name.py index 69e32ab..5136400 100644 --- a/fa/commands/set_name.py +++ b/fa/commands/set_name.py @@ -1,13 +1,9 @@ from typing import List -from fa.commands.locate import locate_single -from fa.fa_types import IDA_MODULE from fa.utils import ArgumentParserNoExit try: import ida_bytes - import ida_name - from ida_idaapi import BADADDR except ImportError: pass @@ -25,16 +21,6 @@ def is_address_nameless(addr: int) -> bool: def set_name(addresses: List[int], name: str, interpreter) -> List[int]: for ea in addresses: - if IDA_MODULE: - current_name = ida_name.get_ea_name(ea) - remote_addr = locate_single(current_name) - if current_name == name: - continue - - # we want to avoid accidental renames from bad sigs, therefore we assert the following: - assert remote_addr == BADADDR, f'Rename failed, name already used at {hex(remote_addr)} ({hex(ea)})' - assert is_address_nameless(ea), f'Rename failed, address has a different name {current_name} ({hex(ea)})' - interpreter.set_symbol(name, ea) return addresses From b800eaa1978612d9b7b75934832e4f23d54b291b Mon Sep 17 00:00:00 2001 From: doronz88 Date: Wed, 11 Sep 2024 15:52:15 +0300 Subject: [PATCH 3/3] commands: fix if-not --- commands.md | 42 +++++++++---------- fa/commands/{if-not.py => if_not.py} | 0 .../sublime/sig.sublime-completions | 10 ++--- 3 files changed, 25 insertions(+), 27 deletions(-) rename fa/commands/{if-not.py => if_not.py} (100%) diff --git a/commands.md b/commands.md index 0e61a5c..d5dbd80 100644 --- a/commands.md +++ b/commands.md @@ -17,8 +17,8 @@ Below is the list of available commands: - [function-lines](#function-lines) - [function-start](#function-start) - [goto-ref](#goto-ref) -- [if-not](#if-not) - [if](#if) +- [if-not](#if-not) - [intersect](#intersect) - [keystone-find-opcodes](#keystone-find-opcodes) - [keystone-verify-opcodes](#keystone-verify-opcodes) @@ -182,9 +182,8 @@ options: ``` usage: deref-data [-h] -l LEN -Dereference pointer as integer data type. Note that the data is assumed to be stored in little endian format. Example #1: -0x00000000: LDR R1, [SP, #0x34] results = [0] -> deref-data -l 4 results = [0xe5d1034] Example #2: 0x00000000: LDR R1, [SP, #0x34] -results = [0] -> deref-data -l 2 results = [0x1034] +Dereference pointer as integer data type. Note that the data is assumed to be stored in little endian format. Example #1: 0x00000000: LDR R1, [SP, #0x34] results = [0] -> deref-data -l 4 results = [0xe5d1034] Example #2: 0x00000000: LDR R1, [SP, #0x34] results = [0] +-> deref-data -l 2 results = [0x1034] options: -h, --help show this help message and exit @@ -374,56 +373,56 @@ options: --code include code references --data include data references ``` -## if-not +## if ``` -usage: if-not [-h] cond label +usage: if [-h] cond label -perform an 'if not' statement to create conditional branches +perform an 'if' statement to create conditional branches using an FA command EXAMPLE: results = [0, 4, 8] - -> if-not 'verify-single' a_is_single_label + -> if 'verify-single' a_is_single_label - set-name a_is_single + set-name a_isnt_single b end - label a_is_not_single_label - set-name a_is_not_single + label a_is_single_label + set-name a_is_single label end positional arguments: cond condition as an FA command - label label to jump to if condition is false + label label to jump to if condition is true options: -h, --help show this help message and exit ``` -## if +## if-not ``` -usage: if [-h] cond label +usage: if-not [-h] cond label -perform an 'if' statement to create conditional branches +perform an 'if not' statement to create conditional branches using an FA command EXAMPLE: results = [0, 4, 8] - -> if 'verify-single' a_is_single_label + -> if-not 'verify-single' a_is_single_label - set-name a_isnt_single + set-name a_is_single b end - label a_is_single_label - set-name a_is_single + label a_is_not_single_label + set-name a_is_not_single label end positional arguments: cond condition as an FA command - label label to jump to if condition is true + label label to jump to if condition is false options: -h, --help show this help message and exit @@ -637,8 +636,7 @@ options: ``` ## next-instruction ``` -usage: next-instruction [-h] [--limit LIMIT] [--back] [--op0 OP0] [--op1 OP1] [--op2 OP2] [--op3 OP3] [--op4 OP4] [--op5 OP5] - mnem [mnem ...] +usage: next-instruction [-h] [--limit LIMIT] [--back] [--op0 OP0] [--op1 OP1] [--op2 OP2] [--op3 OP3] [--op4 OP4] [--op5 OP5] mnem [mnem ...] Map the resultset to the next instruction of a given pattern. The instruction is searched for linearly. diff --git a/fa/commands/if-not.py b/fa/commands/if_not.py similarity index 100% rename from fa/commands/if-not.py rename to fa/commands/if_not.py diff --git a/ide-completions/sublime/sig.sublime-completions b/ide-completions/sublime/sig.sublime-completions index 63274bf..e2e578b 100644 --- a/ide-completions/sublime/sig.sublime-completions +++ b/ide-completions/sublime/sig.sublime-completions @@ -82,14 +82,14 @@ "contents": "goto-ref --code --data" }, { - "trigger": "if-not", + "trigger": "if", "kind": "snippet", - "contents": "if-not ${1:cond} ${2:label}" + "contents": "if ${1:cond} ${2:label}" }, { - "trigger": "if", + "trigger": "if-not", "kind": "snippet", - "contents": "if ${1:cond} ${2:label}" + "contents": "if-not ${1:cond} ${2:label}" }, { "trigger": "intersect", @@ -159,7 +159,7 @@ { "trigger": "next-instruction", "kind": "snippet", - "contents": "next-instruction --limit ${1:LIMIT} --back --op0 ${2:OP0} --op1 ${3:OP1} --op2 ${4:OP2} --op3 ${5:OP3} --op4 ${6:OP4} --op5 ${7:OP5} ${8:mnem} ${9:mnem} ..." + "contents": "next-instruction --limit ${1:LIMIT} --back --op0 ${2:OP0} --op1 ${3:OP1} --op2 ${4:OP2} --op3 ${5:OP3} --op4 ${6:OP4} --op5 ${7:OP5} ${8:mnem} ${9:mnem} ..." }, { "trigger": "offset",